1/*! DataTables 1.10.21 2 * ©2008-2020 SpryMedia Ltd - datatables.net/license 3 */ 4 5/** 6 * @summary DataTables 7 * @description Paginate, search and order HTML tables 8 * @version 1.10.21 9 * @file jquery.dataTables.js 10 * @author SpryMedia Ltd 11 * @contact www.datatables.net 12 * @copyright Copyright 2008-2020 SpryMedia Ltd. 13 * 14 * This source file is free software, available under the following license: 15 * MIT license - http://datatables.net/license 16 * 17 * This source file is distributed in the hope that it will be useful, but 18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 19 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. 20 * 21 * For details please refer to: http://www.datatables.net 22 */ 23 24/*jslint evil: true, undef: true, browser: true */ 25/*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/ 26 27(function( factory ) { 28 "use strict"; 29 30 if ( typeof define === 'function' && define.amd ) { 31 // AMD 32 define( ['jquery'], function ( $ ) { 33 return factory( $, window, document ); 34 } ); 35 } 36 else if ( typeof exports === 'object' ) { 37 // CommonJS 38 module.exports = function (root, $) { 39 if ( ! root ) { 40 // CommonJS environments without a window global must pass a 41 // root. This will give an error otherwise 42 root = window; 43 } 44 45 if ( ! $ ) { 46 $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window 47 require('jquery') : 48 require('jquery')( root ); 49 } 50 51 return factory( $, root, root.document ); 52 }; 53 } 54 else { 55 // Browser 56 factory( jQuery, window, document ); 57 } 58} 59(function( $, window, document, undefined ) { 60 "use strict"; 61 62 /** 63 * DataTables is a plug-in for the jQuery Javascript library. It is a highly 64 * flexible tool, based upon the foundations of progressive enhancement, 65 * which will add advanced interaction controls to any HTML table. For a 66 * full list of features please refer to 67 * [DataTables.net](href="http://datatables.net). 68 * 69 * Note that the `DataTable` object is not a global variable but is aliased 70 * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may 71 * be accessed. 72 * 73 * @class 74 * @param {object} [init={}] Configuration object for DataTables. Options 75 * are defined by {@link DataTable.defaults} 76 * @requires jQuery 1.7+ 77 * 78 * @example 79 * // Basic initialisation 80 * $(document).ready( function { 81 * $('#example').dataTable(); 82 * } ); 83 * 84 * @example 85 * // Initialisation with configuration options - in this case, disable 86 * // pagination and sorting. 87 * $(document).ready( function { 88 * $('#example').dataTable( { 89 * "paginate": false, 90 * "sort": false 91 * } ); 92 * } ); 93 */ 94 var DataTable = function ( options ) 95 {
vendor: 6,636 bytes, lines 95-254
95 96 /** 97 * Perform a jQuery selector action on the table's TR elements (from the tbody) and 98 * return the resulting jQuery object. 99 * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on 100 * @param {object} [oOpts] Optional parameters for modifying the rows to be included 101 * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter 102 * criterion ("applied") or all TR elements (i.e. no filter). 103 * @param {string} [oOpts.order=current] Order of the TR elements in the processed array. 104 * Can be either 'current', whereby the current sorting of the table is used, or 105 * 'original' whereby the original order the data was read into the table is used. 106 * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page 107 * ("current") or not ("all"). If 'current' is given, then order is assumed to be 108 * 'current' and filter is 'applied', regardless of what they might be given as. 109 * @returns {object} jQuery object, filtered by the given selector. 110 * @dtopt API 111 * @deprecated Since v1.10 112 * 113 * @example 114 * $(document).ready(function() { 115 * var oTable = $('#example').dataTable(); 116 * 117 * // Highlight every second row 118 * oTable.$('tr:odd').css('backgroundColor', 'blue'); 119 * } ); 120 * 121 * @example 122 * $(document).ready(function() { 123 * var oTable = $('#example').dataTable(); 124 * 125 * // Filter to rows with 'Webkit' in them, add a background colour and then 126 * // remove the filter, thus highlighting the 'Webkit' rows only. 127 * oTable.fnFilter('Webkit'); 128 * oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue'); 129 * oTable.fnFilter(''); 130 * } ); 131 */ 132 this.$ = function ( sSelector, oOpts ) 133 { 134 return this.api(true).$( sSelector, oOpts ); 135 }; 136 137 138 /** 139 * Almost identical to $ in operation, but in this case returns the data for the matched 140 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes 141 * rather than any descendants, so the data can be obtained for the row/cell. If matching 142 * rows are found, the data returned is the original data array/object that was used to 143 * create the row (or a generated array if from a DOM source). 144 * 145 * This method is often useful in-combination with $ where both functions are given the 146 * same parameters and the array indexes will match identically. 147 * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on 148 * @param {object} [oOpts] Optional parameters for modifying the rows to be included 149 * @param {string} [oOpts.filter=none] Select elements that meet the current filter 150 * criterion ("applied") or all elements (i.e. no filter). 151 * @param {string} [oOpts.order=current] Order of the data in the processed array. 152 * Can be either 'current', whereby the current sorting of the table is used, or 153 * 'original' whereby the original order the data was read into the table is used. 154 * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page 155 * ("current") or not ("all"). If 'current' is given, then order is assumed to be 156 * 'current' and filter is 'applied', regardless of what they might be given as. 157 * @returns {array} Data for the matched elements. If any elements, as a result of the 158 * selector, were not TR, TD or TH elements in the DataTable, they will have a null 159 * entry in the array. 160 * @dtopt API 161 * @deprecated Since v1.10 162 * 163 * @example 164 * $(document).ready(function() { 165 * var oTable = $('#example').dataTable(); 166 * 167 * // Get the data from the first row in the table 168 * var data = oTable._('tr:first'); 169 * 170 * // Do something useful with the data 171 * alert( "First cell is: "+data[0] ); 172 * } ); 173 * 174 * @example 175 * $(document).ready(function() { 176 * var oTable = $('#example').dataTable(); 177 * 178 * // Filter to 'Webkit' and get all data for 179 * oTable.fnFilter('Webkit'); 180 * var data = oTable._('tr', {"search": "applied"}); 181 * 182 * // Do something with the data 183 * alert( data.length+" rows matched the search" ); 184 * } ); 185 */ 186 this._ = function ( sSelector, oOpts ) 187 { 188 return this.api(true).rows( sSelector, oOpts ).data(); 189 }; 190 191 192 /** 193 * Create a DataTables Api instance, with the currently selected tables for 194 * the Api's context. 195 * @param {boolean} [traditional=false] Set the API instance's context to be 196 * only the table referred to by the `DataTable.ext.iApiIndex` option, as was 197 * used in the API presented by DataTables 1.9- (i.e. the traditional mode), 198 * or if all tables captured in the jQuery object should be used. 199 * @return {DataTables.Api} 200 */ 201 this.api = function ( traditional ) 202 { 203 return traditional ? 204 new _Api( 205 _fnSettingsFromNode( this[ _ext.iApiIndex ] ) 206 ) : 207 new _Api( this ); 208 }; 209 210 211 /** 212 * Add a single new row or multiple rows of data to the table. Please note 213 * that this is suitable for client-side processing only - if you are using 214 * server-side processing (i.e. "bServerSide": true), then to add data, you 215 * must add it to the data source, i.e. the server-side, through an Ajax call. 216 * @param {array|object} data The data to be added to the table. This can be: 217 * <ul> 218 * <li>1D array of data - add a single row with the data provided</li> 219 * <li>2D array of arrays - add multiple rows in a single call</li> 220 * <li>object - data object when using <i>mData</i></li> 221 * <li>array of objects - multiple data objects when using <i>mData</i></li> 222 * </ul> 223 * @param {bool} [redraw=true] redraw the table or not 224 * @returns {array} An array of integers, representing the list of indexes in 225 * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to 226 * the table. 227 * @dtopt API 228 * @deprecated Since v1.10 229 * 230 * @example 231 * // Global var for counter 232 * var giCount = 2; 233 * 234 * $(document).ready(function() { 235 * $('#example').dataTable(); 236 * } ); 237 * 238 * function fnClickAddRow() { 239 * $('#example').dataTable().fnAddData( [ 240 * giCount+".1", 241 * giCount+".2", 242 * giCount+".3", 243 * giCount+".4" ] 244 * ); 245 * 246 * giCount++; 247 * } 248 */ 249 this.fnAddData = function( data, redraw ) 250 { 251 var api = this.api( true ); 252 253 /* Check if we want to add multiple rows or not */ 254 var rows =
254$.isArray(data) && ( $
vendor: 18,409 bytes, lines 254-850
254.isArray(data[0]) || $.isPlainObject(data[0]) ) ? 255 api.rows.add( data ) : 256 api.row.add( data ); 257 258 if ( redraw === undefined || redraw ) { 259 api.draw(); 260 } 261 262 return rows.flatten().toArray(); 263 }; 264 265 266 /** 267 * This function will make DataTables recalculate the column sizes, based on the data 268 * contained in the table and the sizes applied to the columns (in the DOM, CSS or 269 * through the sWidth parameter). This can be useful when the width of the table's 270 * parent element changes (for example a window resize). 271 * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to 272 * @dtopt API 273 * @deprecated Since v1.10 274 * 275 * @example 276 * $(document).ready(function() { 277 * var oTable = $('#example').dataTable( { 278 * "sScrollY": "200px", 279 * "bPaginate": false 280 * } ); 281 * 282 * $(window).on('resize', function () { 283 * oTable.fnAdjustColumnSizing(); 284 * } ); 285 * } ); 286 */ 287 this.fnAdjustColumnSizing = function ( bRedraw ) 288 { 289 var api = this.api( true ).columns.adjust(); 290 var settings = api.settings()[0]; 291 var scroll = settings.oScroll; 292 293 if ( bRedraw === undefined || bRedraw ) { 294 api.draw( false ); 295 } 296 else if ( scroll.sX !== "" || scroll.sY !== "" ) { 297 /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */ 298 _fnScrollDraw( settings ); 299 } 300 }; 301 302 303 /** 304 * Quickly and simply clear a table 305 * @param {bool} [bRedraw=true] redraw the table or not 306 * @dtopt API 307 * @deprecated Since v1.10 308 * 309 * @example 310 * $(document).ready(function() { 311 * var oTable = $('#example').dataTable(); 312 * 313 * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...) 314 * oTable.fnClearTable(); 315 * } ); 316 */ 317 this.fnClearTable = function( bRedraw ) 318 { 319 var api = this.api( true ).clear(); 320 321 if ( bRedraw === undefined || bRedraw ) { 322 api.draw(); 323 } 324 }; 325 326 327 /** 328 * The exact opposite of 'opening' a row, this function will close any rows which 329 * are currently 'open'. 330 * @param {node} nTr the table row to 'close' 331 * @returns {int} 0 on success, or 1 if failed (can't find the row) 332 * @dtopt API 333 * @deprecated Since v1.10 334 * 335 * @example 336 * $(document).ready(function() { 337 * var oTable; 338 * 339 * // 'open' an information row when a row is clicked on 340 * $('#example tbody tr').click( function () { 341 * if ( oTable.fnIsOpen(this) ) { 342 * oTable.fnClose( this ); 343 * } else { 344 * oTable.fnOpen( this, "Temporary row opened", "info_row" ); 345 * } 346 * } ); 347 * 348 * oTable = $('#example').dataTable(); 349 * } ); 350 */ 351 this.fnClose = function( nTr ) 352 { 353 this.api( true ).row( nTr ).child.hide(); 354 }; 355 356 357 /** 358 * Remove a row for the table 359 * @param {mixed} target The index of the row from aoData to be deleted, or 360 * the TR element you want to delete 361 * @param {function|null} [callBack] Callback function 362 * @param {bool} [redraw=true] Redraw the table or not 363 * @returns {array} The row that was deleted 364 * @dtopt API 365 * @deprecated Since v1.10 366 * 367 * @example 368 * $(document).ready(function() { 369 * var oTable = $('#example').dataTable(); 370 * 371 * // Immediately remove the first row 372 * oTable.fnDeleteRow( 0 ); 373 * } ); 374 */ 375 this.fnDeleteRow = function( target, callback, redraw ) 376 { 377 var api = this.api( true ); 378 var rows = api.rows( target ); 379 var settings = rows.settings()[0]; 380 var data = settings.aoData[ rows[0][0] ]; 381 382 rows.remove(); 383 384 if ( callback ) { 385 callback.call( this, settings, data ); 386 } 387 388 if ( redraw === undefined || redraw ) { 389 api.draw(); 390 } 391 392 return data; 393 }; 394 395 396 /** 397 * Restore the table to it's original state in the DOM by removing all of DataTables 398 * enhancements, alterations to the DOM structure of the table and event listeners. 399 * @param {boolean} [remove=false] Completely remove the table from the DOM 400 * @dtopt API 401 * @deprecated Since v1.10 402 * 403 * @example 404 * $(document).ready(function() { 405 * // This example is fairly pointless in reality, but shows how fnDestroy can be used 406 * var oTable = $('#example').dataTable(); 407 * oTable.fnDestroy(); 408 * } ); 409 */ 410 this.fnDestroy = function ( remove ) 411 { 412 this.api( true ).destroy( remove ); 413 }; 414 415 416 /** 417 * Redraw the table 418 * @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw. 419 * @dtopt API 420 * @deprecated Since v1.10 421 * 422 * @example 423 * $(document).ready(function() { 424 * var oTable = $('#example').dataTable(); 425 * 426 * // Re-draw the table - you wouldn't want to do it here, but it's an example :-) 427 * oTable.fnDraw(); 428 * } ); 429 */ 430 this.fnDraw = function( complete ) 431 { 432 // Note that this isn't an exact match to the old call to _fnDraw - it takes 433 // into account the new data, but can hold position. 434 this.api( true ).draw( complete ); 435 }; 436 437 438 /** 439 * Filter the input based on data 440 * @param {string} sInput String to filter the table on 441 * @param {int|null} [iColumn] Column to limit filtering to 442 * @param {bool} [bRegex=false] Treat as regular expression or not 443 * @param {bool} [bSmart=true] Perform smart filtering or not 444 * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es) 445 * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false) 446 * @dtopt API 447 * @deprecated Since v1.10 448 * 449 * @example 450 * $(document).ready(function() { 451 * var oTable = $('#example').dataTable(); 452 * 453 * // Sometime later - filter... 454 * oTable.fnFilter( 'test string' ); 455 * } ); 456 */ 457 this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive ) 458 { 459 var api = this.api( true ); 460 461 if ( iColumn === null || iColumn === undefined ) { 462 api.search( sInput, bRegex, bSmart, bCaseInsensitive ); 463 } 464 else { 465 api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive ); 466 } 467 468 api.draw(); 469 }; 470 471 472 /** 473 * Get the data for the whole table, an individual row or an individual cell based on the 474 * provided parameters. 475 * @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as 476 * a TR node then the data source for the whole row will be returned. If given as a 477 * TD/TH cell node then iCol will be automatically calculated and the data for the 478 * cell returned. If given as an integer, then this is treated as the aoData internal 479 * data index for the row (see fnGetPosition) and the data for that row used. 480 * @param {int} [col] Optional column index that you want the data of. 481 * @returns {array|object|string} If mRow is undefined, then the data for all rows is 482 * returned. If mRow is defined, just data for that row, and is iCol is 483 * defined, only data for the designated cell is returned. 484 * @dtopt API 485 * @deprecated Since v1.10 486 * 487 * @example 488 * // Row data 489 * $(document).ready(function() { 490 * oTable = $('#example').dataTable(); 491 * 492 * oTable.$('tr').click( function () { 493 * var data = oTable.fnGetData( this ); 494 * // ... do something with the array / object of data for the row 495 * } ); 496 * } ); 497 * 498 * @example 499 * // Individual cell data 500 * $(document).ready(function() { 501 * oTable = $('#example').dataTable(); 502 * 503 * oTable.$('td').click( function () { 504 * var sData = oTable.fnGetData( this ); 505 * alert( 'The cell clicked on had the value of '+sData ); 506 * } ); 507 * } ); 508 */ 509 this.fnGetData = function( src, col ) 510 { 511 var api = this.api( true ); 512 513 if ( src !== undefined ) { 514 var type = src.nodeName ? src.nodeName.toLowerCase() : ''; 515 516 return col !== undefined || type == 'td' || type == 'th' ? 517 api.cell( src, col ).data() : 518 api.row( src ).data() || null; 519 } 520 521 return api.data().toArray(); 522 }; 523 524 525 /** 526 * Get an array of the TR nodes that are used in the table's body. Note that you will 527 * typically want to use the '$' API method in preference to this as it is more 528 * flexible. 529 * @param {int} [iRow] Optional row index for the TR element you want 530 * @returns {array|node} If iRow is undefined, returns an array of all TR elements 531 * in the table's body, or iRow is defined, just the TR element requested. 532 * @dtopt API 533 * @deprecated Since v1.10 534 * 535 * @example 536 * $(document).ready(function() { 537 * var oTable = $('#example').dataTable(); 538 * 539 * // Get the nodes from the table 540 * var nNodes = oTable.fnGetNodes( ); 541 * } ); 542 */ 543 this.fnGetNodes = function( iRow ) 544 { 545 var api = this.api( true ); 546 547 return iRow !== undefined ? 548 api.row( iRow ).node() : 549 api.rows().nodes().flatten().toArray(); 550 }; 551 552 553 /** 554 * Get the array indexes of a particular cell from it's DOM element 555 * and column index including hidden columns 556 * @param {node} node this can either be a TR, TD or TH in the table's body 557 * @returns {int} If nNode is given as a TR, then a single index is returned, or 558 * if given as a cell, an array of [row index, column index (visible), 559 * column index (all)] is given. 560 * @dtopt API 561 * @deprecated Since v1.10 562 * 563 * @example 564 * $(document).ready(function() { 565 * $('#example tbody td').click( function () { 566 * // Get the position of the current data from the node 567 * var aPos = oTable.fnGetPosition( this ); 568 * 569 * // Get the data array for this row 570 * var aData = oTable.fnGetData( aPos[0] ); 571 * 572 * // Update the data array and return the value 573 * aData[ aPos[1] ] = 'clicked'; 574 * this.innerHTML = 'clicked'; 575 * } ); 576 * 577 * // Init DataTables 578 * oTable = $('#example').dataTable(); 579 * } ); 580 */ 581 this.fnGetPosition = function( node ) 582 { 583 var api = this.api( true ); 584 var nodeName = node.nodeName.toUpperCase(); 585 586 if ( nodeName == 'TR' ) { 587 return api.row( node ).index(); 588 } 589 else if ( nodeName == 'TD' || nodeName == 'TH' ) { 590 var cell = api.cell( node ).index(); 591 592 return [ 593 cell.row, 594 cell.columnVisible, 595 cell.column 596 ]; 597 } 598 return null; 599 }; 600 601 602 /** 603 * Check to see if a row is 'open' or not. 604 * @param {node} nTr the table row to check 605 * @returns {boolean} true if the row is currently open, false otherwise 606 * @dtopt API 607 * @deprecated Since v1.10 608 * 609 * @example 610 * $(document).ready(function() { 611 * var oTable; 612 * 613 * // 'open' an information row when a row is clicked on 614 * $('#example tbody tr').click( function () { 615 * if ( oTable.fnIsOpen(this) ) { 616 * oTable.fnClose( this ); 617 * } else { 618 * oTable.fnOpen( this, "Temporary row opened", "info_row" ); 619 * } 620 * } ); 621 * 622 * oTable = $('#example').dataTable(); 623 * } ); 624 */ 625 this.fnIsOpen = function( nTr ) 626 { 627 return this.api( true ).row( nTr ).child.isShown(); 628 }; 629 630 631 /** 632 * This function will place a new row directly after a row which is currently 633 * on display on the page, with the HTML contents that is passed into the 634 * function. This can be used, for example, to ask for confirmation that a 635 * particular record should be deleted. 636 * @param {node} nTr The table row to 'open' 637 * @param {string|node|jQuery} mHtml The HTML to put into the row 638 * @param {string} sClass Class to give the new TD cell 639 * @returns {node} The row opened. Note that if the table row passed in as the 640 * first parameter, is not found in the table, this method will silently 641 * return. 642 * @dtopt API 643 * @deprecated Since v1.10 644 * 645 * @example 646 * $(document).ready(function() { 647 * var oTable; 648 * 649 * // 'open' an information row when a row is clicked on 650 * $('#example tbody tr').click( function () { 651 * if ( oTable.fnIsOpen(this) ) { 652 * oTable.fnClose( this ); 653 * } else { 654 * oTable.fnOpen( this, "Temporary row opened", "info_row" ); 655 * } 656 * } ); 657 * 658 * oTable = $('#example').dataTable(); 659 * } ); 660 */ 661 this.fnOpen = function( nTr, mHtml, sClass ) 662 { 663 return this.api( true ) 664 .row( nTr ) 665 .child( mHtml, sClass ) 666 .show() 667 .child()[0]; 668 }; 669 670 671 /** 672 * Change the pagination - provides the internal logic for pagination in a simple API 673 * function. With this function you can have a DataTables table go to the next, 674 * previous, first or last pages. 675 * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last" 676 * or page number to jump to (integer), note that page 0 is the first page. 677 * @param {bool} [bRedraw=true] Redraw the table or not 678 * @dtopt API 679 * @deprecated Since v1.10 680 * 681 * @example 682 * $(document).ready(function() { 683 * var oTable = $('#example').dataTable(); 684 * oTable.fnPageChange( 'next' ); 685 * } ); 686 */ 687 this.fnPageChange = function ( mAction, bRedraw ) 688 { 689 var api = this.api( true ).page( mAction ); 690 691 if ( bRedraw === undefined || bRedraw ) { 692 api.draw(false); 693 } 694 }; 695 696 697 /** 698 * Show a particular column 699 * @param {int} iCol The column whose display should be changed 700 * @param {bool} bShow Show (true) or hide (false) the column 701 * @param {bool} [bRedraw=true] Redraw the table or not 702 * @dtopt API 703 * @deprecated Since v1.10 704 * 705 * @example 706 * $(document).ready(function() { 707 * var oTable = $('#example').dataTable(); 708 * 709 * // Hide the second column after initialisation 710 * oTable.fnSetColumnVis( 1, false ); 711 * } ); 712 */ 713 this.fnSetColumnVis = function ( iCol, bShow, bRedraw ) 714 { 715 var api = this.api( true ).column( iCol ).visible( bShow ); 716 717 if ( bRedraw === undefined || bRedraw ) { 718 api.columns.adjust().draw(); 719 } 720 }; 721 722 723 /** 724 * Get the settings for a particular table for external manipulation 725 * @returns {object} DataTables settings object. See 726 * {@link DataTable.models.oSettings} 727 * @dtopt API 728 * @deprecated Since v1.10 729 * 730 * @example 731 * $(document).ready(function() { 732 * var oTable = $('#example').dataTable(); 733 * var oSettings = oTable.fnSettings(); 734 * 735 * // Show an example parameter from the settings 736 * alert( oSettings._iDisplayStart ); 737 * } ); 738 */ 739 this.fnSettings = function() 740 { 741 return _fnSettingsFromNode( this[_ext.iApiIndex] ); 742 }; 743 744 745 /** 746 * Sort the table by a particular column 747 * @param {int} iCol the data index to sort on. Note that this will not match the 748 * 'display index' if you have hidden data entries 749 * @dtopt API 750 * @deprecated Since v1.10 751 * 752 * @example 753 * $(document).ready(function() { 754 * var oTable = $('#example').dataTable(); 755 * 756 * // Sort immediately with columns 0 and 1 757 * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] ); 758 * } ); 759 */ 760 this.fnSort = function( aaSort ) 761 { 762 this.api( true ).order( aaSort ).draw(); 763 }; 764 765 766 /** 767 * Attach a sort listener to an element for a given column 768 * @param {node} nNode the element to attach the sort listener to 769 * @param {int} iColumn the column that a click on this node will sort on 770 * @param {function} [fnCallback] callback function when sort is run 771 * @dtopt API 772 * @deprecated Since v1.10 773 * 774 * @example 775 * $(document).ready(function() { 776 * var oTable = $('#example').dataTable(); 777 * 778 * // Sort on column 1, when 'sorter' is clicked on 779 * oTable.fnSortListener( document.getElementById('sorter'), 1 ); 780 * } ); 781 */ 782 this.fnSortListener = function( nNode, iColumn, fnCallback ) 783 { 784 this.api( true ).order.listener( nNode, iColumn, fnCallback ); 785 }; 786 787 788 /** 789 * Update a table cell or row - this method will accept either a single value to 790 * update the cell with, an array of values with one element for each column or 791 * an object in the same format as the original data source. The function is 792 * self-referencing in order to make the multi column updates easier. 793 * @param {object|array|string} mData Data to update the cell/row with 794 * @param {node|int} mRow TR element you want to update or the aoData index 795 * @param {int} [iColumn] The column to update, give as null or undefined to 796 * update a whole row. 797 * @param {bool} [bRedraw=true] Redraw the table or not 798 * @param {bool} [bAction=true] Perform pre-draw actions or not 799 * @returns {int} 0 on success, 1 on error 800 * @dtopt API 801 * @deprecated Since v1.10 802 * 803 * @example 804 * $(document).ready(function() { 805 * var oTable = $('#example').dataTable(); 806 * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell 807 * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row 808 * } ); 809 */ 810 this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction ) 811 { 812 var api = this.api( true ); 813 814 if ( iColumn === undefined || iColumn === null ) { 815 api.row( mRow ).data( mData ); 816 } 817 else { 818 api.cell( mRow, iColumn ).data( mData ); 819 } 820 821 if ( bAction === undefined || bAction ) { 822 api.columns.adjust(); 823 } 824 825 if ( bRedraw === undefined || bRedraw ) { 826 api.draw(); 827 } 828 return 0; 829 }; 830 831 832 /** 833 * Provide a common method for plug-ins to check the version of DataTables being used, in order 834 * to ensure compatibility. 835 * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the 836 * formats "X" and "X.Y" are also acceptable. 837 * @returns {boolean} true if this version of DataTables is greater or equal to the required 838 * version, or false if this version of DataTales is not suitable 839 * @method 840 * @dtopt API 841 * @deprecated Since v1.10 842 * 843 * @example 844 * $(document).ready(function() { 845 * var oTable = $('#example').dataTable(); 846 * alert( oTable.fnVersionCheck( '1.9.0' ) ); 847 * } ); 848 */ 849 this.fnVersionCheck = _ext.fnVersionCheck; 850
vendor: 57,821 bytes, lines 851-2871
851 852 var _that = this; 853 var emptyInit = options === undefined; 854 var len = this.length; 855 856 if ( emptyInit ) { 857 options = {}; 858 } 859 860 this.oApi = this.internal = _ext.internal; 861 862 // Extend with old style plug-in API methods 863 for ( var fn in DataTable.ext.internal ) { 864 if ( fn ) { 865 this[fn] = _fnExternApiFunc(fn); 866 } 867 } 868 869 this.each(function() { 870 // For each initialisation we want to give it a clean initialisation 871 // object that can be bashed around 872 var o = {}; 873 var oInit = len > 1 ? // optimisation for single table case 874 _fnExtend( o, options, true ) : 875 options; 876 877 /*global oInit,_that,emptyInit*/ 878 var i=0, iLen, j, jLen, k, kLen; 879 var sId = this.getAttribute( 'id' ); 880 var bInitHandedOff = false; 881 var defaults = DataTable.defaults; 882 var $this = $(this); 883 884 885 /* Sanity check */ 886 if ( this.nodeName.toLowerCase() != 'table' ) 887 { 888 _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 ); 889 return; 890 } 891 892 /* Backwards compatibility for the defaults */ 893 _fnCompatOpts( defaults ); 894 _fnCompatCols( defaults.column ); 895 896 /* Convert the camel-case defaults to Hungarian */ 897 _fnCamelToHungarian( defaults, defaults, true ); 898 _fnCamelToHungarian( defaults.column, defaults.column, true ); 899 900 /* Setting up the initialisation object */ 901 _fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ), true ); 902 903 904 905 /* Check to see if we are re-initialising a table */ 906 var allSettings = DataTable.settings; 907 for ( i=0, iLen=allSettings.length ; i<iLen ; i++ ) 908 { 909 var s = allSettings[i]; 910 911 /* Base check on table node */ 912 if ( 913 s.nTable == this || 914 (s.nTHead && s.nTHead.parentNode == this) || 915 (s.nTFoot && s.nTFoot.parentNode == this) 916 ) { 917 var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve; 918 var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy; 919 920 if ( emptyInit || bRetrieve ) 921 { 922 return s.oInstance; 923 } 924 else if ( bDestroy ) 925 { 926 s.oInstance.fnDestroy(); 927 break; 928 } 929 else 930 { 931 _fnLog( s, 0, 'Cannot reinitialise DataTable', 3 ); 932 return; 933 } 934 } 935 936 /* If the element we are initialising has the same ID as a table which was previously 937 * initialised, but the table nodes don't match (from before) then we destroy the old 938 * instance by simply deleting it. This is under the assumption that the table has been 939 * destroyed by other methods. Anyone using non-id selectors will need to do this manually 940 */ 941 if ( s.sTableId == this.id ) 942 { 943 allSettings.splice( i, 1 ); 944 break; 945 } 946 } 947 948 /* Ensure the table has an ID - required for accessibility */ 949 if ( sId === null || sId === "" ) 950 { 951 sId = "DataTables_Table_"+(DataTable.ext._unique++); 952 this.id = sId; 953 } 954 955 /* Create the settings object for this table and set some of the default parameters */ 956 var oSettings = $.extend( true, {}, DataTable.models.oSettings, { 957 "sDestroyWidth": $this[0].style.width, 958 "sInstance": sId, 959 "sTableId": sId 960 } ); 961 oSettings.nTable = this; 962 oSettings.oApi = _that.internal; 963 oSettings.oInit = oInit; 964 965 allSettings.push( oSettings ); 966 967 // Need to add the instance after the instance after the settings object has been added 968 // to the settings array, so we can self reference the table instance if more than one 969 oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable(); 970 971 // Backwards compatibility, before we apply all the defaults 972 _fnCompatOpts( oInit ); 973 _fnLanguageCompat( oInit.oLanguage ); 974 975 // If the length menu is given, but the init display length is not, use the length menu 976 if ( oInit.aLengthMenu && ! oInit.iDisplayLength ) 977 { 978 oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ? 979 oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0]; 980 } 981 982 // Apply the defaults and init options to make a single init object will all 983 // options defined from defaults and instance options. 984 oInit = _fnExtend( $.extend( true, {}, defaults ), oInit ); 985 986 987 // Map the initialisation options onto the settings object 988 _fnMap( oSettings.oFeatures, oInit, [ 989 "bPaginate", 990 "bLengthChange", 991 "bFilter", 992 "bSort", 993 "bSortMulti", 994 "bInfo", 995 "bProcessing", 996 "bAutoWidth", 997 "bSortClasses", 998 "bServerSide", 999 "bDeferRender" 1000 ] ); 1001 _fnMap( oSettings, oInit, [ 1002 "asStripeClasses", 1003 "ajax", 1004 "fnServerData", 1005 "fnFormatNumber", 1006 "sServerMethod", 1007 "aaSorting", 1008 "aaSortingFixed", 1009 "aLengthMenu", 1010 "sPaginationType", 1011 "sAjaxSource", 1012 "sAjaxDataProp", 1013 "iStateDuration", 1014 "sDom", 1015 "bSortCellsTop", 1016 "iTabIndex", 1017 "fnStateLoadCallback", 1018 "fnStateSaveCallback", 1019 "renderer", 1020 "searchDelay", 1021 "rowId", 1022 [ "iCookieDuration", "iStateDuration" ], // backwards compat 1023 [ "oSearch", "oPreviousSearch" ], 1024 [ "aoSearchCols", "aoPreSearchCols" ], 1025 [ "iDisplayLength", "_iDisplayLength" ] 1026 ] ); 1027 _fnMap( oSettings.oScroll, oInit, [ 1028 [ "sScrollX", "sX" ], 1029 [ "sScrollXInner", "sXInner" ], 1030 [ "sScrollY", "sY" ], 1031 [ "bScrollCollapse", "bCollapse" ] 1032 ] ); 1033 _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" ); 1034 1035 /* Callback functions which are array driven */ 1036 _fnCallbackReg( oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user' ); 1037 _fnCallbackReg( oSettings, 'aoServerParams', oInit.fnServerParams, 'user' ); 1038 _fnCallbackReg( oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user' ); 1039 _fnCallbackReg( oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user' ); 1040 _fnCallbackReg( oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user' ); 1041 _fnCallbackReg( oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user' ); 1042 _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user' ); 1043 _fnCallbackReg( oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user' ); 1044 _fnCallbackReg( oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user' ); 1045 _fnCallbackReg( oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user' ); 1046 _fnCallbackReg( oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user' ); 1047 1048 oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId ); 1049 1050 /* Browser support detection */ 1051 _fnBrowserDetect( oSettings ); 1052 1053 var oClasses = oSettings.oClasses; 1054 1055 $.extend( oClasses, DataTable.ext.classes, oInit.oClasses ); 1056 $this.addClass( oClasses.sTable ); 1057 1058 1059 if ( oSettings.iInitDisplayStart === undefined ) 1060 { 1061 /* Display start point, taking into account the save saving */ 1062 oSettings.iInitDisplayStart = oInit.iDisplayStart; 1063 oSettings._iDisplayStart = oInit.iDisplayStart; 1064 } 1065 1066 if ( oInit.iDeferLoading !== null ) 1067 { 1068 oSettings.bDeferLoading = true; 1069 var tmp = $.isArray( oInit.iDeferLoading ); 1070 oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading; 1071 oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading; 1072 } 1073 1074 /* Language definitions */ 1075 var oLanguage = oSettings.oLanguage; 1076 $.extend( true, oLanguage, oInit.oLanguage ); 1077 1078 if ( oLanguage.sUrl ) 1079 { 1080 /* Get the language definitions from a file - because this Ajax call makes the language 1081 * get async to the remainder of this function we use bInitHandedOff to indicate that 1082 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor 1083 */ 1084 $.ajax( { 1085 dataType: 'json', 1086 url: oLanguage.sUrl, 1087 success: function ( json ) { 1088 _fnLanguageCompat( json ); 1089 _fnCamelToHungarian( defaults.oLanguage, json ); 1090 $.extend( true, oLanguage, json ); 1091 _fnInitialise( oSettings ); 1092 }, 1093 error: function () { 1094 // Error occurred loading language file, continue on as best we can 1095 _fnInitialise( oSettings ); 1096 } 1097 } ); 1098 bInitHandedOff = true; 1099 } 1100 1101 /* 1102 * Stripes 1103 */ 1104 if ( oInit.asStripeClasses === null ) 1105 { 1106 oSettings.asStripeClasses =[ 1107 oClasses.sStripeOdd, 1108 oClasses.sStripeEven 1109 ]; 1110 } 1111 1112 /* Remove row stripe classes if they are already on the table row */ 1113 var stripeClasses = oSettings.asStripeClasses; 1114 var rowOne = $this.children('tbody').find('tr').eq(0); 1115 if ( $.inArray( true, $.map( stripeClasses, function(el, i) { 1116 return rowOne.hasClass(el); 1117 } ) ) !== -1 ) { 1118 $('tbody tr', this).removeClass( stripeClasses.join(' ') ); 1119 oSettings.asDestroyStripes = stripeClasses.slice(); 1120 } 1121 1122 /* 1123 * Columns 1124 * See if we should load columns automatically or use defined ones 1125 */ 1126 var anThs = []; 1127 var aoColumnsInit; 1128 var nThead = this.getElementsByTagName('thead'); 1129 if ( nThead.length !== 0 ) 1130 { 1131 _fnDetectHeader( oSettings.aoHeader, nThead[0] ); 1132 anThs = _fnGetUniqueThs( oSettings ); 1133 } 1134 1135 /* If not given a column array, generate one with nulls */ 1136 if ( oInit.aoColumns === null ) 1137 { 1138 aoColumnsInit = []; 1139 for ( i=0, iLen=anThs.length ; i<iLen ; i++ ) 1140 { 1141 aoColumnsInit.push( null ); 1142 } 1143 } 1144 else 1145 { 1146 aoColumnsInit = oInit.aoColumns; 1147 } 1148 1149 /* Add the columns */ 1150 for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ ) 1151 { 1152 _fnAddColumn( oSettings, anThs ? anThs[i] : null ); 1153 } 1154 1155 /* Apply the column definitions */ 1156 _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) { 1157 _fnColumnOptions( oSettings, iCol, oDef ); 1158 } ); 1159 1160 /* HTML5 attribute detection - build an mData object automatically if the 1161 * attributes are found 1162 */ 1163 if ( rowOne.length ) { 1164 var a = function ( cell, name ) { 1165 return cell.getAttribute( 'data-'+name ) !== null ? name : null; 1166 }; 1167 1168 $( rowOne[0] ).children('th, td').each( function (i, cell) { 1169 var col = oSettings.aoColumns[i]; 1170 1171 if ( col.mData === i ) { 1172 var sort = a( cell, 'sort' ) || a( cell, 'order' ); 1173 var filter = a( cell, 'filter' ) || a( cell, 'search' ); 1174 1175 if ( sort !== null || filter !== null ) { 1176 col.mData = { 1177 _: i+'.display', 1178 sort: sort !== null ? i+'.@data-'+sort : undefined, 1179 type: sort !== null ? i+'.@data-'+sort : undefined, 1180 filter: filter !== null ? i+'.@data-'+filter : undefined 1181 }; 1182 1183 _fnColumnOptions( oSettings, i ); 1184 } 1185 } 1186 } ); 1187 } 1188 1189 var features = oSettings.oFeatures; 1190 var loadedInit = function () { 1191 /* 1192 * Sorting 1193 * @todo For modularisation (1.11) this needs to do into a sort start up handler 1194 */ 1195 1196 // If aaSorting is not defined, then we use the first indicator in asSorting 1197 // in case that has been altered, so the default sort reflects that option 1198 if ( oInit.aaSorting === undefined ) { 1199 var sorting = oSettings.aaSorting; 1200 for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) { 1201 sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0]; 1202 } 1203 } 1204 1205 /* Do a first pass on the sorting classes (allows any size changes to be taken into 1206 * account, and also will apply sorting disabled classes if disabled 1207 */ 1208 _fnSortingClasses( oSettings ); 1209 1210 if ( features.bSort ) { 1211 _fnCallbackReg( oSettings, 'aoDrawCallback', function () { 1212 if ( oSettings.bSorted ) { 1213 var aSort = _fnSortFlatten( oSettings ); 1214 var sortedColumns = {}; 1215 1216 $.each( aSort, function (i, val) { 1217 sortedColumns[ val.src ] = val.dir; 1218 } ); 1219 1220 _fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] ); 1221 _fnSortAria( oSettings ); 1222 } 1223 } ); 1224 } 1225 1226 _fnCallbackReg( oSettings, 'aoDrawCallback', function () { 1227 if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) { 1228 _fnSortingClasses( oSettings ); 1229 } 1230 }, 'sc' ); 1231 1232 1233 /* 1234 * Final init 1235 * Cache the header, body and footer as required, creating them if needed 1236 */ 1237 1238 // Work around for Webkit bug 83867 - store the caption-side before removing from doc 1239 var captions = $this.children('caption').each( function () { 1240 this._captionSide = $(this).css('caption-side'); 1241 } ); 1242 1243 var thead = $this.children('thead'); 1244 if ( thead.length === 0 ) { 1245 thead = $('<thead/>').appendTo($this); 1246 } 1247 oSettings.nTHead = thead[0]; 1248 1249 var tbody = $this.children('tbody'); 1250 if ( tbody.length === 0 ) { 1251 tbody = $('<tbody/>').appendTo($this); 1252 } 1253 oSettings.nTBody = tbody[0]; 1254 1255 var tfoot = $this.children('tfoot'); 1256 if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) { 1257 // If we are a scrolling table, and no footer has been given, then we need to create 1258 // a tfoot element for the caption element to be appended to 1259 tfoot = $('<tfoot/>').appendTo($this); 1260 } 1261 1262 if ( tfoot.length === 0 || tfoot.children().length === 0 ) { 1263 $this.addClass( oClasses.sNoFooter ); 1264 } 1265 else if ( tfoot.length > 0 ) { 1266 oSettings.nTFoot = tfoot[0]; 1267 _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot ); 1268 } 1269 1270 /* Check if there is data passing into the constructor */ 1271 if ( oInit.aaData ) { 1272 for ( i=0 ; i<oInit.aaData.length ; i++ ) { 1273 _fnAddData( oSettings, oInit.aaData[ i ] ); 1274 } 1275 } 1276 else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) { 1277 /* Grab the data from the page - only do this when deferred loading or no Ajax 1278 * source since there is no point in reading the DOM data if we are then going 1279 * to replace it with Ajax data 1280 */ 1281 _fnAddTr( oSettings, $(oSettings.nTBody).children('tr') ); 1282 } 1283 1284 /* Copy the data index array */ 1285 oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); 1286 1287 /* Initialisation complete - table can be drawn */ 1288 oSettings.bInitialised = true; 1289 1290 /* Check if we need to initialise the table (it might not have been handed off to the 1291 * language processor) 1292 */ 1293 if ( bInitHandedOff === false ) { 1294 _fnInitialise( oSettings ); 1295 } 1296 }; 1297 1298 /* Must be done after everything which can be overridden by the state saving! */ 1299 if ( oInit.bStateSave ) 1300 { 1301 features.bStateSave = true; 1302 _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' ); 1303 _fnLoadState( oSettings, oInit, loadedInit ); 1304 } 1305 else { 1306 loadedInit(); 1307 } 1308 1309 } ); 1310 _that = null; 1311 return this; 1312 }; 1313 1314 1315 /* 1316 * It is useful to have variables which are scoped locally so only the 1317 * DataTables functions can access them and they don't leak into global space. 1318 * At the same time these functions are often useful over multiple files in the 1319 * core and API, so we list, or at least document, all variables which are used 1320 * by DataTables as private variables here. This also ensures that there is no 1321 * clashing of variable names and that they can easily referenced for reuse. 1322 */ 1323 1324 1325 // Defined else where 1326 // _selector_run 1327 // _selector_opts 1328 // _selector_first 1329 // _selector_row_indexes 1330 1331 var _ext; // DataTable.ext 1332 var _Api; // DataTable.Api 1333 var _api_register; // DataTable.Api.register 1334 var _api_registerPlural; // DataTable.Api.registerPlural 1335 1336 var _re_dic = {}; 1337 var _re_new_lines = /[\r\n\u2028]/g; 1338 var _re_html = /<.*?>/g; 1339 1340 // This is not strict ISO8601 - Date.parse() is quite lax, although 1341 // implementations differ between browsers. 1342 var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/; 1343 1344 // Escape regular expression special characters 1345 var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' ); 1346 1347 // http://en.wikipedia.org/wiki/Foreign_exchange_market 1348 // - \u20BD - Russian ruble. 1349 // - \u20a9 - South Korean Won 1350 // - \u20BA - Turkish Lira 1351 // - \u20B9 - Indian Rupee 1352 // - R - Brazil (R$) and South Africa 1353 // - fr - Swiss Franc 1354 // - kr - Swedish krona, Norwegian krone and Danish krone 1355 // - \u2009 is thin space and \u202F is narrow no-break space, both used in many 1356 // - É - Bitcoin 1357 // - Î - Ethereum 1358 // standards as thousands separators. 1359 var _re_formatted_numeric = /[',$£â¬Â¥%\u2009\u202F\u20BD\u20a9\u20BArfkÉÎ]/gi; 1360 1361 1362 var _empty = function ( d ) { 1363 return !d || d === true || d === '-' ? true : false; 1364 }; 1365 1366 1367 var _intVal = function ( s ) { 1368 var integer = parseInt( s, 10 ); 1369 return !isNaN(integer) && isFinite(s) ? integer : null; 1370 }; 1371 1372 // Convert from a formatted number with characters other than `.` as the 1373 // decimal place, to a Javascript number 1374 var _numToDecimal = function ( num, decimalPoint ) { 1375 // Cache created regular expressions for speed as this function is called often 1376 if ( ! _re_dic[ decimalPoint ] ) { 1377 _re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' ); 1378 } 1379 return typeof num === 'string' && decimalPoint !== '.' ? 1380 num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) : 1381 num; 1382 }; 1383 1384 1385 var _isNumber = function ( d, decimalPoint, formatted ) { 1386 var strType = typeof d === 'string'; 1387 1388 // If empty return immediately so there must be a number if it is a 1389 // formatted string (this stops the string "k", or "kr", etc being detected 1390 // as a formatted number for currency 1391 if ( _empty( d ) ) { 1392 return true; 1393 } 1394 1395 if ( decimalPoint && strType ) { 1396 d = _numToDecimal( d, decimalPoint ); 1397 } 1398 1399 if ( formatted && strType ) { 1400 d = d.replace( _re_formatted_numeric, '' ); 1401 } 1402 1403 return !isNaN( parseFloat(d) ) && isFinite( d ); 1404 }; 1405 1406 1407 // A string without HTML in it can be considered to be HTML still 1408 var _isHtml = function ( d ) { 1409 return _empty( d ) || typeof d === 'string'; 1410 }; 1411 1412 1413 var _htmlNumeric = function ( d, decimalPoint, formatted ) { 1414 if ( _empty( d ) ) { 1415 return true; 1416 } 1417 1418 var html = _isHtml( d ); 1419 return ! html ? 1420 null : 1421 _isNumber( _stripHtml( d ), decimalPoint, formatted ) ? 1422 true : 1423 null; 1424 }; 1425 1426 1427 var _pluck = function ( a, prop, prop2 ) { 1428 var out = []; 1429 var i=0, ien=a.length; 1430 1431 // Could have the test in the loop for slightly smaller code, but speed 1432 // is essential here 1433 if ( prop2 !== undefined ) { 1434 for ( ; i<ien ; i++ ) { 1435 if ( a[i] && a[i][ prop ] ) { 1436 out.push( a[i][ prop ][ prop2 ] ); 1437 } 1438 } 1439 } 1440 else { 1441 for ( ; i<ien ; i++ ) { 1442 if ( a[i] ) { 1443 out.push( a[i][ prop ] ); 1444 } 1445 } 1446 } 1447 1448 return out; 1449 }; 1450 1451 1452 // Basically the same as _pluck, but rather than looping over `a` we use `order` 1453 // as the indexes to pick from `a` 1454 var _pluck_order = function ( a, order, prop, prop2 ) 1455 { 1456 var out = []; 1457 var i=0, ien=order.length; 1458 1459 // Could have the test in the loop for slightly smaller code, but speed 1460 // is essential here 1461 if ( prop2 !== undefined ) { 1462 for ( ; i<ien ; i++ ) { 1463 if ( a[ order[i] ][ prop ] ) { 1464 out.push( a[ order[i] ][ prop ][ prop2 ] ); 1465 } 1466 } 1467 } 1468 else { 1469 for ( ; i<ien ; i++ ) { 1470 out.push( a[ order[i] ][ prop ] ); 1471 } 1472 } 1473 1474 return out; 1475 }; 1476 1477 1478 var _range = function ( len, start ) 1479 { 1480 var out = []; 1481 var end; 1482 1483 if ( start === undefined ) { 1484 start = 0; 1485 end = len; 1486 } 1487 else { 1488 end = start; 1489 start = len; 1490 } 1491 1492 for ( var i=start ; i<end ; i++ ) { 1493 out.push( i ); 1494 } 1495 1496 return out; 1497 }; 1498 1499 1500 var _removeEmpty = function ( a ) 1501 { 1502 var out = []; 1503 1504 for ( var i=0, ien=a.length ; i<ien ; i++ ) { 1505 if ( a[i] ) { // careful - will remove all falsy values! 1506 out.push( a[i] ); 1507 } 1508 } 1509 1510 return out; 1511 }; 1512 1513 1514 var _stripHtml = function ( d ) { 1515 return d.replace( _re_html, '' ); 1516 }; 1517 1518 1519 /** 1520 * Determine if all values in the array are unique. This means we can short 1521 * cut the _unique method at the cost of a single loop. A sorted array is used 1522 * to easily check the values. 1523 * 1524 * @param {array} src Source array 1525 * @return {boolean} true if all unique, false otherwise 1526 * @ignore 1527 */ 1528 var _areAllUnique = function ( src ) { 1529 if ( src.length < 2 ) { 1530 return true; 1531 } 1532 1533 var sorted = src.slice().sort(); 1534 var last = sorted[0]; 1535 1536 for ( var i=1, ien=sorted.length ; i<ien ; i++ ) { 1537 if ( sorted[i] === last ) { 1538 return false; 1539 } 1540 1541 last = sorted[i]; 1542 } 1543 1544 return true; 1545 }; 1546 1547 1548 /** 1549 * Find the unique elements in a source array. 1550 * 1551 * @param {array} src Source array 1552 * @return {array} Array of unique items 1553 * @ignore 1554 */ 1555 var _unique = function ( src ) 1556 { 1557 if ( _areAllUnique( src ) ) { 1558 return src.slice(); 1559 } 1560 1561 // A faster unique method is to use object keys to identify used values, 1562 // but this doesn't work with arrays or objects, which we must also 1563 // consider. See jsperf.com/compare-array-unique-versions/4 for more 1564 // information. 1565 var 1566 out = [], 1567 val, 1568 i, ien=src.length, 1569 j, k=0; 1570 1571 again: for ( i=0 ; i<ien ; i++ ) { 1572 val = src[i]; 1573 1574 for ( j=0 ; j<k ; j++ ) { 1575 if ( out[j] === val ) { 1576 continue again; 1577 } 1578 } 1579 1580 out.push( val ); 1581 k++; 1582 } 1583 1584 return out; 1585 }; 1586 1587 1588 /** 1589 * DataTables utility methods 1590 * 1591 * This namespace provides helper methods that DataTables uses internally to 1592 * create a DataTable, but which are not exclusively used only for DataTables. 1593 * These methods can be used by extension authors to save the duplication of 1594 * code. 1595 * 1596 * @namespace 1597 */ 1598 DataTable.util = { 1599 /** 1600 * Throttle the calls to a function. Arguments and context are maintained 1601 * for the throttled function. 1602 * 1603 * @param {function} fn Function to be called 1604 * @param {integer} freq Call frequency in mS 1605 * @return {function} Wrapped function 1606 */ 1607 throttle: function ( fn, freq ) { 1608 var 1609 frequency = freq !== undefined ? freq : 200, 1610 last, 1611 timer; 1612 1613 return function () { 1614 var 1615 that = this, 1616 now = +new Date(), 1617 args = arguments; 1618 1619 if ( last && now < last + frequency ) { 1620 clearTimeout( timer ); 1621 1622 timer = setTimeout( function () { 1623 last = undefined; 1624 fn.apply( that, args ); 1625 }, frequency ); 1626 } 1627 else { 1628 last = now; 1629 fn.apply( that, args ); 1630 } 1631 }; 1632 }, 1633 1634 1635 /** 1636 * Escape a string such that it can be used in a regular expression 1637 * 1638 * @param {string} val string to escape 1639 * @returns {string} escaped string 1640 */ 1641 escapeRegex: function ( val ) { 1642 return val.replace( _re_escape_regex, '\\$1' ); 1643 } 1644 }; 1645 1646 1647 1648 /** 1649 * Create a mapping object that allows camel case parameters to be looked up 1650 * for their Hungarian counterparts. The mapping is stored in a private 1651 * parameter called `_hungarianMap` which can be accessed on the source object. 1652 * @param {object} o 1653 * @memberof DataTable#oApi 1654 */ 1655 function _fnHungarianMap ( o ) 1656 { 1657 var 1658 hungarian = 'a aa ai ao as b fn i m o s ', 1659 match, 1660 newKey, 1661 map = {}; 1662 1663 $.each( o, function (key, val) { 1664 match = key.match(/^([^A-Z]+?)([A-Z])/); 1665 1666 if ( match && hungarian.indexOf(match[1]+' ') !== -1 ) 1667 { 1668 newKey = key.replace( match[0], match[2].toLowerCase() ); 1669 map[ newKey ] = key; 1670 1671 if ( match[1] === 'o' ) 1672 { 1673 _fnHungarianMap( o[key] ); 1674 } 1675 } 1676 } ); 1677 1678 o._hungarianMap = map; 1679 } 1680 1681 1682 /** 1683 * Convert from camel case parameters to Hungarian, based on a Hungarian map 1684 * created by _fnHungarianMap. 1685 * @param {object} src The model object which holds all parameters that can be 1686 * mapped. 1687 * @param {object} user The object to convert from camel case to Hungarian. 1688 * @param {boolean} force When set to `true`, properties which already have a 1689 * Hungarian value in the `user` object will be overwritten. Otherwise they 1690 * won't be. 1691 * @memberof DataTable#oApi 1692 */ 1693 function _fnCamelToHungarian ( src, user, force ) 1694 { 1695 if ( ! src._hungarianMap ) { 1696 _fnHungarianMap( src ); 1697 } 1698 1699 var hungarianKey; 1700 1701 $.each( user, function (key, val) { 1702 hungarianKey = src._hungarianMap[ key ]; 1703 1704 if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) ) 1705 { 1706 // For objects, we need to buzz down into the object to copy parameters 1707 if ( hungarianKey.charAt(0) === 'o' ) 1708 { 1709 // Copy the camelCase options over to the hungarian 1710 if ( ! user[ hungarianKey ] ) { 1711 user[ hungarianKey ] = {}; 1712 } 1713 $.extend( true, user[hungarianKey], user[key] ); 1714 1715 _fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force ); 1716 } 1717 else { 1718 user[hungarianKey] = user[ key ]; 1719 } 1720 } 1721 } ); 1722 } 1723 1724 1725 /** 1726 * Language compatibility - when certain options are given, and others aren't, we 1727 * need to duplicate the values over, in order to provide backwards compatibility 1728 * with older language files. 1729 * @param {object} oSettings dataTables settings object 1730 * @memberof DataTable#oApi 1731 */ 1732 function _fnLanguageCompat( lang ) 1733 { 1734 // Note the use of the Hungarian notation for the parameters in this method as 1735 // this is called after the mapping of camelCase to Hungarian 1736 var defaults = DataTable.defaults.oLanguage; 1737 1738 // Default mapping 1739 var defaultDecimal = defaults.sDecimal; 1740 if ( defaultDecimal ) { 1741 _addNumericSort( defaultDecimal ); 1742 } 1743 1744 if ( lang ) { 1745 var zeroRecords = lang.sZeroRecords; 1746 1747 // Backwards compatibility - if there is no sEmptyTable given, then use the same as 1748 // sZeroRecords - assuming that is given. 1749 if ( ! lang.sEmptyTable && zeroRecords && 1750 defaults.sEmptyTable === "No data available in table" ) 1751 { 1752 _fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' ); 1753 } 1754 1755 // Likewise with loading records 1756 if ( ! lang.sLoadingRecords && zeroRecords && 1757 defaults.sLoadingRecords === "Loading..." ) 1758 { 1759 _fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' ); 1760 } 1761 1762 // Old parameter name of the thousands separator mapped onto the new 1763 if ( lang.sInfoThousands ) { 1764 lang.sThousands = lang.sInfoThousands; 1765 } 1766 1767 var decimal = lang.sDecimal; 1768 if ( decimal && defaultDecimal !== decimal ) { 1769 _addNumericSort( decimal ); 1770 } 1771 } 1772 } 1773 1774 1775 /** 1776 * Map one parameter onto another 1777 * @param {object} o Object to map 1778 * @param {*} knew The new parameter name 1779 * @param {*} old The old parameter name 1780 */ 1781 var _fnCompatMap = function ( o, knew, old ) { 1782 if ( o[ knew ] !== undefined ) { 1783 o[ old ] = o[ knew ]; 1784 } 1785 }; 1786 1787 1788 /** 1789 * Provide backwards compatibility for the main DT options. Note that the new 1790 * options are mapped onto the old parameters, so this is an external interface 1791 * change only. 1792 * @param {object} init Object to map 1793 */ 1794 function _fnCompatOpts ( init ) 1795 { 1796 _fnCompatMap( init, 'ordering', 'bSort' ); 1797 _fnCompatMap( init, 'orderMulti', 'bSortMulti' ); 1798 _fnCompatMap( init, 'orderClasses', 'bSortClasses' ); 1799 _fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' ); 1800 _fnCompatMap( init, 'order', 'aaSorting' ); 1801 _fnCompatMap( init, 'orderFixed', 'aaSortingFixed' ); 1802 _fnCompatMap( init, 'paging', 'bPaginate' ); 1803 _fnCompatMap( init, 'pagingType', 'sPaginationType' ); 1804 _fnCompatMap( init, 'pageLength', 'iDisplayLength' ); 1805 _fnCompatMap( init, 'searching', 'bFilter' ); 1806 1807 // Boolean initialisation of x-scrolling 1808 if ( typeof init.sScrollX === 'boolean' ) { 1809 init.sScrollX = init.sScrollX ? '100%' : ''; 1810 } 1811 if ( typeof init.scrollX === 'boolean' ) { 1812 init.scrollX = init.scrollX ? '100%' : ''; 1813 } 1814 1815 // Column search objects are in an array, so it needs to be converted 1816 // element by element 1817 var searchCols = init.aoSearchCols; 1818 1819 if ( searchCols ) { 1820 for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) { 1821 if ( searchCols[i] ) { 1822 _fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] ); 1823 } 1824 } 1825 } 1826 } 1827 1828 1829 /** 1830 * Provide backwards compatibility for column options. Note that the new options 1831 * are mapped onto the old parameters, so this is an external interface change 1832 * only. 1833 * @param {object} init Object to map 1834 */ 1835 function _fnCompatCols ( init ) 1836 { 1837 _fnCompatMap( init, 'orderable', 'bSortable' ); 1838 _fnCompatMap( init, 'orderData', 'aDataSort' ); 1839 _fnCompatMap( init, 'orderSequence', 'asSorting' ); 1840 _fnCompatMap( init, 'orderDataType', 'sortDataType' ); 1841 1842 // orderData can be given as an integer 1843 var dataSort = init.aDataSort; 1844 if ( typeof dataSort === 'number' && ! $.isArray( dataSort ) ) { 1845 init.aDataSort = [ dataSort ]; 1846 } 1847 } 1848 1849 1850 /** 1851 * Browser feature detection for capabilities, quirks 1852 * @param {object} settings dataTables settings object 1853 * @memberof DataTable#oApi 1854 */ 1855 function _fnBrowserDetect( settings ) 1856 { 1857 // We don't need to do this every time DataTables is constructed, the values 1858 // calculated are specific to the browser and OS configuration which we 1859 // don't expect to change between initialisations 1860 if ( ! DataTable.__browser ) { 1861 var browser = {}; 1862 DataTable.__browser = browser; 1863 1864 // Scrolling feature / quirks detection 1865 var n = $('<div/>') 1866 .css( { 1867 position: 'fixed', 1868 top: 0, 1869 left: $(window).scrollLeft()*-1, // allow for scrolling 1870 height: 1, 1871 width: 1, 1872 overflow: 'hidden' 1873 } ) 1874 .append( 1875 $('<div/>') 1876 .css( { 1877 position: 'absolute', 1878 top: 1, 1879 left: 1, 1880 width: 100, 1881 overflow: 'scroll' 1882 } ) 1883 .append( 1884 $('<div/>') 1885 .css( { 1886 width: '100%', 1887 height: 10 1888 } ) 1889 ) 1890 ) 1891 .appendTo( 'body' ); 1892 1893 var outer = n.children(); 1894 var inner = outer.children(); 1895 1896 // Numbers below, in order, are: 1897 // inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth 1898 // 1899 // IE6 XP: 100 100 100 83 1900 // IE7 Vista: 100 100 100 83 1901 // IE 8+ Windows: 83 83 100 83 1902 // Evergreen Windows: 83 83 100 83 1903 // Evergreen Mac with scrollbars: 85 85 100 85 1904 // Evergreen Mac without scrollbars: 100 100 100 100 1905 1906 // Get scrollbar width 1907 browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth; 1908 1909 // IE6/7 will oversize a width 100% element inside a scrolling element, to 1910 // include the width of the scrollbar, while other browsers ensure the inner 1911 // element is contained without forcing scrolling 1912 browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100; 1913 1914 // In rtl text layout, some browsers (most, but not all) will place the 1915 // scrollbar on the left, rather than the right. 1916 browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1; 1917 1918 // IE8- don't provide height and width for getBoundingClientRect 1919 browser.bBounding = n[0].getBoundingClientRect().width ? true : false; 1920 1921 n.remove(); 1922 } 1923 1924 $.extend( settings.oBrowser, DataTable.__browser ); 1925 settings.oScroll.iBarWidth = DataTable.__browser.barWidth; 1926 } 1927 1928 1929 /** 1930 * Array.prototype reduce[Right] method, used for browsers which don't support 1931 * JS 1.6. Done this way to reduce code size, since we iterate either way 1932 * @param {object} settings dataTables settings object 1933 * @memberof DataTable#oApi 1934 */ 1935 function _fnReduce ( that, fn, init, start, end, inc ) 1936 { 1937 var 1938 i = start, 1939 value, 1940 isSet = false; 1941 1942 if ( init !== undefined ) { 1943 value = init; 1944 isSet = true; 1945 } 1946 1947 while ( i !== end ) { 1948 if ( ! that.hasOwnProperty(i) ) { 1949 continue; 1950 } 1951 1952 value = isSet ? 1953 fn( value, that[i], i, that ) : 1954 that[i]; 1955 1956 isSet = true; 1957 i += inc; 1958 } 1959 1960 return value; 1961 } 1962 1963 /** 1964 * Add a column to the list used for the table with default values 1965 * @param {object} oSettings dataTables settings object 1966 * @param {node} nTh The th element for this column 1967 * @memberof DataTable#oApi 1968 */ 1969 function _fnAddColumn( oSettings, nTh ) 1970 { 1971 // Add column to aoColumns array 1972 var oDefaults = DataTable.defaults.column; 1973 var iCol = oSettings.aoColumns.length; 1974 var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, { 1975 "nTh": nTh ? nTh : document.createElement('th'), 1976 "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '', 1977 "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol], 1978 "mData": oDefaults.mData ? oDefaults.mData : iCol, 1979 idx: iCol 1980 } ); 1981 oSettings.aoColumns.push( oCol ); 1982 1983 // Add search object for column specific search. Note that the `searchCols[ iCol ]` 1984 // passed into extend can be undefined. This allows the user to give a default 1985 // with only some of the parameters defined, and also not give a default 1986 var searchCols = oSettings.aoPreSearchCols; 1987 searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] ); 1988 1989 // Use the default column options function to initialise classes etc 1990 _fnColumnOptions( oSettings, iCol, $(nTh).data() ); 1991 } 1992 1993 1994 /** 1995 * Apply options for a column 1996 * @param {object} oSettings dataTables settings object 1997 * @param {int} iCol column index to consider 1998 * @param {object} oOptions object with sType, bVisible and bSearchable etc 1999 * @memberof DataTable#oApi 2000 */ 2001 function _fnColumnOptions( oSettings, iCol, oOptions ) 2002 { 2003 var oCol = oSettings.aoColumns[ iCol ]; 2004 var oClasses = oSettings.oClasses; 2005 var th = $(oCol.nTh); 2006 2007 // Try to get width information from the DOM. We can't get it from CSS 2008 // as we'd need to parse the CSS stylesheet. `width` option can override 2009 if ( ! oCol.sWidthOrig ) { 2010 // Width attribute 2011 oCol.sWidthOrig = th.attr('width') || null; 2012 2013 // Style attribute 2014 var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/); 2015 if ( t ) { 2016 oCol.sWidthOrig = t[1]; 2017 } 2018 } 2019 2020 /* User specified column options */ 2021 if ( oOptions !== undefined && oOptions !== null ) 2022 { 2023 // Backwards compatibility 2024 _fnCompatCols( oOptions ); 2025 2026 // Map camel case parameters to their Hungarian counterparts 2027 _fnCamelToHungarian( DataTable.defaults.column, oOptions, true ); 2028 2029 /* Backwards compatibility for mDataProp */ 2030 if ( oOptions.mDataProp !== undefined && !oOptions.mData ) 2031 { 2032 oOptions.mData = oOptions.mDataProp; 2033 } 2034 2035 if ( oOptions.sType ) 2036 { 2037 oCol._sManualType = oOptions.sType; 2038 } 2039 2040 // `class` is a reserved word in Javascript, so we need to provide 2041 // the ability to use a valid name for the camel case input 2042 if ( oOptions.className && ! oOptions.sClass ) 2043 { 2044 oOptions.sClass = oOptions.className; 2045 } 2046 if ( oOptions.sClass ) { 2047 th.addClass( oOptions.sClass ); 2048 } 2049 2050 $.extend( oCol, oOptions ); 2051 _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" ); 2052 2053 /* iDataSort to be applied (backwards compatibility), but aDataSort will take 2054 * priority if defined 2055 */ 2056 if ( oOptions.iDataSort !== undefined ) 2057 { 2058 oCol.aDataSort = [ oOptions.iDataSort ]; 2059 } 2060 _fnMap( oCol, oOptions, "aDataSort" ); 2061 } 2062 2063 /* Cache the data get and set functions for speed */ 2064 var mDataSrc = oCol.mData; 2065 var mData = _fnGetObjectDataFn( mDataSrc ); 2066 var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null; 2067 2068 var attrTest = function( src ) { 2069 return typeof src === 'string' && src.indexOf('@') !== -1; 2070 }; 2071 oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && ( 2072 attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter) 2073 ); 2074 oCol._setter = null; 2075 2076 oCol.fnGetData = function (rowData, type, meta) { 2077 var innerData = mData( rowData, type, undefined, meta ); 2078 2079 return mRender && type ? 2080 mRender( innerData, type, rowData, meta ) : 2081 innerData; 2082 }; 2083 oCol.fnSetData = function ( rowData, val, meta ) { 2084 return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta ); 2085 }; 2086 2087 // Indicate if DataTables should read DOM data as an object or array 2088 // Used in _fnGetRowElements 2089 if ( typeof mDataSrc !== 'number' ) { 2090 oSettings._rowReadObject = true; 2091 } 2092 2093 /* Feature sorting overrides column specific when off */ 2094 if ( !oSettings.oFeatures.bSort ) 2095 { 2096 oCol.bSortable = false; 2097 th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called 2098 } 2099 2100 /* Check that the class assignment is correct for sorting */ 2101 var bAsc = $.inArray('asc', oCol.asSorting) !== -1; 2102 var bDesc = $.inArray('desc', oCol.asSorting) !== -1; 2103 if ( !oCol.bSortable || (!bAsc && !bDesc) ) 2104 { 2105 oCol.sSortingClass = oClasses.sSortableNone; 2106 oCol.sSortingClassJUI = ""; 2107 } 2108 else if ( bAsc && !bDesc ) 2109 { 2110 oCol.sSortingClass = oClasses.sSortableAsc; 2111 oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed; 2112 } 2113 else if ( !bAsc && bDesc ) 2114 { 2115 oCol.sSortingClass = oClasses.sSortableDesc; 2116 oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed; 2117 } 2118 else 2119 { 2120 oCol.sSortingClass = oClasses.sSortable; 2121 oCol.sSortingClassJUI = oClasses.sSortJUI; 2122 } 2123 } 2124 2125 2126 /** 2127 * Adjust the table column widths for new data. Note: you would probably want to 2128 * do a redraw after calling this function! 2129 * @param {object} settings dataTables settings object 2130 * @memberof DataTable#oApi 2131 */ 2132 function _fnAdjustColumnSizing ( settings ) 2133 { 2134 /* Not interested in doing column width calculation if auto-width is disabled */ 2135 if ( settings.oFeatures.bAutoWidth !== false ) 2136 { 2137 var columns = settings.aoColumns; 2138 2139 _fnCalculateColumnWidths( settings ); 2140 for ( var i=0 , iLen=columns.length ; i<iLen ; i++ ) 2141 { 2142 columns[i].nTh.style.width = columns[i].sWidth; 2143 } 2144 } 2145 2146 var scroll = settings.oScroll; 2147 if ( scroll.sY !== '' || scroll.sX !== '') 2148 { 2149 _fnScrollDraw( settings ); 2150 } 2151 2152 _fnCallbackFire( settings, null, 'column-sizing', [settings] ); 2153 } 2154 2155 2156 /** 2157 * Covert the index of a visible column to the index in the data array (take account 2158 * of hidden columns) 2159 * @param {object} oSettings dataTables settings object 2160 * @param {int} iMatch Visible column index to lookup 2161 * @returns {int} i the data index 2162 * @memberof DataTable#oApi 2163 */ 2164 function _fnVisibleToColumnIndex( oSettings, iMatch ) 2165 { 2166 var aiVis = _fnGetColumns( oSettings, 'bVisible' ); 2167 2168 return typeof aiVis[iMatch] === 'number' ? 2169 aiVis[iMatch] : 2170 null; 2171 } 2172 2173 2174 /** 2175 * Covert the index of an index in the data array and convert it to the visible 2176 * column index (take account of hidden columns) 2177 * @param {int} iMatch Column index to lookup 2178 * @param {object} oSettings dataTables settings object 2179 * @returns {int} i the data index 2180 * @memberof DataTable#oApi 2181 */ 2182 function _fnColumnIndexToVisible( oSettings, iMatch ) 2183 { 2184 var aiVis = _fnGetColumns( oSettings, 'bVisible' ); 2185 var iPos = $.inArray( iMatch, aiVis ); 2186 2187 return iPos !== -1 ? iPos : null; 2188 } 2189 2190 2191 /** 2192 * Get the number of visible columns 2193 * @param {object} oSettings dataTables settings object 2194 * @returns {int} i the number of visible columns 2195 * @memberof DataTable#oApi 2196 */ 2197 function _fnVisbleColumns( oSettings ) 2198 { 2199 var vis = 0; 2200 2201 // No reduce in IE8, use a loop for now 2202 $.each( oSettings.aoColumns, function ( i, col ) { 2203 if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) { 2204 vis++; 2205 } 2206 } ); 2207 2208 return vis; 2209 } 2210 2211 2212 /** 2213 * Get an array of column indexes that match a given property 2214 * @param {object} oSettings dataTables settings object 2215 * @param {string} sParam Parameter in aoColumns to look for - typically 2216 * bVisible or bSearchable 2217 * @returns {array} Array of indexes with matched properties 2218 * @memberof DataTable#oApi 2219 */ 2220 function _fnGetColumns( oSettings, sParam ) 2221 { 2222 var a = []; 2223 2224 $.map( oSettings.aoColumns, function(val, i) { 2225 if ( val[sParam] ) { 2226 a.push( i ); 2227 } 2228 } ); 2229 2230 return a; 2231 } 2232 2233 2234 /** 2235 * Calculate the 'type' of a column 2236 * @param {object} settings dataTables settings object 2237 * @memberof DataTable#oApi 2238 */ 2239 function _fnColumnTypes ( settings ) 2240 { 2241 var columns = settings.aoColumns; 2242 var data = settings.aoData; 2243 var types = DataTable.ext.type.detect; 2244 var i, ien, j, jen, k, ken; 2245 var col, cell, detectedType, cache; 2246 2247 // For each column, spin over the 2248 for ( i=0, ien=columns.length ; i<ien ; i++ ) { 2249 col = columns[i]; 2250 cache = []; 2251 2252 if ( ! col.sType && col._sManualType ) { 2253 col.sType = col._sManualType; 2254 } 2255 else if ( ! col.sType ) { 2256 for ( j=0, jen=types.length ; j<jen ; j++ ) { 2257 for ( k=0, ken=data.length ; k<ken ; k++ ) { 2258 // Use a cache array so we only need to get the type data 2259 // from the formatter once (when using multiple detectors) 2260 if ( cache[k] === undefined ) { 2261 cache[k] = _fnGetCellData( settings, k, i, 'type' ); 2262 } 2263 2264 detectedType = types[j]( cache[k], settings ); 2265 2266 // If null, then this type can't apply to this column, so 2267 // rather than testing all cells, break out. There is an 2268 // exception for the last type which is `html`. We need to 2269 // scan all rows since it is possible to mix string and HTML 2270 // types 2271 if ( ! detectedType && j !== types.length-1 ) { 2272 break; 2273 } 2274 2275 // Only a single match is needed for html type since it is 2276 // bottom of the pile and very similar to string 2277 if ( detectedType === 'html' ) { 2278 break; 2279 } 2280 } 2281 2282 // Type is valid for all data points in the column - use this 2283 // type 2284 if ( detectedType ) { 2285 col.sType = detectedType; 2286 break; 2287 } 2288 } 2289 2290 // Fall back - if no type was detected, always use string 2291 if ( ! col.sType ) { 2292 col.sType = 'string'; 2293 } 2294 } 2295 } 2296 } 2297 2298 2299 /** 2300 * Take the column definitions and static columns arrays and calculate how 2301 * they relate to column indexes. The callback function will then apply the 2302 * definition found for a column to a suitable configuration object. 2303 * @param {object} oSettings dataTables settings object 2304 * @param {array} aoColDefs The aoColumnDefs array that is to be applied 2305 * @param {array} aoCols The aoColumns array that defines columns individually 2306 * @param {function} fn Callback function - takes two parameters, the calculated 2307 * column index and the definition for that column. 2308 * @memberof DataTable#oApi 2309 */ 2310 function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn ) 2311 { 2312 var i, iLen, j, jLen, k, kLen, def; 2313 var columns = oSettings.aoColumns; 2314 2315 // Column definitions with aTargets 2316 if ( aoColDefs ) 2317 { 2318 /* Loop over the definitions array - loop in reverse so first instance has priority */ 2319 for ( i=aoColDefs.length-1 ; i>=0 ; i-- ) 2320 { 2321 def = aoColDefs[i]; 2322 2323 /* Each definition can target multiple columns, as it is an array */ 2324 var aTargets = def.targets !== undefined ? 2325 def.targets : 2326 def.aTargets; 2327 2328 if ( ! $.isArray( aTargets ) ) 2329 { 2330 aTargets = [ aTargets ]; 2331 } 2332 2333 for ( j=0, jLen=aTargets.length ; j<jLen ; j++ ) 2334 { 2335 if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 ) 2336 { 2337 /* Add columns that we don't yet know about */ 2338 while( columns.length <= aTargets[j] ) 2339 { 2340 _fnAddColumn( oSettings ); 2341 } 2342 2343 /* Integer, basic index */ 2344 fn( aTargets[j], def ); 2345 } 2346 else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 ) 2347 { 2348 /* Negative integer, right to left column counting */ 2349 fn( columns.length+aTargets[j], def ); 2350 } 2351 else if ( typeof aTargets[j] === 'string' ) 2352 { 2353 /* Class name matching on TH element */ 2354 for ( k=0, kLen=columns.length ; k<kLen ; k++ ) 2355 { 2356 if ( aTargets[j] == "_all" || 2357 $(columns[k].nTh).hasClass( aTargets[j] ) ) 2358 { 2359 fn( k, def ); 2360 } 2361 } 2362 } 2363 } 2364 } 2365 } 2366 2367 // Statically defined columns array 2368 if ( aoCols ) 2369 { 2370 for ( i=0, iLen=aoCols.length ; i<iLen ; i++ ) 2371 { 2372 fn( i, aoCols[i] ); 2373 } 2374 } 2375 } 2376 2377 /** 2378 * Add a data array to the table, creating DOM node etc. This is the parallel to 2379 * _fnGatherData, but for adding rows from a Javascript source, rather than a 2380 * DOM source. 2381 * @param {object} oSettings dataTables settings object 2382 * @param {array} aData data array to be added 2383 * @param {node} [nTr] TR element to add to the table - optional. If not given, 2384 * DataTables will create a row automatically 2385 * @param {array} [anTds] Array of TD|TH elements for the row - must be given 2386 * if nTr is. 2387 * @returns {int} >=0 if successful (index of new aoData entry), -1 if failed 2388 * @memberof DataTable#oApi 2389 */ 2390 function _fnAddData ( oSettings, aDataIn, nTr, anTds ) 2391 { 2392 /* Create the object for storing information about this new row */ 2393 var iRow = oSettings.aoData.length; 2394 var oData = $.extend( true, {}, DataTable.models.oRow, { 2395 src: nTr ? 'dom' : 'data', 2396 idx: iRow 2397 } ); 2398 2399 oData._aData = aDataIn; 2400 oSettings.aoData.push( oData ); 2401 2402 /* Create the cells */ 2403 var nTd, sThisType; 2404 var columns = oSettings.aoColumns; 2405 2406 // Invalidate the column types as the new data needs to be revalidated 2407 for ( var i=0, iLen=columns.length ; i<iLen ; i++ ) 2408 { 2409 columns[i].sType = null; 2410 } 2411 2412 /* Add to the display array */ 2413 oSettings.aiDisplayMaster.push( iRow ); 2414 2415 var id = oSettings.rowIdFn( aDataIn ); 2416 if ( id !== undefined ) { 2417 oSettings.aIds[ id ] = oData; 2418 } 2419 2420 /* Create the DOM information, or register it if already present */ 2421 if ( nTr || ! oSettings.oFeatures.bDeferRender ) 2422 { 2423 _fnCreateTr( oSettings, iRow, nTr, anTds ); 2424 } 2425 2426 return iRow; 2427 } 2428 2429 2430 /** 2431 * Add one or more TR elements to the table. Generally we'd expect to 2432 * use this for reading data from a DOM sourced table, but it could be 2433 * used for an TR element. Note that if a TR is given, it is used (i.e. 2434 * it is not cloned). 2435 * @param {object} settings dataTables settings object 2436 * @param {array|node|jQuery} trs The TR element(s) to add to the table 2437 * @returns {array} Array of indexes for the added rows 2438 * @memberof DataTable#oApi 2439 */ 2440 function _fnAddTr( settings, trs ) 2441 { 2442 var row; 2443 2444 // Allow an individual node to be passed in 2445 if ( ! (trs instanceof $) ) { 2446 trs = $(trs); 2447 } 2448 2449 return trs.map( function (i, el) { 2450 row = _fnGetRowElements( settings, el ); 2451 return _fnAddData( settings, row.data, el, row.cells ); 2452 } ); 2453 } 2454 2455 2456 /** 2457 * Take a TR element and convert it to an index in aoData 2458 * @param {object} oSettings dataTables settings object 2459 * @param {node} n the TR element to find 2460 * @returns {int} index if the node is found, null if not 2461 * @memberof DataTable#oApi 2462 */ 2463 function _fnNodeToDataIndex( oSettings, n ) 2464 { 2465 return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null; 2466 } 2467 2468 2469 /** 2470 * Take a TD element and convert it into a column data index (not the visible index) 2471 * @param {object} oSettings dataTables settings object 2472 * @param {int} iRow The row number the TD/TH can be found in 2473 * @param {node} n The TD/TH element to find 2474 * @returns {int} index if the node is found, -1 if not 2475 * @memberof DataTable#oApi 2476 */ 2477 function _fnNodeToColumnIndex( oSettings, iRow, n ) 2478 { 2479 return $.inArray( n, oSettings.aoData[ iRow ].anCells ); 2480 } 2481 2482 2483 /** 2484 * Get the data for a given cell from the internal cache, taking into account data mapping 2485 * @param {object} settings dataTables settings object 2486 * @param {int} rowIdx aoData row id 2487 * @param {int} colIdx Column index 2488 * @param {string} type data get type ('display', 'type' 'filter' 'sort') 2489 * @returns {*} Cell data 2490 * @memberof DataTable#oApi 2491 */ 2492 function _fnGetCellData( settings, rowIdx, colIdx, type ) 2493 { 2494 var draw = settings.iDraw; 2495 var col = settings.aoColumns[colIdx]; 2496 var rowData = settings.aoData[rowIdx]._aData; 2497 var defaultContent = col.sDefaultContent; 2498 var cellData = col.fnGetData( rowData, type, { 2499 settings: settings, 2500 row: rowIdx, 2501 col: colIdx 2502 } ); 2503 2504 if ( cellData === undefined ) { 2505 if ( settings.iDrawError != draw && defaultContent === null ) { 2506 _fnLog( settings, 0, "Requested unknown parameter "+ 2507 (typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+ 2508 " for row "+rowIdx+", column "+colIdx, 4 ); 2509 settings.iDrawError = draw; 2510 } 2511 return defaultContent; 2512 } 2513 2514 // When the data source is null and a specific data type is requested (i.e. 2515 // not the original data), we can use default column data 2516 if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) { 2517 cellData = defaultContent; 2518 } 2519 else if ( typeof cellData === 'function' ) { 2520 // If the data source is a function, then we run it and use the return, 2521 // executing in the scope of the data object (for instances) 2522 return cellData.call( rowData ); 2523 } 2524 2525 if ( cellData === null && type == 'display' ) { 2526 return ''; 2527 } 2528 return cellData; 2529 } 2530 2531 2532 /** 2533 * Set the value for a specific cell, into the internal data cache 2534 * @param {object} settings dataTables settings object 2535 * @param {int} rowIdx aoData row id 2536 * @param {int} colIdx Column index 2537 * @param {*} val Value to set 2538 * @memberof DataTable#oApi 2539 */ 2540 function _fnSetCellData( settings, rowIdx, colIdx, val ) 2541 { 2542 var col = settings.aoColumns[colIdx]; 2543 var rowData = settings.aoData[rowIdx]._aData; 2544 2545 col.fnSetData( rowData, val, { 2546 settings: settings, 2547 row: rowIdx, 2548 col: colIdx 2549 } ); 2550 } 2551 2552 2553 // Private variable that is used to match action syntax in the data property object 2554 var __reArray = /\[.*?\]$/; 2555 var __reFn = /\(\)$/; 2556 2557 /** 2558 * Split string on periods, taking into account escaped periods 2559 * @param {string} str String to split 2560 * @return {array} Split string 2561 */ 2562 function _fnSplitObjNotation( str ) 2563 { 2564 return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) { 2565 return s.replace(/\\\./g, '.'); 2566 } ); 2567 } 2568 2569 2570 /** 2571 * Return a function that can be used to get data from a source object, taking 2572 * into account the ability to use nested objects as a source 2573 * @param {string|int|function} mSource The data source for the object 2574 * @returns {function} Data get function 2575 * @memberof DataTable#oApi 2576 */ 2577 function _fnGetObjectDataFn( mSource ) 2578 { 2579 if ( $.isPlainObject( mSource ) ) 2580 { 2581 /* Build an object of get functions, and wrap them in a single call */ 2582 var o = {}; 2583 $.each( mSource, function (key, val) { 2584 if ( val ) { 2585 o[key] = _fnGetObjectDataFn( val ); 2586 } 2587 } ); 2588 2589 return function (data, type, row, meta) { 2590 var t = o[type] || o._; 2591 return t !== undefined ? 2592 t(data, type, row, meta) : 2593 data; 2594 }; 2595 } 2596 else if ( mSource === null ) 2597 { 2598 /* Give an empty string for rendering / sorting etc */ 2599 return function (data) { // type, row and meta also passed, but not used 2600 return data; 2601 }; 2602 } 2603 else if ( typeof mSource === 'function' ) 2604 { 2605 return function (data, type, row, meta) { 2606 return mSource( data, type, row, meta ); 2607 }; 2608 } 2609 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || 2610 mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) ) 2611 { 2612 /* If there is a . in the source string then the data source is in a 2613 * nested object so we loop over the data for each level to get the next 2614 * level down. On each loop we test for undefined, and if found immediately 2615 * return. This allows entire objects to be missing and sDefaultContent to 2616 * be used if defined, rather than throwing an error 2617 */ 2618 var fetchData = function (data, type, src) { 2619 var arrayNotation, funcNotation, out, innerSrc; 2620 2621 if ( src !== "" ) 2622 { 2623 var a = _fnSplitObjNotation( src ); 2624 2625 for ( var i=0, iLen=a.length ; i<iLen ; i++ ) 2626 { 2627 // Check if we are dealing with special notation 2628 arrayNotation = a[i].match(__reArray); 2629 funcNotation = a[i].match(__reFn); 2630 2631 if ( arrayNotation ) 2632 { 2633 // Array notation 2634 a[i] = a[i].replace(__reArray, ''); 2635 2636 // Condition allows simply [] to be passed in 2637 if ( a[i] !== "" ) { 2638 data = data[ a[i] ]; 2639 } 2640 out = []; 2641 2642 // Get the remainder of the nested object to get 2643 a.splice( 0, i+1 ); 2644 innerSrc = a.join('.'); 2645 2646 // Traverse each entry in the array getting the properties requested 2647 if ( $.isArray( data ) ) { 2648 for ( var j=0, jLen=data.length ; j<jLen ; j++ ) { 2649 out.push( fetchData( data[j], type, innerSrc ) ); 2650 } 2651 } 2652 2653 // If a string is given in between the array notation indicators, that 2654 // is used to join the strings together, otherwise an array is returned 2655 var join = arrayNotation[0].substring(1, arrayNotation[0].length-1); 2656 data = (join==="") ? out : out.join(join); 2657 2658 // The inner call to fetchData has already traversed through the remainder 2659 // of the source requested, so we exit from the loop 2660 break; 2661 } 2662 else if ( funcNotation ) 2663 { 2664 // Function call 2665 a[i] = a[i].replace(__reFn, ''); 2666 data = data[ a[i] ](); 2667 continue; 2668 } 2669 2670 if ( data === null || data[ a[i] ] === undefined ) 2671 { 2672 return undefined; 2673 } 2674 data = data[ a[i] ]; 2675 } 2676 } 2677 2678 return data; 2679 }; 2680 2681 return function (data, type) { // row and meta also passed, but not used 2682 return fetchData( data, type, mSource ); 2683 }; 2684 } 2685 else 2686 { 2687 /* Array or flat object mapping */ 2688 return function (data, type) { // row and meta also passed, but not used 2689 return data[mSource]; 2690 }; 2691 } 2692 } 2693 2694 2695 /** 2696 * Return a function that can be used to set data from a source object, taking 2697 * into account the ability to use nested objects as a source 2698 * @param {string|int|function} mSource The data source for the object 2699 * @returns {function} Data set function 2700 * @memberof DataTable#oApi 2701 */ 2702 function _fnSetObjectDataFn( mSource ) 2703 { 2704 if ( $.isPlainObject( mSource ) ) 2705 { 2706 /* Unlike get, only the underscore (global) option is used for for 2707 * setting data since we don't know the type here. This is why an object 2708 * option is not documented for `mData` (which is read/write), but it is 2709 * for `mRender` which is read only. 2710 */ 2711 return _fnSetObjectDataFn( mSource._ ); 2712 } 2713 else if ( mSource === null ) 2714 { 2715 /* Nothing to do when the data source is null */ 2716 return function () {}; 2717 } 2718 else if ( typeof mSource === 'function' ) 2719 { 2720 return function (data, val, meta) { 2721 mSource( data, 'set', val, meta ); 2722 }; 2723 } 2724 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || 2725 mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) ) 2726 { 2727 /* Like the get, we need to get data from a nested object */ 2728 var setData = function (data, val, src) { 2729 var a = _fnSplitObjNotation( src ), b; 2730 var aLast = a[a.length-1]; 2731 var arrayNotation, funcNotation, o, innerSrc; 2732 2733 for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ ) 2734 { 2735 // Check if we are dealing with an array notation request 2736 arrayNotation = a[i].match(__reArray); 2737 funcNotation = a[i].match(__reFn); 2738 2739 if ( arrayNotation ) 2740 { 2741 a[i] = a[i].replace(__reArray, ''); 2742 data[ a[i] ] = []; 2743 2744 // Get the remainder of the nested object to set so we can recurse 2745 b = a.slice(); 2746 b.splice( 0, i+1 ); 2747 innerSrc = b.join('.'); 2748 2749 // Traverse each entry in the array setting the properties requested 2750 if ( $.isArray( val ) ) 2751 { 2752 for ( var j=0, jLen=val.length ; j<jLen ; j++ ) 2753 { 2754 o = {}; 2755 setData( o, val[j], innerSrc ); 2756 data[ a[i] ].push( o ); 2757 } 2758 } 2759 else 2760 { 2761 // We've been asked to save data to an array, but it 2762 // isn't array data to be saved. Best that can be done 2763 // is to just save the value. 2764 data[ a[i] ] = val; 2765 } 2766 2767 // The inner call to setData has already traversed through the remainder 2768 // of the source and has set the data, thus we can exit here 2769 return; 2770 } 2771 else if ( funcNotation ) 2772 { 2773 // Function call 2774 a[i] = a[i].replace(__reFn, ''); 2775 data = data[ a[i] ]( val ); 2776 } 2777 2778 // If the nested object doesn't currently exist - since we are 2779 // trying to set the value - create it 2780 if ( data[ a[i] ] === null || data[ a[i] ] === undefined ) 2781 { 2782 data[ a[i] ] = {}; 2783 } 2784 data = data[ a[i] ]; 2785 } 2786 2787 // Last item in the input - i.e, the actual set 2788 if ( aLast.match(__reFn ) ) 2789 { 2790 // Function call 2791 data = data[ aLast.replace(__reFn, '') ]( val ); 2792 } 2793 else 2794 { 2795 // If array notation is used, we just want to strip it and use the property name 2796 // and assign the value. If it isn't used, then we get the result we want anyway 2797 data[ aLast.replace(__reArray, '') ] = val; 2798 } 2799 }; 2800 2801 return function (data, val) { // meta is also passed in, but not used 2802 return setData( data, val, mSource ); 2803 }; 2804 } 2805 else 2806 { 2807 /* Array or flat object mapping */ 2808 return function (data, val) { // meta is also passed in, but not used 2809 data[mSource] = val; 2810 }; 2811 } 2812 } 2813 2814 2815 /** 2816 * Return an array with the full table data 2817 * @param {object} oSettings dataTables settings object 2818 * @returns array {array} aData Master data array 2819 * @memberof DataTable#oApi 2820 */ 2821 function _fnGetDataMaster ( settings ) 2822 { 2823 return _pluck( settings.aoData, '_aData' ); 2824 } 2825 2826 2827 /** 2828 * Nuke the table 2829 * @param {object} oSettings dataTables settings object 2830 * @memberof DataTable#oApi 2831 */ 2832 function _fnClearTable( settings ) 2833 { 2834 settings.aoData.length = 0; 2835 settings.aiDisplayMaster.length = 0; 2836 settings.aiDisplay.length = 0; 2837 settings.aIds = {}; 2838 } 2839 2840 2841 /** 2842 * Take an array of integers (index array) and remove a target integer (value - not 2843 * the key!) 2844 * @param {array} a Index array to target 2845 * @param {int} iTarget value to find 2846 * @memberof DataTable#oApi 2847 */ 2848 function _fnDeleteIndex( a, iTarget, splice ) 2849 { 2850 var iTargetIndex = -1; 2851 2852 for ( var i=0, iLen=a.length ; i<iLen ; i++ ) 2853 { 2854 if ( a[i] == iTarget ) 2855 { 2856 iTargetIndex = i; 2857 } 2858 else if ( a[i] > iTarget ) 2859 { 2860 a[i]--; 2861 } 2862 } 2863 2864 if ( iTargetIndex != -1 && splice === undefined ) 2865 { 2866 a.splice( iTargetIndex, 1 ); 2867 } 2868 } 2869 2870 2871 /**
2872 * Mark cached data as invalid such that a re-read of the data will occur when 2873 * the cached data is next requested. Also update from the data source object. 2874 * 2875 * @param {object} settings DataTables settings object 2876 * @param {int} rowIdx Row index to invalidate 2877 * @param {string} [src] Source to invalidate from: undefined, 'auto', 'dom' 2878 * or 'data' 2879 * @param {int} [colIdx] Column index to invalidate. If undefined the whole 2880 * row will be invalidated 2881 * @memberof DataTable#oApi 2882 * 2883 * @todo For the modularisation of v1.11 this will need to become a callback, so 2884 * the sort and filter methods can subscribe to it. That will required 2885 * initialisation options for sorting, which is why it is not already baked in 2886 */ 2887 function _fnInvalidate( settings, rowIdx, src, colIdx ) 2888 { 2889 var row = settings.aoData[ rowIdx ]; 2890 var i, ien; 2891 var cellWrite = function ( cell, col ) { 2892 // This is very frustrating, but in IE if you just write directly 2893 // to innerHTML, and elements that are overwritten are GC'ed, 2894 // even if there is a reference to them elsewhere 2895 while ( cell.childNodes.length ) { 2896 cell.removeChild( cell.firstChild ); 2897 } 2898 2899 cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' ); 2900 }; 2901 2902 // Are we reading last data from DOM or the data object? 2903 if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) { 2904 // Read the data from the DOM 2905 row._aData = _fnGetRowElements( 2906 settings, row, colIdx, colIdx === undefined ? undefined : row._aData 2907 ) 2908 .data; 2909 } 2910 else { 2911 // Reading from data object, update the DOM 2912 var cells = row.anCells; 2913 2914 if ( cells ) { 2915 if ( colIdx !== undefined ) { 2916 cellWrite( cells[colIdx], colIdx ); 2917 } 2918 else { 2919 for ( i=0, ien=cells.length ; i<ien ; i++ ) { 2920 cellWrite( cells[i], i ); 2921 } 2922 } 2923 } 2924 } 2925 2926 // For both row and cell invalidation, the cached data for sorting and 2927 // filtering is nulled out 2928 row._aSortData = null; 2929 row._aFilterData = null; 2930 2931 // Invalidate the type for a specific column (if given) or all columns since 2932 // the data might have changed 2933 var cols = settings.aoColumns; 2934 if ( colIdx !== undefined ) { 2935 cols[ colIdx ].sType = null; 2936 } 2937 else { 2938 for ( i=0, ien=cols.length ; i<ien ; i++ ) { 2939 cols[i].sType = null; 2940 } 2941 2942 // Update DataTables special `DT_*` attributes for the row 2943 _fnRowAttributes( settings, row ); 2944 } 2945 } 2946 2947 2948 /** 2949 * Build a data source object from an HTML row, reading the contents of the 2950 * cells that are in the row. 2951 * 2952 * @param {object} settings DataTables settings object 2953 * @param {node|object} TR element from which to read data or existing row 2954 * object from which to re-read the data from the cells 2955 * @param {int} [colIdx] Optional column index 2956 * @param {array|object} [d] Data source object. If `colIdx` is given then this 2957 * parameter should also be given and will be used to write the data into. 2958 * Only the column in question will be written 2959 * @returns {object} Object with two parameters: `data` the data read, in 2960 * document order, and `cells` and array of nodes (they can be useful to the 2961 * caller, so rather than needing a second traversal to get them, just return 2962 * them from here). 2963 * @memberof DataTable#oApi 2964 */ 2965 function _fnGetRowElements( settings, row, colIdx, d ) 2966 { 2967 var 2968 tds = [], 2969 td = row.firstChild, 2970 name, col, o, i=0, contents, 2971 columns = settings.aoColumns, 2972 objectRead = settings._rowReadObject; 2973 2974 // Allow the data object to be passed in, or construct 2975 d = d !== undefined ? 2976 d : 2977 objectRead ? 2978 {} : 2979 []; 2980 2981 var attr = function ( str, td ) { 2982 if ( typeof str === 'string' ) { 2983 var idx = str.indexOf('@'); 2984 2985 if ( idx !== -1 ) { 2986 var attr = str.substring( idx+1 ); 2987 var setter = _fnSetObjectDataFn( str ); 2988 setter( d, td.getAttribute( attr ) ); 2989 } 2990 } 2991 }; 2992 2993 // Read data from a cell and store into the data object 2994 var cellProcess = function ( cell ) { 2995 if ( colIdx === undefined || colIdx === i ) { 2996 col = columns[i]; 2997 contents = $.trim(cell.innerHTML); 2998 2999 if ( col && col._bAttrSrc ) { 3000 var setter = _fnSetObjectDataFn( col.mData._ ); 3001 setter( d, contents ); 3002 3003 attr( col.mData.sort, cell ); 3004 attr( col.mData.type, cell ); 3005 attr( col.mData.filter, cell ); 3006 } 3007 else { 3008 // Depending on the `data` option for the columns the data can 3009 // be read to either an object or an array.
vendor: 11,053 bytes, lines 3010-3433
3010 if ( objectRead ) { 3011 if ( ! col._setter ) { 3012 // Cache the setter function 3013 col._setter = _fnSetObjectDataFn( col.mData ); 3014 } 3015 col._setter( d, contents ); 3016 } 3017 else { 3018 d[i] = contents; 3019 } 3020 } 3021 } 3022 3023 i++; 3024 }; 3025 3026 if ( td ) { 3027 // `tr` element was passed in 3028 while ( td ) { 3029 name = td.nodeName.toUpperCase(); 3030 3031 if ( name == "TD" || name == "TH" ) { 3032 cellProcess( td ); 3033 tds.push( td ); 3034 } 3035 3036 td = td.nextSibling; 3037 } 3038 } 3039 else { 3040 // Existing row object passed in 3041 tds = row.anCells; 3042 3043 for ( var j=0, jen=tds.length ; j<jen ; j++ ) { 3044 cellProcess( tds[j] ); 3045 } 3046 } 3047 3048 // Read the ID from the DOM if present 3049 var rowNode = row.firstChild ? row : row.nTr; 3050 3051 if ( rowNode ) { 3052 var id = rowNode.getAttribute( 'id' ); 3053 3054 if ( id ) { 3055 _fnSetObjectDataFn( settings.rowId )( d, id ); 3056 } 3057 } 3058 3059 return { 3060 data: d, 3061 cells: tds 3062 }; 3063 } 3064 /** 3065 * Create a new TR element (and it's TD children) for a row 3066 * @param {object} oSettings dataTables settings object 3067 * @param {int} iRow Row to consider 3068 * @param {node} [nTrIn] TR element to add to the table - optional. If not given, 3069 * DataTables will create a row automatically 3070 * @param {array} [anTds] Array of TD|TH elements for the row - must be given 3071 * if nTr is. 3072 * @memberof DataTable#oApi 3073 */ 3074 function _fnCreateTr ( oSettings, iRow, nTrIn, anTds ) 3075 { 3076 var 3077 row = oSettings.aoData[iRow], 3078 rowData = row._aData, 3079 cells = [], 3080 nTr, nTd, oCol, 3081 i, iLen, create; 3082 3083 if ( row.nTr === null ) 3084 { 3085 nTr = nTrIn || document.createElement('tr'); 3086 3087 row.nTr = nTr; 3088 row.anCells = cells; 3089 3090 /* Use a private property on the node to allow reserve mapping from the node 3091 * to the aoData array for fast look up 3092 */ 3093 nTr._DT_RowIndex = iRow; 3094 3095 /* Special parameters can be given by the data source to be used on the row */ 3096 _fnRowAttributes( oSettings, row ); 3097 3098 /* Process each column */ 3099 for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) 3100 { 3101 oCol = oSettings.aoColumns[i]; 3102 create = nTrIn ? false : true; 3103 3104 nTd = create ? document.createElement( oCol.sCellType ) : anTds[i]; 3105 nTd._DT_CellIndex = { 3106 row: iRow, 3107 column: i 3108 }; 3109 3110 cells.push( nTd ); 3111 3112 // Need to create the HTML if new, or if a rendering function is defined 3113 if ( create || ((!nTrIn || oCol.mRender || oCol.mData !== i) && 3114 (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display') 3115 )) { 3116 nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' ); 3117 } 3118 3119 /* Add user defined class */ 3120 if ( oCol.sClass ) 3121 { 3122 nTd.className += ' '+oCol.sClass; 3123 } 3124 3125 // Visibility - add or remove as required 3126 if ( oCol.bVisible && ! nTrIn ) 3127 { 3128 nTr.appendChild( nTd ); 3129 } 3130 else if ( ! oCol.bVisible && nTrIn ) 3131 { 3132 nTd.parentNode.removeChild( nTd ); 3133 } 3134 3135 if ( oCol.fnCreatedCell ) 3136 { 3137 oCol.fnCreatedCell.call( oSettings.oInstance, 3138 nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i 3139 ); 3140 } 3141 } 3142 3143 _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow, cells] ); 3144 } 3145 3146 // Remove once webkit bug 131819 and Chromium bug 365619 have been resolved 3147 // and deployed 3148 row.nTr.setAttribute( 'role', 'row' ); 3149 } 3150 3151 3152 /** 3153 * Add attributes to a row based on the special `DT_*` parameters in a data 3154 * source object. 3155 * @param {object} settings DataTables settings object 3156 * @param {object} DataTables row object for the row to be modified 3157 * @memberof DataTable#oApi 3158 */ 3159 function _fnRowAttributes( settings, row ) 3160 { 3161 var tr = row.nTr; 3162 var data = row._aData; 3163 3164 if ( tr ) { 3165 var id = settings.rowIdFn( data ); 3166 3167 if ( id ) { 3168 tr.id = id; 3169 } 3170 3171 if ( data.DT_RowClass ) { 3172 // Remove any classes added by DT_RowClass before 3173 var a = data.DT_RowClass.split(' '); 3174 row.__rowc = row.__rowc ? 3175 _unique( row.__rowc.concat( a ) ) : 3176 a; 3177 3178 $(tr) 3179 .removeClass( row.__rowc.join(' ') ) 3180 .addClass( data.DT_RowClass ); 3181 } 3182 3183 if ( data.DT_RowAttr ) { 3184 $(tr).attr( data.DT_RowAttr ); 3185 } 3186 3187 if ( data.DT_RowData ) { 3188 $(tr).data( data.DT_RowData ); 3189 } 3190 } 3191 } 3192 3193 3194 /** 3195 * Create the HTML header for the table 3196 * @param {object} oSettings dataTables settings object 3197 * @memberof DataTable#oApi 3198 */ 3199 function _fnBuildHead( oSettings ) 3200 { 3201 var i, ien, cell, row, column; 3202 var thead = oSettings.nTHead; 3203 var tfoot = oSettings.nTFoot; 3204 var createHeader = $('th, td', thead).length === 0; 3205 var classes = oSettings.oClasses; 3206 var columns = oSettings.aoColumns; 3207 3208 if ( createHeader ) { 3209 row = $('<tr/>').appendTo( thead ); 3210 } 3211 3212 for ( i=0, ien=columns.length ; i<ien ; i++ ) { 3213 column = columns[i]; 3214 cell = $( column.nTh ).addClass( column.sClass ); 3215 3216 if ( createHeader ) { 3217 cell.appendTo( row ); 3218 } 3219 3220 // 1.11 move into sorting 3221 if ( oSettings.oFeatures.bSort ) { 3222 cell.addClass( column.sSortingClass ); 3223 3224 if ( column.bSortable !== false ) { 3225 cell 3226 .attr( 'tabindex', oSettings.iTabIndex ) 3227 .attr( 'aria-controls', oSettings.sTableId ); 3228 3229 _fnSortAttachListener( oSettings, column.nTh, i ); 3230 } 3231 } 3232 3233 if ( column.sTitle != cell[0].innerHTML ) { 3234 cell.html( column.sTitle ); 3235 } 3236 3237 _fnRenderer( oSettings, 'header' )( 3238 oSettings, cell, column, classes 3239 ); 3240 } 3241 3242 if ( createHeader ) { 3243 _fnDetectHeader( oSettings.aoHeader, thead ); 3244 } 3245 3246 /* ARIA role for the rows */ 3247 $(thead).find('>tr').attr('role', 'row'); 3248 3249 /* Deal with the footer - add classes if required */ 3250 $(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH ); 3251 $(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH ); 3252 3253 // Cache the footer cells. Note that we only take the cells from the first 3254 // row in the footer. If there is more than one row the user wants to 3255 // interact with, they need to use the table().foot() method. Note also this 3256 // allows cells to be used for multiple columns using colspan 3257 if ( tfoot !== null ) { 3258 var cells = oSettings.aoFooter[0]; 3259 3260 for ( i=0, ien=cells.length ; i<ien ; i++ ) { 3261 column = columns[i]; 3262 column.nTf = cells[i].cell; 3263 3264 if ( column.sClass ) { 3265 $(column.nTf).addClass( column.sClass ); 3266 } 3267 } 3268 } 3269 } 3270 3271 3272 /** 3273 * Draw the header (or footer) element based on the column visibility states. The 3274 * methodology here is to use the layout array from _fnDetectHeader, modified for 3275 * the instantaneous column visibility, to construct the new layout. The grid is 3276 * traversed over cell at a time in a rows x columns grid fashion, although each 3277 * cell insert can cover multiple elements in the grid - which is tracks using the 3278 * aApplied array. Cell inserts in the grid will only occur where there isn't 3279 * already a cell in that position. 3280 * @param {object} oSettings dataTables settings object 3281 * @param array {objects} aoSource Layout array from _fnDetectHeader 3282 * @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc, 3283 * @memberof DataTable#oApi 3284 */ 3285 function _fnDrawHead( oSettings, aoSource, bIncludeHidden ) 3286 { 3287 var i, iLen, j, jLen, k, kLen, n, nLocalTr; 3288 var aoLocal = []; 3289 var aApplied = []; 3290 var iColumns = oSettings.aoColumns.length; 3291 var iRowspan, iColspan; 3292 3293 if ( ! aoSource ) 3294 { 3295 return; 3296 } 3297 3298 if ( bIncludeHidden === undefined ) 3299 { 3300 bIncludeHidden = false; 3301 } 3302 3303 /* Make a copy of the master layout array, but without the visible columns in it */ 3304 for ( i=0, iLen=aoSource.length ; i<iLen ; i++ ) 3305 { 3306 aoLocal[i] = aoSource[i].slice(); 3307 aoLocal[i].nTr = aoSource[i].nTr; 3308 3309 /* Remove any columns which are currently hidden */ 3310 for ( j=iColumns-1 ; j>=0 ; j-- ) 3311 { 3312 if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden ) 3313 { 3314 aoLocal[i].splice( j, 1 ); 3315 } 3316 } 3317 3318 /* Prep the applied array - it needs an element for each row */ 3319 aApplied.push( [] ); 3320 } 3321 3322 for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ ) 3323 { 3324 nLocalTr = aoLocal[i].nTr; 3325 3326 /* All cells are going to be replaced, so empty out the row */ 3327 if ( nLocalTr ) 3328 { 3329 while( (n = nLocalTr.firstChild) ) 3330 { 3331 nLocalTr.removeChild( n ); 3332 } 3333 } 3334 3335 for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ ) 3336 { 3337 iRowspan = 1; 3338 iColspan = 1; 3339 3340 /* Check to see if there is already a cell (row/colspan) covering our target 3341 * insert point. If there is, then there is nothing to do. 3342 */ 3343 if ( aApplied[i][j] === undefined ) 3344 { 3345 nLocalTr.appendChild( aoLocal[i][j].cell ); 3346 aApplied[i][j] = 1; 3347 3348 /* Expand the cell to cover as many rows as needed */ 3349 while ( aoLocal[i+iRowspan] !== undefined && 3350 aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell ) 3351 { 3352 aApplied[i+iRowspan][j] = 1; 3353 iRowspan++; 3354 } 3355 3356 /* Expand the cell to cover as many columns as needed */ 3357 while ( aoLocal[i][j+iColspan] !== undefined && 3358 aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell ) 3359 { 3360 /* Must update the applied array over the rows for the columns */ 3361 for ( k=0 ; k<iRowspan ; k++ ) 3362 { 3363 aApplied[i+k][j+iColspan] = 1; 3364 } 3365 iColspan++; 3366 } 3367 3368 /* Do the actual expansion in the DOM */ 3369 $(aoLocal[i][j].cell) 3370 .attr('rowspan', iRowspan) 3371 .attr('colspan', iColspan); 3372 } 3373 } 3374 } 3375 } 3376 3377 3378 /** 3379 * Insert the required TR nodes into the table for display 3380 * @param {object} oSettings dataTables settings object 3381 * @memberof DataTable#oApi 3382 */ 3383 function _fnDraw( oSettings ) 3384 { 3385 /* Provide a pre-callback function which can be used to cancel the draw is false is returned */ 3386 var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] ); 3387 if ( $.inArray( false, aPreDraw ) !== -1 ) 3388 { 3389 _fnProcessingDisplay( oSettings, false ); 3390 return; 3391 } 3392 3393 var i, iLen, n; 3394 var anRows = []; 3395 var iRowCount = 0; 3396 var asStripeClasses = oSettings.asStripeClasses; 3397 var iStripes = asStripeClasses.length; 3398 var iOpenRows = oSettings.aoOpenRows.length; 3399 var oLang = oSettings.oLanguage; 3400 var iInitDisplayStart = oSettings.iInitDisplayStart; 3401 var bServerSide = _fnDataSource( oSettings ) == 'ssp'; 3402 var aiDisplay = oSettings.aiDisplay; 3403 3404 oSettings.bDrawing = true; 3405 3406 /* Check and see if we have an initial draw position from state saving */ 3407 if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 ) 3408 { 3409 oSettings._iDisplayStart = bServerSide ? 3410 iInitDisplayStart : 3411 iInitDisplayStart >= oSettings.fnRecordsDisplay() ? 3412 0 : 3413 iInitDisplayStart; 3414 3415 oSettings.iInitDisplayStart = -1; 3416 } 3417 3418 var iDisplayStart = oSettings._iDisplayStart; 3419 var iDisplayEnd = oSettings.fnDisplayEnd(); 3420 3421 /* Server-side processing draw intercept */ 3422 if ( oSettings.bDeferLoading ) 3423 { 3424 oSettings.bDeferLoading = false; 3425 oSettings.iDraw++; 3426 _fnProcessingDisplay( oSettings, false ); 3427 } 3428 else if ( !bServerSide ) 3429 { 3430 oSettings.iDraw++; 3431 } 3432 else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) ) 3433 {
vendor: 10,503 bytes, lines 3433-3822
3433 3434 return; 3435 } 3436 3437 if ( aiDisplay.length !== 0 ) 3438 { 3439 var iStart = bServerSide ? 0 : iDisplayStart; 3440 var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd; 3441 3442 for ( var j=iStart ; j<iEnd ; j++ ) 3443 { 3444 var iDataIndex = aiDisplay[j]; 3445 var aoData = oSettings.aoData[ iDataIndex ]; 3446 if ( aoData.nTr === null ) 3447 { 3448 _fnCreateTr( oSettings, iDataIndex ); 3449 } 3450 3451 var nRow = aoData.nTr; 3452 3453 /* Remove the old striping classes and then add the new one */ 3454 if ( iStripes !== 0 ) 3455 { 3456 var sStripe = asStripeClasses[ iRowCount % iStripes ]; 3457 if ( aoData._sRowStripe != sStripe ) 3458 { 3459 $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe ); 3460 aoData._sRowStripe = sStripe; 3461 } 3462 } 3463 3464 // Row callback functions - might want to manipulate the row 3465 // iRowCount and j are not currently documented. Are they at all 3466 // useful? 3467 _fnCallbackFire( oSettings, 'aoRowCallback', null, 3468 [nRow, aoData._aData, iRowCount, j, iDataIndex] ); 3469 3470 anRows.push( nRow ); 3471 iRowCount++; 3472 } 3473 } 3474 else 3475 { 3476 /* Table is empty - create a row with an empty message in it */ 3477 var sZero = oLang.sZeroRecords; 3478 if ( oSettings.iDraw == 1 && _fnDataSource( oSettings ) == 'ajax' ) 3479 { 3480 sZero = oLang.sLoadingRecords; 3481 } 3482 else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 ) 3483 { 3484 sZero = oLang.sEmptyTable; 3485 } 3486 3487 anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } ) 3488 .append( $('<td />', { 3489 'valign': 'top', 3490 'colSpan': _fnVisbleColumns( oSettings ), 3491 'class': oSettings.oClasses.sRowEmpty 3492 } ).html( sZero ) )[0]; 3493 } 3494 3495 /* Header and footer callbacks */ 3496 _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0], 3497 _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] ); 3498 3499 _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0], 3500 _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] ); 3501 3502 var body = $(oSettings.nTBody); 3503 3504 body.children().detach(); 3505 body.append( $(anRows) ); 3506 3507 /* Call all required callback functions for the end of a draw */ 3508 _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] ); 3509 3510 /* Draw is complete, sorting and filtering must be as well */ 3511 oSettings.bSorted = false; 3512 oSettings.bFiltered = false; 3513 oSettings.bDrawing = false; 3514 } 3515 3516 3517 /** 3518 * Redraw the table - taking account of the various features which are enabled 3519 * @param {object} oSettings dataTables settings object 3520 * @param {boolean} [holdPosition] Keep the current paging position. By default 3521 * the paging is reset to the first page 3522 * @memberof DataTable#oApi 3523 */ 3524 function _fnReDraw( settings, holdPosition ) 3525 { 3526 var 3527 features = settings.oFeatures, 3528 sort = features.bSort, 3529 filter = features.bFilter; 3530 3531 if ( sort ) { 3532 _fnSort( settings ); 3533 } 3534 3535 if ( filter ) { 3536 _fnFilterComplete( settings, settings.oPreviousSearch ); 3537 } 3538 else { 3539 // No filtering, so we want to just use the display master 3540 settings.aiDisplay = settings.aiDisplayMaster.slice(); 3541 } 3542 3543 if ( holdPosition !== true ) { 3544 settings._iDisplayStart = 0; 3545 } 3546 3547 // Let any modules know about the draw hold position state (used by 3548 // scrolling internally) 3549 settings._drawHold = holdPosition; 3550 3551 _fnDraw( settings ); 3552 3553 settings._drawHold = false; 3554 } 3555 3556 3557 /** 3558 * Add the options to the page HTML for the table 3559 * @param {object} oSettings dataTables settings object 3560 * @memberof DataTable#oApi 3561 */ 3562 function _fnAddOptionsHtml ( oSettings ) 3563 { 3564 var classes = oSettings.oClasses; 3565 var table = $(oSettings.nTable); 3566 var holding = $('<div/>').insertBefore( table ); // Holding element for speed 3567 var features = oSettings.oFeatures; 3568 3569 // All DataTables are wrapped in a div 3570 var insert = $('<div/>', { 3571 id: oSettings.sTableId+'_wrapper', 3572 'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter) 3573 } ); 3574 3575 oSettings.nHolding = holding[0]; 3576 oSettings.nTableWrapper = insert[0]; 3577 oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling; 3578 3579 /* Loop over the user set positioning and place the elements as needed */ 3580 var aDom = oSettings.sDom.split(''); 3581 var featureNode, cOption, nNewNode, cNext, sAttr, j; 3582 for ( var i=0 ; i<aDom.length ; i++ ) 3583 { 3584 featureNode = null; 3585 cOption = aDom[i]; 3586 3587 if ( cOption == '<' ) 3588 { 3589 /* New container div */ 3590 nNewNode = $('<div/>')[0]; 3591 3592 /* Check to see if we should append an id and/or a class name to the container */ 3593 cNext = aDom[i+1]; 3594 if ( cNext == "'" || cNext == '"' ) 3595 { 3596 sAttr = ""; 3597 j = 2; 3598 while ( aDom[i+j] != cNext ) 3599 { 3600 sAttr += aDom[i+j]; 3601 j++; 3602 } 3603 3604 /* Replace jQuery UI constants @todo depreciated */ 3605 if ( sAttr == "H" ) 3606 { 3607 sAttr = classes.sJUIHeader; 3608 } 3609 else if ( sAttr == "F" ) 3610 { 3611 sAttr = classes.sJUIFooter; 3612 } 3613 3614 /* The attribute can be in the format of "#id.class", "#id" or "class" This logic 3615 * breaks the string into parts and applies them as needed 3616 */ 3617 if ( sAttr.indexOf('.') != -1 ) 3618 { 3619 var aSplit = sAttr.split('.'); 3620 nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1); 3621 nNewNode.className = aSplit[1]; 3622 } 3623 else if ( sAttr.charAt(0) == "#" ) 3624 { 3625 nNewNode.id = sAttr.substr(1, sAttr.length-1); 3626 } 3627 else 3628 { 3629 nNewNode.className = sAttr; 3630 } 3631 3632 i += j; /* Move along the position array */ 3633 } 3634 3635 insert.append( nNewNode ); 3636 insert = $(nNewNode); 3637 } 3638 else if ( cOption == '>' ) 3639 { 3640 /* End container div */ 3641 insert = insert.parent(); 3642 } 3643 // @todo Move options into their own plugins? 3644 else if ( cOption == 'l' && features.bPaginate && features.bLengthChange ) 3645 { 3646 /* Length */ 3647 featureNode = _fnFeatureHtmlLength( oSettings ); 3648 } 3649 else if ( cOption == 'f' && features.bFilter ) 3650 { 3651 /* Filter */ 3652 featureNode = _fnFeatureHtmlFilter( oSettings ); 3653 } 3654 else if ( cOption == 'r' && features.bProcessing ) 3655 { 3656 /* pRocessing */ 3657 featureNode = _fnFeatureHtmlProcessing( oSettings ); 3658 } 3659 else if ( cOption == 't' ) 3660 { 3661 /* Table */ 3662 featureNode = _fnFeatureHtmlTable( oSettings ); 3663 } 3664 else if ( cOption == 'i' && features.bInfo ) 3665 { 3666 /* Info */ 3667 featureNode = _fnFeatureHtmlInfo( oSettings ); 3668 } 3669 else if ( cOption == 'p' && features.bPaginate ) 3670 { 3671 /* Pagination */ 3672 featureNode = _fnFeatureHtmlPaginate( oSettings ); 3673 } 3674 else if ( DataTable.ext.feature.length !== 0 ) 3675 { 3676 /* Plug-in features */ 3677 var aoFeatures = DataTable.ext.feature; 3678 for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ ) 3679 { 3680 if ( cOption == aoFeatures[k].cFeature ) 3681 { 3682 featureNode = aoFeatures[k].fnInit( oSettings ); 3683 break; 3684 } 3685 } 3686 } 3687 3688 /* Add to the 2D features array */ 3689 if ( featureNode ) 3690 { 3691 var aanFeatures = oSettings.aanFeatures; 3692 3693 if ( ! aanFeatures[cOption] ) 3694 { 3695 aanFeatures[cOption] = []; 3696 } 3697 3698 aanFeatures[cOption].push( featureNode ); 3699 insert.append( featureNode ); 3700 } 3701 } 3702 3703 /* Built our DOM structure - replace the holding div with what we want */ 3704 holding.replaceWith( insert ); 3705 oSettings.nHolding = null; 3706 } 3707 3708 3709 /** 3710 * Use the DOM source to create up an array of header cells. The idea here is to 3711 * create a layout grid (array) of rows x columns, which contains a reference 3712 * to the cell that that point in the grid (regardless of col/rowspan), such that 3713 * any column / row could be removed and the new grid constructed 3714 * @param array {object} aLayout Array to store the calculated layout in 3715 * @param {node} nThead The header/footer element for the table 3716 * @memberof DataTable#oApi 3717 */ 3718 function _fnDetectHeader ( aLayout, nThead ) 3719 { 3720 var nTrs = $(nThead).children('tr'); 3721 var nTr, nCell; 3722 var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan; 3723 var bUnique; 3724 var fnShiftCol = function ( a, i, j ) { 3725 var k = a[i]; 3726 while ( k[j] ) { 3727 j++; 3728 } 3729 return j; 3730 }; 3731 3732 aLayout.splice( 0, aLayout.length ); 3733 3734 /* We know how many rows there are in the layout - so prep it */ 3735 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ ) 3736 { 3737 aLayout.push( [] ); 3738 } 3739 3740 /* Calculate a layout array */ 3741 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ ) 3742 { 3743 nTr = nTrs[i]; 3744 iColumn = 0; 3745 3746 /* For every cell in the row... */ 3747 nCell = nTr.firstChild; 3748 while ( nCell ) { 3749 if ( nCell.nodeName.toUpperCase() == "TD" || 3750 nCell.nodeName.toUpperCase() == "TH" ) 3751 { 3752 /* Get the col and rowspan attributes from the DOM and sanitise them */ 3753 iColspan = nCell.getAttribute('colspan') * 1; 3754 iRowspan = nCell.getAttribute('rowspan') * 1; 3755 iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan; 3756 iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan; 3757 3758 /* There might be colspan cells already in this row, so shift our target 3759 * accordingly 3760 */ 3761 iColShifted = fnShiftCol( aLayout, i, iColumn ); 3762 3763 /* Cache calculation for unique columns */ 3764 bUnique = iColspan === 1 ? true : false; 3765 3766 /* If there is col / rowspan, copy the information into the layout grid */ 3767 for ( l=0 ; l<iColspan ; l++ ) 3768 { 3769 for ( k=0 ; k<iRowspan ; k++ ) 3770 { 3771 aLayout[i+k][iColShifted+l] = { 3772 "cell": nCell, 3773 "unique": bUnique 3774 }; 3775 aLayout[i+k].nTr = nTr; 3776 } 3777 } 3778 } 3779 nCell = nCell.nextSibling; 3780 } 3781 } 3782 } 3783 3784 3785 /** 3786 * Get an array of unique th elements, one for each column 3787 * @param {object} oSettings dataTables settings object 3788 * @param {node} nHeader automatically detect the layout from this node - optional 3789 * @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional 3790 * @returns array {node} aReturn list of unique th's 3791 * @memberof DataTable#oApi 3792 */ 3793 function _fnGetUniqueThs ( oSettings, nHeader, aLayout ) 3794 { 3795 var aReturn = []; 3796 if ( !aLayout ) 3797 { 3798 aLayout = oSettings.aoHeader; 3799 if ( nHeader ) 3800 { 3801 aLayout = []; 3802 _fnDetectHeader( aLayout, nHeader ); 3803 } 3804 } 3805 3806 for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ ) 3807 { 3808 for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ ) 3809 { 3810 if ( aLayout[i][j].unique && 3811 (!aReturn[j] || !oSettings.bSortCellsTop) ) 3812 { 3813 aReturn[j] = aLayout[i][j].cell; 3814 } 3815 } 3816 } 3817 3818 return aReturn; 3819 } 3820 3821 /** 3822 *
vendor: 34,951 bytes, lines 3822-5053
3822Create an Ajax call based on the table's settings, taking into account that 3823 * parameters can have multiple forms, and backwards compatibility. 3824 * 3825 * @param {object} oSettings dataTables settings object 3826 * @param {array} data Data to send to the server, required by 3827 * DataTables - may be augmented by developer callbacks 3828 * @param {function} fn Callback function to run when data is obtained 3829 */ 3830 function _fnBuildAjax( oSettings, data, fn ) 3831 { 3832 // Compatibility with 1.9-, allow fnServerData and event to manipulate 3833 _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] ); 3834 3835 // Convert to object based for 1.10+ if using the old array scheme which can 3836 // come from server-side processing or serverParams 3837 if ( data && $.isArray(data) ) { 3838 var tmp = {}; 3839 var rbracket = /(.*?)\[\]$/; 3840 3841 $.each( data, function (key, val) { 3842 var match = val.name.match(rbracket); 3843 3844 if ( match ) { 3845 // Support for arrays 3846 var name = match[0]; 3847 3848 if ( ! tmp[ name ] ) { 3849 tmp[ name ] = []; 3850 } 3851 tmp[ name ].push( val.value ); 3852 } 3853 else { 3854 tmp[val.name] = val.value; 3855 } 3856 } ); 3857 data = tmp; 3858 } 3859 3860 var ajaxData; 3861 var ajax = oSettings.ajax; 3862 var instance = oSettings.oInstance; 3863 var callback = function ( json ) { 3864 _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] ); 3865 fn( json ); 3866 }; 3867 3868 if ( $.isPlainObject( ajax ) && ajax.data ) 3869 { 3870 ajaxData = ajax.data; 3871 3872 var newData = typeof ajaxData === 'function' ? 3873 ajaxData( data, oSettings ) : // fn can manipulate data or return 3874 ajaxData; // an object object or array to merge 3875 3876 // If the function returned something, use that alone 3877 data = typeof ajaxData === 'function' && newData ? 3878 newData : 3879 $.extend( true, data, newData ); 3880 3881 // Remove the data property as we've resolved it already and don't want 3882 // jQuery to do it again (it is restored at the end of the function) 3883 delete ajax.data; 3884 } 3885 3886 var baseAjax = { 3887 "data": data, 3888 "success": function (json) { 3889 var error = json.error || json.sError; 3890 if ( error ) { 3891 _fnLog( oSettings, 0, error ); 3892 } 3893 3894 oSettings.json = json; 3895 callback( json ); 3896 }, 3897 "dataType": "json", 3898 "cache": false, 3899 "type": oSettings.sServerMethod, 3900 "error": function (xhr, error, thrown) { 3901 var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] ); 3902 3903 if ( $.inArray( true, ret ) === -1 ) { 3904 if ( error == "parsererror" ) { 3905 _fnLog( oSettings, 0, 'Invalid JSON response', 1 ); 3906 } 3907 else if ( xhr.readyState === 4 ) { 3908 _fnLog( oSettings, 0, 'Ajax error', 7 ); 3909 } 3910 } 3911 3912 _fnProcessingDisplay( oSettings, false ); 3913 } 3914 }; 3915 3916 // Store the data submitted for the API 3917 oSettings.oAjaxData = data; 3918 3919 // Allow plug-ins and external processes to modify the data 3920 _fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] ); 3921 3922 if ( oSettings.fnServerData ) 3923 { 3924 // DataTables 1.9- compatibility 3925 oSettings.fnServerData.call( instance, 3926 oSettings.sAjaxSource, 3927 $.map( data, function (val, key) { // Need to convert back to 1.9 trad format 3928 return { name: key, value: val }; 3929 } ), 3930 callback, 3931 oSettings 3932 ); 3933 } 3934 else if ( oSettings.sAjaxSource || typeof ajax === 'string' ) 3935 { 3936 // DataTables 1.9- compatibility 3937 oSettings.jqXHR = $.ajax( $.extend( baseAjax, { 3938 url: ajax || oSettings.sAjaxSource 3939 } ) ); 3940 } 3941 else if ( typeof ajax === 'function' ) 3942 { 3943 // Is a function - let the caller define what needs to be done 3944 oSettings.jqXHR = ajax.call( instance, data, callback, oSettings ); 3945 } 3946 else 3947 { 3948 // Object to extend the base settings 3949 oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) ); 3950 3951 // Restore for next time around 3952 ajax.data = ajaxData; 3953 } 3954 } 3955 3956 3957 /** 3958 * Update the table using an Ajax call 3959 * @param {object} settings dataTables settings object 3960 * @returns {boolean} Block the table drawing or not 3961 * @memberof DataTable#oApi 3962 */ 3963 function _fnAjaxUpdate( settings ) 3964 { 3965 if ( settings.bAjaxDataGet ) { 3966 settings.iDraw++; 3967 _fnProcessingDisplay( settings, true ); 3968 3969 _fnBuildAjax( 3970 settings, 3971 _fnAjaxParameters( settings ), 3972 function(json) { 3973 _fnAjaxUpdateDraw( settings, json ); 3974 } 3975 ); 3976 3977 return false; 3978 } 3979 return true; 3980 } 3981 3982 3983 /** 3984 * Build up the parameters in an object needed for a server-side processing 3985 * request. Note that this is basically done twice, is different ways - a modern 3986 * method which is used by default in DataTables 1.10 which uses objects and 3987 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if 3988 * the sAjaxSource option is used in the initialisation, or the legacyAjax 3989 * option is set. 3990 * @param {object} oSettings dataTables settings object 3991 * @returns {bool} block the table drawing or not 3992 * @memberof DataTable#oApi 3993 */ 3994 function _fnAjaxParameters( settings ) 3995 { 3996 var 3997 columns = settings.aoColumns, 3998 columnCount = columns.length, 3999 features = settings.oFeatures, 4000 preSearch = settings.oPreviousSearch, 4001 preColSearch = settings.aoPreSearchCols, 4002 i, data = [], dataProp, column, columnSearch, 4003 sort = _fnSortFlatten( settings ), 4004 displayStart = settings._iDisplayStart, 4005 displayLength = features.bPaginate !== false ? 4006 settings._iDisplayLength : 4007 -1; 4008 4009 var param = function ( name, value ) { 4010 data.push( { 'name': name, 'value': value } ); 4011 }; 4012 4013 // DataTables 1.9- compatible method 4014 param( 'sEcho', settings.iDraw ); 4015 param( 'iColumns', columnCount ); 4016 param( 'sColumns', _pluck( columns, 'sName' ).join(',') ); 4017 param( 'iDisplayStart', displayStart ); 4018 param( 'iDisplayLength', displayLength ); 4019 4020 // DataTables 1.10+ method 4021 var d = { 4022 draw: settings.iDraw, 4023 columns: [], 4024 order: [], 4025 start: displayStart, 4026 length: displayLength, 4027 search: { 4028 value: preSearch.sSearch, 4029 regex: preSearch.bRegex 4030 } 4031 }; 4032 4033 for ( i=0 ; i<columnCount ; i++ ) { 4034 column = columns[i]; 4035 columnSearch = preColSearch[i]; 4036 dataProp = typeof column.mData=="function" ? 'function' : column.mData ; 4037 4038 d.columns.push( { 4039 data: dataProp, 4040 name: column.sName, 4041 searchable: column.bSearchable, 4042 orderable: column.bSortable, 4043 search: { 4044 value: columnSearch.sSearch, 4045 regex: columnSearch.bRegex 4046 } 4047 } ); 4048 4049 param( "mDataProp_"+i, dataProp ); 4050 4051 if ( features.bFilter ) { 4052 param( 'sSearch_'+i, columnSearch.sSearch ); 4053 param( 'bRegex_'+i, columnSearch.bRegex ); 4054 param( 'bSearchable_'+i, column.bSearchable ); 4055 } 4056 4057 if ( features.bSort ) { 4058 param( 'bSortable_'+i, column.bSortable ); 4059 } 4060 } 4061 4062 if ( features.bFilter ) { 4063 param( 'sSearch', preSearch.sSearch ); 4064 param( 'bRegex', preSearch.bRegex ); 4065 } 4066 4067 if ( features.bSort ) { 4068 $.each( sort, function ( i, val ) { 4069 d.order.push( { column: val.col, dir: val.dir } ); 4070 4071 param( 'iSortCol_'+i, val.col ); 4072 param( 'sSortDir_'+i, val.dir ); 4073 } ); 4074 4075 param( 'iSortingCols', sort.length ); 4076 } 4077 4078 // If the legacy.ajax parameter is null, then we automatically decide which 4079 // form to use, based on sAjaxSource 4080 var legacy = DataTable.ext.legacy.ajax; 4081 if ( legacy === null ) { 4082 return settings.sAjaxSource ? data : d; 4083 } 4084 4085 // Otherwise, if legacy has been specified then we use that to decide on the 4086 // form 4087 return legacy ? data : d; 4088 } 4089 4090 4091 /** 4092 * Data the data from the server (nuking the old) and redraw the table 4093 * @param {object} oSettings dataTables settings object 4094 * @param {object} json json data return from the server. 4095 * @param {string} json.sEcho Tracking flag for DataTables to match requests 4096 * @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering 4097 * @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering 4098 * @param {array} json.aaData The data to display on this page 4099 * @param {string} [json.sColumns] Column ordering (sName, comma separated) 4100 * @memberof DataTable#oApi 4101 */ 4102 function _fnAjaxUpdateDraw ( settings, json ) 4103 { 4104 // v1.10 uses camelCase variables, while 1.9 uses Hungarian notation. 4105 // Support both 4106 var compat = function ( old, modern ) { 4107 return json[old] !== undefined ? json[old] : json[modern]; 4108 }; 4109 4110 var data = _fnAjaxDataSrc( settings, json ); 4111 var draw = compat( 'sEcho', 'draw' ); 4112 var recordsTotal = compat( 'iTotalRecords', 'recordsTotal' ); 4113 var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' ); 4114 4115 if ( draw !== undefined ) { 4116 // Protect against out of sequence returns 4117 if ( draw*1 < settings.iDraw ) { 4118 return; 4119 } 4120 settings.iDraw = draw * 1; 4121 } 4122 4123 _fnClearTable( settings ); 4124 settings._iRecordsTotal = parseInt(recordsTotal, 10); 4125 settings._iRecordsDisplay = parseInt(recordsFiltered, 10); 4126 4127 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 4128 _fnAddData( settings, data[i] ); 4129 } 4130 settings.aiDisplay = settings.aiDisplayMaster.slice(); 4131 4132 settings.bAjaxDataGet = false; 4133 _fnDraw( settings ); 4134 4135 if ( ! settings._bInitComplete ) { 4136 _fnInitComplete( settings, json ); 4137 } 4138 4139 settings.bAjaxDataGet = true; 4140 _fnProcessingDisplay( settings, false ); 4141 } 4142 4143 4144 /** 4145 * Get the data from the JSON data source to use for drawing a table. Using 4146 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the 4147 * source object, or from a processing function. 4148 * @param {object} oSettings dataTables settings object 4149 * @param {object} json Data source object / array from the server 4150 * @return {array} Array of data to use 4151 */ 4152 function _fnAjaxDataSrc ( oSettings, json ) 4153 { 4154 var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ? 4155 oSettings.ajax.dataSrc : 4156 oSettings.sAjaxDataProp; // Compatibility with 1.9-. 4157 4158 // Compatibility with 1.9-. In order to read from aaData, check if the 4159 // default has been changed, if not, check for aaData 4160 if ( dataSrc === 'data' ) { 4161 return json.aaData || json[dataSrc]; 4162 } 4163 4164 return dataSrc !== "" ? 4165 _fnGetObjectDataFn( dataSrc )( json ) : 4166 json; 4167 } 4168 4169 /** 4170 * Generate the node required for filtering text 4171 * @returns {node} Filter control element 4172 * @param {object} oSettings dataTables settings object 4173 * @memberof DataTable#oApi 4174 */ 4175 function _fnFeatureHtmlFilter ( settings ) 4176 { 4177 var classes = settings.oClasses; 4178 var tableId = settings.sTableId; 4179 var language = settings.oLanguage; 4180 var previousSearch = settings.oPreviousSearch; 4181 var features = settings.aanFeatures; 4182 var input = '<input type="search" class="'+classes.sFilterInput+'"/>'; 4183 4184 var str = language.sSearch; 4185 str = str.match(/_INPUT_/) ? 4186 str.replace('_INPUT_', input) : 4187 str+input; 4188 4189 var filter = $('<div/>', { 4190 'id': ! features.f ? tableId+'_filter' : null, 4191 'class': classes.sFilter 4192 } ) 4193 .append( $('<label/>' ).append( str ) ); 4194 4195 var searchFn = function() { 4196 /* Update all other filter input elements for the new display */ 4197 var n = features.f; 4198 var val = !this.value ? "" : this.value; // mental IE8 fix :-( 4199 4200 /* Now do the filter */ 4201 if ( val != previousSearch.sSearch ) { 4202 _fnFilterComplete( settings, { 4203 "sSearch": val, 4204 "bRegex": previousSearch.bRegex, 4205 "bSmart": previousSearch.bSmart , 4206 "bCaseInsensitive": previousSearch.bCaseInsensitive 4207 } ); 4208 4209 // Need to redraw, without resorting 4210 settings._iDisplayStart = 0; 4211 _fnDraw( settings ); 4212 } 4213 }; 4214 4215 var searchDelay = settings.searchDelay !== null ? 4216 settings.searchDelay : 4217 _fnDataSource( settings ) === 'ssp' ? 4218 400 : 4219 0; 4220 4221 var jqFilter = $('input', filter) 4222 .val( previousSearch.sSearch ) 4223 .attr( 'placeholder', language.sSearchPlaceholder ) 4224 .on( 4225 'keyup.DT search.DT input.DT paste.DT cut.DT', 4226 searchDelay ? 4227 _fnThrottle( searchFn, searchDelay ) : 4228 searchFn 4229 ) 4230 .on( 'mouseup', function(e) { 4231 // Edge fix! Edge 17 does not trigger anything other than mouse events when clicking 4232 // on the clear icon (Edge bug 17584515). This is safe in other browsers as `searchFn` 4233 // checks the value to see if it has changed. In other browsers it won't have. 4234 setTimeout( function () { 4235 searchFn.call(jqFilter[0]); 4236 }, 10); 4237 } ) 4238 .on( 'keypress.DT', function(e) { 4239 /* Prevent form submission */ 4240 if ( e.keyCode == 13 ) { 4241 return false; 4242 } 4243 } ) 4244 .attr('aria-controls', tableId); 4245 4246 // Update the input elements whenever the table is filtered 4247 $(settings.nTable).on( 'search.dt.DT', function ( ev, s ) { 4248 if ( settings === s ) { 4249 // IE9 throws an 'unknown error' if document.activeElement is used 4250 // inside an iframe or frame... 4251 try { 4252 if ( jqFilter[0] !== document.activeElement ) { 4253 jqFilter.val( previousSearch.sSearch ); 4254 } 4255 } 4256 catch ( e ) {} 4257 } 4258 } ); 4259 4260 return filter[0]; 4261 } 4262 4263 4264 /** 4265 * Filter the table using both the global filter and column based filtering 4266 * @param {object} oSettings dataTables settings object 4267 * @param {object} oSearch search information 4268 * @param {int} [iForce] force a research of the master array (1) or not (undefined or 0) 4269 * @memberof DataTable#oApi 4270 */ 4271 function _fnFilterComplete ( oSettings, oInput, iForce ) 4272 { 4273 var oPrevSearch = oSettings.oPreviousSearch; 4274 var aoPrevSearch = oSettings.aoPreSearchCols; 4275 var fnSaveFilter = function ( oFilter ) { 4276 /* Save the filtering values */ 4277 oPrevSearch.sSearch = oFilter.sSearch; 4278 oPrevSearch.bRegex = oFilter.bRegex; 4279 oPrevSearch.bSmart = oFilter.bSmart; 4280 oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive; 4281 }; 4282 var fnRegex = function ( o ) { 4283 // Backwards compatibility with the bEscapeRegex option 4284 return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex; 4285 }; 4286 4287 // Resolve any column types that are unknown due to addition or invalidation 4288 // @todo As per sort - can this be moved into an event handler? 4289 _fnColumnTypes( oSettings ); 4290 4291 /* In server-side processing all filtering is done by the server, so no point hanging around here */ 4292 if ( _fnDataSource( oSettings ) != 'ssp' ) 4293 { 4294 /* Global filter */ 4295 _fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive ); 4296 fnSaveFilter( oInput ); 4297 4298 /* Now do the individual column filter */ 4299 for ( var i=0 ; i<aoPrevSearch.length ; i++ ) 4300 { 4301 _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]), 4302 aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive ); 4303 } 4304 4305 /* Custom filtering */ 4306 _fnFilterCustom( oSettings ); 4307 } 4308 else 4309 { 4310 fnSaveFilter( oInput ); 4311 } 4312 4313 /* Tell the draw function we have been filtering */ 4314 oSettings.bFiltered = true; 4315 _fnCallbackFire( oSettings, null, 'search', [oSettings] ); 4316 } 4317 4318 4319 /** 4320 * Apply custom filtering functions 4321 * @param {object} oSettings dataTables settings object 4322 * @memberof DataTable#oApi 4323 */ 4324 function _fnFilterCustom( settings ) 4325 { 4326 var filters = DataTable.ext.search; 4327 var displayRows = settings.aiDisplay; 4328 var row, rowIdx; 4329 4330 for ( var i=0, ien=filters.length ; i<ien ; i++ ) { 4331 var rows = []; 4332 4333 // Loop over each row and see if it should be included 4334 for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) { 4335 rowIdx = displayRows[ j ]; 4336 row = settings.aoData[ rowIdx ]; 4337 4338 if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) { 4339 rows.push( rowIdx ); 4340 } 4341 } 4342 4343 // So the array reference doesn't break set the results into the 4344 // existing array 4345 displayRows.length = 0; 4346 $.merge( displayRows, rows ); 4347 } 4348 } 4349 4350 4351 /** 4352 * Filter the table on a per-column basis 4353 * @param {object} oSettings dataTables settings object 4354 * @param {string} sInput string to filter on 4355 * @param {int} iColumn column to filter 4356 * @param {bool} bRegex treat search string as a regular expression or not 4357 * @param {bool} bSmart use smart filtering or not 4358 * @param {bool} bCaseInsensitive Do case insenstive matching or not 4359 * @memberof DataTable#oApi 4360 */ 4361 function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive ) 4362 { 4363 if ( searchStr === '' ) { 4364 return; 4365 } 4366 4367 var data; 4368 var out = []; 4369 var display = settings.aiDisplay; 4370 var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive ); 4371 4372 for ( var i=0 ; i<display.length ; i++ ) { 4373 data = settings.aoData[ display[i] ]._aFilterData[ colIdx ]; 4374 4375 if ( rpSearch.test( data ) ) { 4376 out.push( display[i] ); 4377 } 4378 } 4379 4380 settings.aiDisplay = out; 4381 } 4382 4383 4384 /** 4385 * Filter the data table based on user input and draw the table 4386 * @param {object} settings dataTables settings object 4387 * @param {string} input string to filter on 4388 * @param {int} force optional - force a research of the master array (1) or not (undefined or 0) 4389 * @param {bool} regex treat as a regular expression or not 4390 * @param {bool} smart perform smart filtering or not 4391 * @param {bool} caseInsensitive Do case insenstive matching or not 4392 * @memberof DataTable#oApi 4393 */ 4394 function _fnFilter( settings, input, force, regex, smart, caseInsensitive ) 4395 { 4396 var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive ); 4397 var prevSearch = settings.oPreviousSearch.sSearch; 4398 var displayMaster = settings.aiDisplayMaster; 4399 var display, invalidated, i; 4400 var filtered = []; 4401 4402 // Need to take account of custom filtering functions - always filter 4403 if ( DataTable.ext.search.length !== 0 ) { 4404 force = true; 4405 } 4406 4407 // Check if any of the rows were invalidated 4408 invalidated = _fnFilterData( settings ); 4409 4410 // If the input is blank - we just want the full data set 4411 if ( input.length <= 0 ) { 4412 settings.aiDisplay = displayMaster.slice(); 4413 } 4414 else { 4415 // New search - start from the master array 4416 if ( invalidated || 4417 force || 4418 regex || 4419 prevSearch.length > input.length || 4420 input.indexOf(prevSearch) !== 0 || 4421 settings.bSorted // On resort, the display master needs to be 4422 // re-filtered since indexes will have changed 4423 ) { 4424 settings.aiDisplay = displayMaster.slice(); 4425 } 4426 4427 // Search the display array 4428 display = settings.aiDisplay; 4429 4430 for ( i=0 ; i<display.length ; i++ ) { 4431 if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) { 4432 filtered.push( display[i] ); 4433 } 4434 } 4435 4436 settings.aiDisplay = filtered; 4437 } 4438 } 4439 4440 4441 /** 4442 * Build a regular expression object suitable for searching a table 4443 * @param {string} sSearch string to search for 4444 * @param {bool} bRegex treat as a regular expression or not 4445 * @param {bool} bSmart perform smart filtering or not 4446 * @param {bool} bCaseInsensitive Do case insensitive matching or not 4447 * @returns {RegExp} constructed object 4448 * @memberof DataTable#oApi 4449 */ 4450 function _fnFilterCreateSearch( search, regex, smart, caseInsensitive ) 4451 { 4452 search = regex ? 4453 search : 4454 _fnEscapeRegex( search ); 4455 4456 if ( smart ) { 4457 /* For smart filtering we want to allow the search to work regardless of 4458 * word order. We also want double quoted text to be preserved, so word 4459 * order is important - a la google. So this is what we want to 4460 * generate: 4461 * 4462 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$ 4463 */ 4464 var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) { 4465 if ( word.charAt(0) === '"' ) { 4466 var m = word.match( /^"(.*)"$/ ); 4467 word = m ? m[1] : word; 4468 } 4469 4470 return word.replace('"', ''); 4471 } ); 4472 4473 search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$'; 4474 } 4475 4476 return new RegExp( search, caseInsensitive ? 'i' : '' ); 4477 } 4478 4479 4480 /** 4481 * Escape a string such that it can be used in a regular expression 4482 * @param {string} sVal string to escape 4483 * @returns {string} escaped string 4484 * @memberof DataTable#oApi 4485 */ 4486 var _fnEscapeRegex = DataTable.util.escapeRegex; 4487 4488 var __filter_div = $('<div>')[0]; 4489 var __filter_div_textContent = __filter_div.textContent !== undefined; 4490 4491 // Update the filtering data for each row if needed (by invalidation or first run) 4492 function _fnFilterData ( settings ) 4493 { 4494 var columns = settings.aoColumns; 4495 var column; 4496 var i, j, ien, jen, filterData, cellData, row; 4497 var fomatters = DataTable.ext.type.search; 4498 var wasInvalidated = false; 4499 4500 for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 4501 row = settings.aoData[i]; 4502 4503 if ( ! row._aFilterData ) { 4504 filterData = []; 4505 4506 for ( j=0, jen=columns.length ; j<jen ; j++ ) { 4507 column = columns[j]; 4508 4509 if ( column.bSearchable ) { 4510 cellData = _fnGetCellData( settings, i, j, 'filter' ); 4511 4512 if ( fomatters[ column.sType ] ) { 4513 cellData = fomatters[ column.sType ]( cellData ); 4514 } 4515 4516 // Search in DataTables 1.10 is string based. In 1.11 this 4517 // should be altered to also allow strict type checking. 4518 if ( cellData === null ) { 4519 cellData = ''; 4520 } 4521 4522 if ( typeof cellData !== 'string' && cellData.toString ) { 4523 cellData = cellData.toString(); 4524 } 4525 } 4526 else { 4527 cellData = ''; 4528 } 4529 4530 // If it looks like there is an HTML entity in the string, 4531 // attempt to decode it so sorting works as expected. Note that 4532 // we could use a single line of jQuery to do this, but the DOM 4533 // method used here is much faster http://jsperf.com/html-decode 4534 if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) { 4535 __filter_div.innerHTML = cellData; 4536 cellData = __filter_div_textContent ? 4537 __filter_div.textContent : 4538 __filter_div.innerText; 4539 } 4540 4541 if ( cellData.replace ) { 4542 cellData = cellData.replace(/[\r\n\u2028]/g, ''); 4543 } 4544 4545 filterData.push( cellData ); 4546 } 4547 4548 row._aFilterData = filterData; 4549 row._sFilterRow = filterData.join(' '); 4550 wasInvalidated = true; 4551 } 4552 } 4553 4554 return wasInvalidated; 4555 } 4556 4557 4558 /** 4559 * Convert from the internal Hungarian notation to camelCase for external 4560 * interaction 4561 * @param {object} obj Object to convert 4562 * @returns {object} Inverted object 4563 * @memberof DataTable#oApi 4564 */ 4565 function _fnSearchToCamel ( obj ) 4566 { 4567 return { 4568 search: obj.sSearch, 4569 smart: obj.bSmart, 4570 regex: obj.bRegex, 4571 caseInsensitive: obj.bCaseInsensitive 4572 }; 4573 } 4574 4575 4576 4577 /** 4578 * Convert from camelCase notation to the internal Hungarian. We could use the 4579 * Hungarian convert function here, but this is cleaner 4580 * @param {object} obj Object to convert 4581 * @returns {object} Inverted object 4582 * @memberof DataTable#oApi 4583 */ 4584 function _fnSearchToHung ( obj ) 4585 { 4586 return { 4587 sSearch: obj.search, 4588 bSmart: obj.smart, 4589 bRegex: obj.regex, 4590 bCaseInsensitive: obj.caseInsensitive 4591 }; 4592 } 4593 4594 /** 4595 * Generate the node required for the info display 4596 * @param {object} oSettings dataTables settings object 4597 * @returns {node} Information element 4598 * @memberof DataTable#oApi 4599 */ 4600 function _fnFeatureHtmlInfo ( settings ) 4601 { 4602 var 4603 tid = settings.sTableId, 4604 nodes = settings.aanFeatures.i, 4605 n = $('<div/>', { 4606 'class': settings.oClasses.sInfo, 4607 'id': ! nodes ? tid+'_info' : null 4608 } ); 4609 4610 if ( ! nodes ) { 4611 // Update display on each draw 4612 settings.aoDrawCallback.push( { 4613 "fn": _fnUpdateInfo, 4614 "sName": "information" 4615 } ); 4616 4617 n 4618 .attr( 'role', 'status' ) 4619 .attr( 'aria-live', 'polite' ); 4620 4621 // Table is described by our info div 4622 $(settings.nTable).attr( 'aria-describedby', tid+'_info' ); 4623 } 4624 4625 return n[0]; 4626 } 4627 4628 4629 /** 4630 * Update the information elements in the display 4631 * @param {object} settings dataTables settings object 4632 * @memberof DataTable#oApi 4633 */ 4634 function _fnUpdateInfo ( settings ) 4635 { 4636 /* Show information about the table */ 4637 var nodes = settings.aanFeatures.i; 4638 if ( nodes.length === 0 ) { 4639 return; 4640 } 4641 4642 var 4643 lang = settings.oLanguage, 4644 start = settings._iDisplayStart+1, 4645 end = settings.fnDisplayEnd(), 4646 max = settings.fnRecordsTotal(), 4647 total = settings.fnRecordsDisplay(), 4648 out = total ? 4649 lang.sInfo : 4650 lang.sInfoEmpty; 4651 4652 if ( total !== max ) { 4653 /* Record set after filtering */ 4654 out += ' ' + lang.sInfoFiltered; 4655 } 4656 4657 // Convert the macros 4658 out += lang.sInfoPostFix; 4659 out = _fnInfoMacros( settings, out ); 4660 4661 var callback = lang.fnInfoCallback; 4662 if ( callback !== null ) { 4663 out = callback.call( settings.oInstance, 4664 settings, start, end, max, total, out 4665 ); 4666 } 4667 4668 $(nodes).html( out ); 4669 } 4670 4671 4672 function _fnInfoMacros ( settings, str ) 4673 { 4674 // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only 4675 // internally 4676 var 4677 formatter = settings.fnFormatNumber, 4678 start = settings._iDisplayStart+1, 4679 len = settings._iDisplayLength, 4680 vis = settings.fnRecordsDisplay(), 4681 all = len === -1; 4682 4683 return str. 4684 replace(/_START_/g, formatter.call( settings, start ) ). 4685 replace(/_END_/g, formatter.call( settings, settings.fnDisplayEnd() ) ). 4686 replace(/_MAX_/g, formatter.call( settings, settings.fnRecordsTotal() ) ). 4687 replace(/_TOTAL_/g, formatter.call( settings, vis ) ). 4688 replace(/_PAGE_/g, formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ). 4689 replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) ); 4690 } 4691 4692 4693 4694 /** 4695 * Draw the table for the first time, adding all required features 4696 * @param {object} settings dataTables settings object 4697 * @memberof DataTable#oApi 4698 */ 4699 function _fnInitialise ( settings ) 4700 { 4701 var i, iLen, iAjaxStart=settings.iInitDisplayStart; 4702 var columns = settings.aoColumns, column; 4703 var features = settings.oFeatures; 4704 var deferLoading = settings.bDeferLoading; // value modified by the draw 4705 4706 /* Ensure that the table data is fully initialised */ 4707 if ( ! settings.bInitialised ) { 4708 setTimeout( function(){ _fnInitialise( settings ); }, 200 ); 4709 return; 4710 } 4711 4712 /* Show the display HTML options */ 4713 _fnAddOptionsHtml( settings ); 4714 4715 /* Build and draw the header / footer for the table */ 4716 _fnBuildHead( settings ); 4717 _fnDrawHead( settings, settings.aoHeader ); 4718 _fnDrawHead( settings, settings.aoFooter ); 4719 4720 /* Okay to show that something is going on now */ 4721 _fnProcessingDisplay( settings, true ); 4722 4723 /* Calculate sizes for columns */ 4724 if ( features.bAutoWidth ) { 4725 _fnCalculateColumnWidths( settings ); 4726 } 4727 4728 for ( i=0, iLen=columns.length ; i<iLen ; i++ ) { 4729 column = columns[i]; 4730 4731 if ( column.sWidth ) { 4732 column.nTh.style.width = _fnStringToCss( column.sWidth ); 4733 } 4734 } 4735 4736 _fnCallbackFire( settings, null, 'preInit', [settings] ); 4737 4738 // If there is default sorting required - let's do it. The sort function 4739 // will do the drawing for us. Otherwise we draw the table regardless of the 4740 // Ajax source - this allows the table to look initialised for Ajax sourcing 4741 // data (show 'loading' message possibly) 4742 _fnReDraw( settings ); 4743 4744 // Server-side processing init complete is done by _fnAjaxUpdateDraw 4745 var dataSrc = _fnDataSource( settings ); 4746 if ( dataSrc != 'ssp' || deferLoading ) { 4747 // if there is an ajax source load the data 4748 if ( dataSrc == 'ajax' ) { 4749 _fnBuildAjax( settings, [], function(json) { 4750 var aData = _fnAjaxDataSrc( settings, json ); 4751 4752 // Got the data - add it to the table 4753 for ( i=0 ; i<aData.length ; i++ ) { 4754 _fnAddData( settings, aData[i] ); 4755 } 4756 4757 // Reset the init display for cookie saving. We've already done 4758 // a filter, and therefore cleared it before. So we need to make 4759 // it appear 'fresh' 4760 settings.iInitDisplayStart = iAjaxStart; 4761 4762 _fnReDraw( settings ); 4763 4764 _fnProcessingDisplay( settings, false ); 4765 _fnInitComplete( settings, json ); 4766 }, settings ); 4767 } 4768 else { 4769 _fnProcessingDisplay( settings, false ); 4770 _fnInitComplete( settings ); 4771 } 4772 } 4773 } 4774 4775 4776 /** 4777 * Draw the table for the first time, adding all required features 4778 * @param {object} oSettings dataTables settings object 4779 * @param {object} [json] JSON from the server that completed the table, if using Ajax source 4780 * with client-side processing (optional) 4781 * @memberof DataTable#oApi 4782 */ 4783 function _fnInitComplete ( settings, json ) 4784 { 4785 settings._bInitComplete = true; 4786 4787 // When data was added after the initialisation (data or Ajax) we need to 4788 // calculate the column sizing 4789 if ( json || settings.oInit.aaData ) { 4790 _fnAdjustColumnSizing( settings ); 4791 } 4792 4793 _fnCallbackFire( settings, null, 'plugin-init', [settings, json] ); 4794 _fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] ); 4795 } 4796 4797 4798 function _fnLengthChange ( settings, val ) 4799 { 4800 var len = parseInt( val, 10 ); 4801 settings._iDisplayLength = len; 4802 4803 _fnLengthOverflow( settings ); 4804 4805 // Fire length change event 4806 _fnCallbackFire( settings, null, 'length', [settings, len] ); 4807 } 4808 4809 4810 /** 4811 * Generate the node required for user display length changing 4812 * @param {object} settings dataTables settings object 4813 * @returns {node} Display length feature node 4814 * @memberof DataTable#oApi 4815 */ 4816 function _fnFeatureHtmlLength ( settings ) 4817 { 4818 var 4819 classes = settings.oClasses, 4820 tableId = settings.sTableId, 4821 menu = settings.aLengthMenu, 4822 d2 = $.isArray( menu[0] ), 4823 lengths = d2 ? menu[0] : menu, 4824 language = d2 ? menu[1] : menu; 4825 4826 var select = $('<select/>', { 4827 'name': tableId+'_length', 4828 'aria-controls': tableId, 4829 'class': classes.sLengthSelect 4830 } ); 4831 4832 for ( var i=0, ien=lengths.length ; i<ien ; i++ ) { 4833 select[0][ i ] = new Option( 4834 typeof language[i] === 'number' ? 4835 settings.fnFormatNumber( language[i] ) : 4836 language[i], 4837 lengths[i] 4838 ); 4839 } 4840 4841 var div = $('<div><label/></div>').addClass( classes.sLength ); 4842 if ( ! settings.aanFeatures.l ) { 4843 div[0].id = tableId+'_length'; 4844 } 4845 4846 div.children().append( 4847 settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML ) 4848 ); 4849 4850 // Can't use `select` variable as user might provide their own and the 4851 // reference is broken by the use of outerHTML 4852 $('select', div) 4853 .val( settings._iDisplayLength ) 4854 .on( 'change.DT', function(e) { 4855 _fnLengthChange( settings, $(this).val() ); 4856 _fnDraw( settings ); 4857 } ); 4858 4859 // Update node value whenever anything changes the table's length 4860 $(settings.nTable).on( 'length.dt.DT', function (e, s, len) { 4861 if ( settings === s ) { 4862 $('select', div).val( len ); 4863 } 4864 } ); 4865 4866 return div[0]; 4867 } 4868 4869 4870 4871 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 4872 * Note that most of the paging logic is done in 4873 * DataTable.ext.pager 4874 */ 4875 4876 /** 4877 * Generate the node required for default pagination 4878 * @param {object} oSettings dataTables settings object 4879 * @returns {node} Pagination feature node 4880 * @memberof DataTable#oApi 4881 */ 4882 function _fnFeatureHtmlPaginate ( settings ) 4883 { 4884 var 4885 type = settings.sPaginationType, 4886 plugin = DataTable.ext.pager[ type ], 4887 modern = typeof plugin === 'function', 4888 redraw = function( settings ) { 4889 _fnDraw( settings ); 4890 }, 4891 node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0], 4892 features = settings.aanFeatures; 4893 4894 if ( ! modern ) { 4895 plugin.fnInit( settings, node, redraw ); 4896 } 4897 4898 /* Add a draw callback for the pagination on first instance, to update the paging display */ 4899 if ( ! features.p ) 4900 { 4901 node.id = settings.sTableId+'_paginate'; 4902 4903 settings.aoDrawCallback.push( { 4904 "fn": function( settings ) { 4905 if ( modern ) { 4906 var 4907 start = settings._iDisplayStart, 4908 len = settings._iDisplayLength, 4909 visRecords = settings.fnRecordsDisplay(), 4910 all = len === -1, 4911 page = all ? 0 : Math.ceil( start / len ), 4912 pages = all ? 1 : Math.ceil( visRecords / len ), 4913 buttons = plugin(page, pages), 4914 i, ien; 4915 4916 for ( i=0, ien=features.p.length ; i<ien ; i++ ) { 4917 _fnRenderer( settings, 'pageButton' )( 4918 settings, features.p[i], i, buttons, page, pages 4919 ); 4920 } 4921 } 4922 else { 4923 plugin.fnUpdate( settings, redraw ); 4924 } 4925 }, 4926 "sName": "pagination" 4927 } ); 4928 } 4929 4930 return node; 4931 } 4932 4933 4934 /** 4935 * Alter the display settings to change the page 4936 * @param {object} settings DataTables settings object 4937 * @param {string|int} action Paging action to take: "first", "previous", 4938 * "next" or "last" or page number to jump to (integer) 4939 * @param [bool] redraw Automatically draw the update or not 4940 * @returns {bool} true page has changed, false - no change 4941 * @memberof DataTable#oApi 4942 */ 4943 function _fnPageChange ( settings, action, redraw ) 4944 { 4945 var 4946 start = settings._iDisplayStart, 4947 len = settings._iDisplayLength, 4948 records = settings.fnRecordsDisplay(); 4949 4950 if ( records === 0 || len === -1 ) 4951 { 4952 start = 0; 4953 } 4954 else if ( typeof action === "number" ) 4955 { 4956 start = action * len; 4957 4958 if ( start > records ) 4959 { 4960 start = 0; 4961 } 4962 } 4963 else if ( action == "first" ) 4964 { 4965 start = 0; 4966 } 4967 else if ( action == "previous" ) 4968 { 4969 start = len >= 0 ? 4970 start - len : 4971 0; 4972 4973 if ( start < 0 ) 4974 { 4975 start = 0; 4976 } 4977 } 4978 else if ( action == "next" ) 4979 { 4980 if ( start + len < records ) 4981 { 4982 start += len; 4983 } 4984 } 4985 else if ( action == "last" ) 4986 { 4987 start = Math.floor( (records-1) / len) * len; 4988 } 4989 else 4990 { 4991 _fnLog( settings, 0, "Unknown paging action: "+action, 5 ); 4992 } 4993 4994 var changed = settings._iDisplayStart !== start; 4995 settings._iDisplayStart = start; 4996 4997 if ( changed ) { 4998 _fnCallbackFire( settings, null, 'page', [settings] ); 4999 5000 if ( redraw ) { 5001 _fnDraw( settings ); 5002 } 5003 } 5004 5005 return changed; 5006 } 5007 5008 5009 5010 /** 5011 * Generate the node required for the processing node 5012 * @param {object} settings dataTables settings object 5013 * @returns {node} Processing element 5014 * @memberof DataTable#oApi 5015 */ 5016 function _fnFeatureHtmlProcessing ( settings ) 5017 { 5018 return $('<div/>', { 5019 'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null, 5020 'class': settings.oClasses.sProcessing 5021 } ) 5022 .html( settings.oLanguage.sProcessing ) 5023 .insertBefore( settings.nTable )[0]; 5024 } 5025 5026 5027 /** 5028 * Display or hide the processing indicator 5029 * @param {object} settings dataTables settings object 5030 * @param {bool} show Show the processing indicator (true) or not (false) 5031 * @memberof DataTable#oApi 5032 */ 5033 function _fnProcessingDisplay ( settings, show ) 5034 { 5035 if ( settings.oFeatures.bProcessing ) { 5036 $(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' ); 5037 } 5038 5039 _fnCallbackFire( settings, null, 'processing', [settings, show] ); 5040 } 5041 5042 /** 5043 * Add any control elements for the table - specifically scrolling 5044 * @param {object} settings dataTables settings object 5045 * @returns {node} Node to add to the DOM 5046 * @memberof DataTable#oApi 5047 */ 5048 function _fnFeatureHtmlTable ( settings ) 5049 { 5050 var table = $(settings.nTable); 5051 5052 // Add the ARIA grid role to the table 5053 table.attr( 'role', 'grid'
vendor: 6,387 bytes, lines 5053-5275
5053); 5054 5055 // Scrolling from here on in 5056 var scroll = settings.oScroll; 5057 5058 if ( scroll.sX === '' && scroll.sY === '' ) { 5059 return settings.nTable; 5060 } 5061 5062 var scrollX = scroll.sX; 5063 var scrollY = scroll.sY; 5064 var classes = settings.oClasses; 5065 var caption = table.children('caption'); 5066 var captionSide = caption.length ? caption[0]._captionSide : null; 5067 var headerClone = $( table[0].cloneNode(false) ); 5068 var footerClone = $( table[0].cloneNode(false) ); 5069 var footer = table.children('tfoot'); 5070 var _div = '<div/>'; 5071 var size = function ( s ) { 5072 return !s ? null : _fnStringToCss( s ); 5073 }; 5074 5075 if ( ! footer.length ) { 5076 footer = null; 5077 } 5078 5079 /* 5080 * The HTML structure that we want to generate in this function is: 5081 * div - scroller 5082 * div - scroll head 5083 * div - scroll head inner 5084 * table - scroll head table 5085 * thead - thead 5086 * div - scroll body 5087 * table - table (master table) 5088 * thead - thead clone for sizing 5089 * tbody - tbody 5090 * div - scroll foot 5091 * div - scroll foot inner 5092 * table - scroll foot table 5093 * tfoot - tfoot 5094 */ 5095 var scroller = $( _div, { 'class': classes.sScrollWrapper } ) 5096 .append( 5097 $(_div, { 'class': classes.sScrollHead } ) 5098 .css( { 5099 overflow: 'hidden', 5100 position: 'relative', 5101 border: 0, 5102 width: scrollX ? size(scrollX) : '100%' 5103 } ) 5104 .append( 5105 $(_div, { 'class': classes.sScrollHeadInner } ) 5106 .css( { 5107 'box-sizing': 'content-box', 5108 width: scroll.sXInner || '100%' 5109 } ) 5110 .append( 5111 headerClone 5112 .removeAttr('id') 5113 .css( 'margin-left', 0 ) 5114 .append( captionSide === 'top' ? caption : null ) 5115 .append( 5116 table.children('thead') 5117 ) 5118 ) 5119 ) 5120 ) 5121 .append( 5122 $(_div, { 'class': classes.sScrollBody } ) 5123 .css( { 5124 position: 'relative', 5125 overflow: 'auto', 5126 width: size( scrollX ) 5127 } ) 5128 .append( table ) 5129 ); 5130 5131 if ( footer ) { 5132 scroller.append( 5133 $(_div, { 'class': classes.sScrollFoot } ) 5134 .css( { 5135 overflow: 'hidden', 5136 border: 0, 5137 width: scrollX ? size(scrollX) : '100%' 5138 } ) 5139 .append( 5140 $(_div, { 'class': classes.sScrollFootInner } ) 5141 .append( 5142 footerClone 5143 .removeAttr('id') 5144 .css( 'margin-left', 0 ) 5145 .append( captionSide === 'bottom' ? caption : null ) 5146 .append( 5147 table.children('tfoot') 5148 ) 5149 ) 5150 ) 5151 ); 5152 } 5153 5154 var children = scroller.children(); 5155 var scrollHead = children[0]; 5156 var scrollBody = children[1]; 5157 var scrollFoot = footer ? children[2] : null; 5158 5159 // When the body is scrolled, then we also want to scroll the headers 5160 if ( scrollX ) { 5161 $(scrollBody).on( 'scroll.DT', function (e) { 5162 var scrollLeft = this.scrollLeft; 5163 5164 scrollHead.scrollLeft = scrollLeft; 5165 5166 if ( footer ) { 5167 scrollFoot.scrollLeft = scrollLeft; 5168 } 5169 } ); 5170 } 5171 5172 $(scrollBody).css('max-height', scrollY); 5173 if (! scroll.bCollapse) { 5174 $(scrollBody).css('height', scrollY); 5175 } 5176 5177 settings.nScrollHead = scrollHead; 5178 settings.nScrollBody = scrollBody; 5179 settings.nScrollFoot = scrollFoot; 5180 5181 // On redraw - align columns 5182 settings.aoDrawCallback.push( { 5183 "fn": _fnScrollDraw, 5184 "sName": "scrolling" 5185 } ); 5186 5187 return scroller[0]; 5188 } 5189 5190 5191 5192 /** 5193 * Update the header, footer and body tables for resizing - i.e. column 5194 * alignment. 5195 * 5196 * Welcome to the most horrible function DataTables. The process that this 5197 * function follows is basically: 5198 * 1. Re-create the table inside the scrolling div 5199 * 2. Take live measurements from the DOM 5200 * 3. Apply the measurements to align the columns 5201 * 4. Clean up 5202 * 5203 * @param {object} settings dataTables settings object 5204 * @memberof DataTable#oApi 5205 */ 5206 function _fnScrollDraw ( settings ) 5207 { 5208 // Given that this is such a monster function, a lot of variables are use 5209 // to try and keep the minimised size as small as possible 5210 var 5211 scroll = settings.oScroll, 5212 scrollX = scroll.sX, 5213 scrollXInner = scroll.sXInner, 5214 scrollY = scroll.sY, 5215 barWidth = scroll.iBarWidth, 5216 divHeader = $(settings.nScrollHead), 5217 divHeaderStyle = divHeader[0].style, 5218 divHeaderInner = divHeader.children('div'), 5219 divHeaderInnerStyle = divHeaderInner[0].style, 5220 divHeaderTable = divHeaderInner.children('table'), 5221 divBodyEl = settings.nScrollBody, 5222 divBody = $(divBodyEl), 5223 divBodyStyle = divBodyEl.style, 5224 divFooter = $(settings.nScrollFoot), 5225 divFooterInner = divFooter.children('div'), 5226 divFooterTable = divFooterInner.children('table'), 5227 header = $(settings.nTHead), 5228 table = $(settings.nTable), 5229 tableEl = table[0], 5230 tableStyle = tableEl.style, 5231 footer = settings.nTFoot ? $(settings.nTFoot) : null, 5232 browser = settings.oBrowser, 5233 ie67 = browser.bScrollOversize, 5234 dtHeaderCells = _pluck( settings.aoColumns, 'nTh' ), 5235 headerTrgEls, footerTrgEls, 5236 headerSrcEls, footerSrcEls, 5237 headerCopy, footerCopy, 5238 headerWidths=[], footerWidths=[], 5239 headerContent=[], footerContent=[], 5240 idx, correction, sanityWidth, 5241 zeroOut = function(nSizer) { 5242 var style = nSizer.style; 5243 style.paddingTop = "0"; 5244 style.paddingBottom = "0"; 5245 style.borderTopWidth = "0"; 5246 style.borderBottomWidth = "0"; 5247 style.height = 0; 5248 }; 5249 5250 // If the scrollbar visibility has changed from the last draw, we need to 5251 // adjust the column sizes as the table width will have changed to account 5252 // for the scrollbar 5253 var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight; 5254 5255 if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) { 5256 settings.scrollBarVis = scrollBarVis; 5257 _fnAdjustColumnSizing( settings ); 5258 return; // adjust column sizing will call this function again 5259 } 5260 else { 5261 settings.scrollBarVis = scrollBarVis; 5262 } 5263 5264 /* 5265 * 1. Re-create the table inside the scrolling div 5266 */ 5267 5268 // Remove the old minimised thead and tfoot elements in the inner table 5269 table.children('thead, tfoot').remove(); 5270 5271 if ( footer ) { 5272 footerCopy = footer.clone().prependTo( table ); 5273 footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized 5274 footerSrcEls = footerCopy.find('tr'); 5275
vendor: 4,185 bytes, lines 5275-5402
5275} 5276 5277 // Clone the current header and footer elements and then place it into the inner table 5278 headerCopy = header.clone().prependTo( table ); 5279 headerTrgEls = header.find('tr'); // original header is in its own table 5280 headerSrcEls = headerCopy.find('tr'); 5281 headerCopy.find('th, td').removeAttr('tabindex'); 5282 5283 5284 /* 5285 * 2. Take live measurements from the DOM - do not alter the DOM itself! 5286 */ 5287 5288 // Remove old sizing and apply the calculated column widths 5289 // Get the unique column headers in the newly created (cloned) header. We want to apply the 5290 // calculated sizes to this header 5291 if ( ! scrollX ) 5292 { 5293 divBodyStyle.width = '100%'; 5294 divHeader[0].style.width = '100%'; 5295 } 5296 5297 $.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) { 5298 idx = _fnVisibleToColumnIndex( settings, i ); 5299 el.style.width = settings.aoColumns[idx].sWidth; 5300 } ); 5301 5302 if ( footer ) { 5303 _fnApplyToChildren( function(n) { 5304 n.style.width = ""; 5305 }, footerSrcEls ); 5306 } 5307 5308 // Size the table as a whole 5309 sanityWidth = table.outerWidth(); 5310 if ( scrollX === "" ) { 5311 // No x scrolling 5312 tableStyle.width = "100%"; 5313 5314 // IE7 will make the width of the table when 100% include the scrollbar 5315 // - which is shouldn't. When there is a scrollbar we need to take this 5316 // into account. 5317 if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight || 5318 divBody.css('overflow-y') == "scroll") 5319 ) { 5320 tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth); 5321 } 5322 5323 // Recalculate the sanity width 5324 sanityWidth = table.outerWidth(); 5325 } 5326 else if ( scrollXInner !== "" ) { 5327 // legacy x scroll inner has been given - use it 5328 tableStyle.width = _fnStringToCss(scrollXInner); 5329 5330 // Recalculate the sanity width 5331 sanityWidth = table.outerWidth(); 5332 } 5333 5334 // Hidden header should have zero height, so remove padding and borders. Then 5335 // set the width based on the real headers 5336 5337 // Apply all styles in one pass 5338 _fnApplyToChildren( zeroOut, headerSrcEls ); 5339 5340 // Read all widths in next pass 5341 _fnApplyToChildren( function(nSizer) { 5342 headerContent.push( nSizer.innerHTML ); 5343 headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) ); 5344 }, headerSrcEls ); 5345 5346 // Apply all widths in final pass 5347 _fnApplyToChildren( function(nToSize, i) { 5348 // Only apply widths to the DataTables detected header cells - this 5349 // prevents complex headers from having contradictory sizes applied 5350 if ( $.inArray( nToSize, dtHeaderCells ) !== -1 ) { 5351 nToSize.style.width = headerWidths[i]; 5352 } 5353 }, headerTrgEls ); 5354 5355 $(headerSrcEls).height(0); 5356 5357 /* Same again with the footer if we have one */ 5358 if ( footer ) 5359 { 5360 _fnApplyToChildren( zeroOut, footerSrcEls ); 5361 5362 _fnApplyToChildren( function(nSizer) { 5363 footerContent.push( nSizer.innerHTML ); 5364 footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) ); 5365 }, footerSrcEls ); 5366 5367 _fnApplyToChildren( function(nToSize, i) { 5368 nToSize.style.width = footerWidths[i]; 5369 }, footerTrgEls ); 5370 5371 $(footerSrcEls).height(0); 5372 } 5373 5374 5375 /* 5376 * 3. Apply the measurements 5377 */ 5378 5379 // "Hide" the header and footer that we used for the sizing. We need to keep 5380 // the content of the cell so that the width applied to the header and body 5381 // both match, but we want to hide it completely. We want to also fix their 5382 // width to what they currently are 5383 _fnApplyToChildren( function(nSizer, i) { 5384 nSizer.innerHTML = '<div class="dataTables_sizing">'+headerContent[i]+'</div>'; 5385 nSizer.childNodes[0].style.height = "0"; 5386 nSizer.childNodes[0].style.overflow = "hidden"; 5387 nSizer.style.width = headerWidths[i]; 5388 }, headerSrcEls ); 5389 5390 if ( footer ) 5391 { 5392 _fnApplyToChildren( function(nSizer, i) { 5393 nSizer.innerHTML = '<div class="dataTables_sizing">'+footerContent[i]+'</div>'; 5394 nSizer.childNodes[0].style.height = "0"; 5395 nSizer.childNodes[0].style.overflow = "hidden"; 5396 nSizer.style.width = footerWidths[i]; 5397 }, footerSrcEls ); 5398 } 5399 5400 // Sanity check that the table is of a sensible width. If not then we are going to get 5401 // misalignment - try to prevent this by not allowing the table to shrink below its min width 5402 if ( table.outerWidth() < sanityWidth
vendor: 14,111 bytes, lines 5402-5868
5402 ) 5403 { 5404 // The min width depends upon if we have a vertical scrollbar visible or not */ 5405 correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight || 5406 divBody.css('overflow-y') == "scroll")) ? 5407 sanityWidth+barWidth : 5408 sanityWidth; 5409 5410 // IE6/7 are a law unto themselves... 5411 if ( ie67 && (divBodyEl.scrollHeight > 5412 divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll") 5413 ) { 5414 tableStyle.width = _fnStringToCss( correction-barWidth ); 5415 } 5416 5417 // And give the user a warning that we've stopped the table getting too small 5418 if ( scrollX === "" || scrollXInner !== "" ) { 5419 _fnLog( settings, 1, 'Possible column misalignment', 6 ); 5420 } 5421 } 5422 else 5423 { 5424 correction = '100%'; 5425 } 5426 5427 // Apply to the container elements 5428 divBodyStyle.width = _fnStringToCss( correction ); 5429 divHeaderStyle.width = _fnStringToCss( correction ); 5430 5431 if ( footer ) { 5432 settings.nScrollFoot.style.width = _fnStringToCss( correction ); 5433 } 5434 5435 5436 /* 5437 * 4. Clean up 5438 */ 5439 if ( ! scrollY ) { 5440 /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting 5441 * the scrollbar height from the visible display, rather than adding it on. We need to 5442 * set the height in order to sort this. Don't want to do it in any other browsers. 5443 */ 5444 if ( ie67 ) { 5445 divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth ); 5446 } 5447 } 5448 5449 /* Finally set the width's of the header and footer tables */ 5450 var iOuterWidth = table.outerWidth(); 5451 divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth ); 5452 divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth ); 5453 5454 // Figure out if there are scrollbar present - if so then we need a the header and footer to 5455 // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar) 5456 var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll"; 5457 var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' ); 5458 divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px"; 5459 5460 if ( footer ) { 5461 divFooterTable[0].style.width = _fnStringToCss( iOuterWidth ); 5462 divFooterInner[0].style.width = _fnStringToCss( iOuterWidth ); 5463 divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px"; 5464 } 5465 5466 // Correct DOM ordering for colgroup - comes before the thead 5467 table.children('colgroup').insertBefore( table.children('thead') ); 5468 5469 /* Adjust the position of the header in case we loose the y-scrollbar */ 5470 divBody.trigger('scroll'); 5471 5472 // If sorting or filtering has occurred, jump the scrolling back to the top 5473 // only if we aren't holding the position 5474 if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) { 5475 divBodyEl.scrollTop = 0; 5476 } 5477 } 5478 5479 5480 5481 /** 5482 * Apply a given function to the display child nodes of an element array (typically 5483 * TD children of TR rows 5484 * @param {function} fn Method to apply to the objects 5485 * @param array {nodes} an1 List of elements to look through for display children 5486 * @param array {nodes} an2 Another list (identical structure to the first) - optional 5487 * @memberof DataTable#oApi 5488 */ 5489 function _fnApplyToChildren( fn, an1, an2 ) 5490 { 5491 var index=0, i=0, iLen=an1.length; 5492 var nNode1, nNode2; 5493 5494 while ( i < iLen ) { 5495 nNode1 = an1[i].firstChild; 5496 nNode2 = an2 ? an2[i].firstChild : null; 5497 5498 while ( nNode1 ) { 5499 if ( nNode1.nodeType === 1 ) { 5500 if ( an2 ) { 5501 fn( nNode1, nNode2, index ); 5502 } 5503 else { 5504 fn( nNode1, index ); 5505 } 5506 5507 index++; 5508 } 5509 5510 nNode1 = nNode1.nextSibling; 5511 nNode2 = an2 ? nNode2.nextSibling : null; 5512 } 5513 5514 i++; 5515 } 5516 } 5517 5518 5519 5520 var __re_html_remove = /<.*?>/g; 5521 5522 5523 /** 5524 * Calculate the width of columns for the table 5525 * @param {object} oSettings dataTables settings object 5526 * @memberof DataTable#oApi 5527 */ 5528 function _fnCalculateColumnWidths ( oSettings ) 5529 { 5530 var 5531 table = oSettings.nTable, 5532 columns = oSettings.aoColumns, 5533 scroll = oSettings.oScroll, 5534 scrollY = scroll.sY, 5535 scrollX = scroll.sX, 5536 scrollXInner = scroll.sXInner, 5537 columnCount = columns.length, 5538 visibleColumns = _fnGetColumns( oSettings, 'bVisible' ), 5539 headerCells = $('th', oSettings.nTHead), 5540 tableWidthAttr = table.getAttribute('width'), // from DOM element 5541 tableContainer = table.parentNode, 5542 userInputs = false, 5543 i, column, columnIdx, width, outerWidth, 5544 browser = oSettings.oBrowser, 5545 ie67 = browser.bScrollOversize; 5546 5547 var styleWidth = table.style.width; 5548 if ( styleWidth && styleWidth.indexOf('%') !== -1 ) { 5549 tableWidthAttr = styleWidth; 5550 } 5551 5552 /* Convert any user input sizes into pixel sizes */ 5553 for ( i=0 ; i<visibleColumns.length ; i++ ) { 5554 column = columns[ visibleColumns[i] ]; 5555 5556 if ( column.sWidth !== null ) { 5557 column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer ); 5558 5559 userInputs = true; 5560 } 5561 } 5562 5563 /* If the number of columns in the DOM equals the number that we have to 5564 * process in DataTables, then we can use the offsets that are created by 5565 * the web- browser. No custom sizes can be set in order for this to happen, 5566 * nor scrolling used 5567 */ 5568 if ( ie67 || ! userInputs && ! scrollX && ! scrollY && 5569 columnCount == _fnVisbleColumns( oSettings ) && 5570 columnCount == headerCells.length 5571 ) { 5572 for ( i=0 ; i<columnCount ; i++ ) { 5573 var colIdx = _fnVisibleToColumnIndex( oSettings, i ); 5574 5575 if ( colIdx !== null ) { 5576 columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() ); 5577 } 5578 } 5579 } 5580 else 5581 { 5582 // Otherwise construct a single row, worst case, table with the widest 5583 // node in the data, assign any user defined widths, then insert it into 5584 // the DOM and allow the browser to do all the hard work of calculating 5585 // table widths 5586 var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table 5587 .css( 'visibility', 'hidden' ) 5588 .removeAttr( 'id' ); 5589 5590 // Clean up the table body 5591 tmpTable.find('tbody tr').remove(); 5592 var tr = $('<tr/>').appendTo( tmpTable.find('tbody') ); 5593 5594 // Clone the table header and footer - we can't use the header / footer 5595 // from the cloned table, since if scrolling is active, the table's 5596 // real header and footer are contained in different table tags 5597 tmpTable.find('thead, tfoot').remove(); 5598 tmpTable 5599 .append( $(oSettings.nTHead).clone() ) 5600 .append( $(oSettings.nTFoot).clone() ); 5601 5602 // Remove any assigned widths from the footer (from scrolling) 5603 tmpTable.find('tfoot th, tfoot td').css('width', ''); 5604 5605 // Apply custom sizing to the cloned header 5606 headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] ); 5607 5608 for ( i=0 ; i<visibleColumns.length ; i++ ) { 5609 column = columns[ visibleColumns[i] ]; 5610 5611 headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ? 5612 _fnStringToCss( column.sWidthOrig ) : 5613 ''; 5614 5615 // For scrollX we need to force the column width otherwise the 5616 // browser will collapse it. If this width is smaller than the 5617 // width the column requires, then it will have no effect 5618 if ( column.sWidthOrig && scrollX ) { 5619 $( headerCells[i] ).append( $('<div/>').css( { 5620 width: column.sWidthOrig, 5621 margin: 0, 5622 padding: 0, 5623 border: 0, 5624 height: 1 5625 } ) ); 5626 } 5627 } 5628 5629 // Find the widest cell for each column and put it into the table 5630 if ( oSettings.aoData.length ) { 5631 for ( i=0 ; i<visibleColumns.length ; i++ ) { 5632 columnIdx = visibleColumns[i]; 5633 column = columns[ columnIdx ]; 5634 5635 $( _fnGetWidestNode( oSettings, columnIdx ) ) 5636 .clone( false ) 5637 .append( column.sContentPadding ) 5638 .appendTo( tr ); 5639 } 5640 } 5641 5642 // Tidy the temporary table - remove name attributes so there aren't 5643 // duplicated in the dom (radio elements for example) 5644 $('[name]', tmpTable).removeAttr('name'); 5645 5646 // Table has been built, attach to the document so we can work with it. 5647 // A holding element is used, positioned at the top of the container 5648 // with minimal height, so it has no effect on if the container scrolls 5649 // or not. Otherwise it might trigger scrolling when it actually isn't 5650 // needed 5651 var holder = $('<div/>').css( scrollX || scrollY ? 5652 { 5653 position: 'absolute', 5654 top: 0, 5655 left: 0, 5656 height: 1, 5657 right: 0, 5658 overflow: 'hidden' 5659 } : 5660 {} 5661 ) 5662 .append( tmpTable ) 5663 .appendTo( tableContainer ); 5664 5665 // When scrolling (X or Y) we want to set the width of the table as 5666 // appropriate. However, when not scrolling leave the table width as it 5667 // is. This results in slightly different, but I think correct behaviour 5668 if ( scrollX && scrollXInner ) { 5669 tmpTable.width( scrollXInner ); 5670 } 5671 else if ( scrollX ) { 5672 tmpTable.css( 'width', 'auto' ); 5673 tmpTable.removeAttr('width'); 5674 5675 // If there is no width attribute or style, then allow the table to 5676 // collapse 5677 if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) { 5678 tmpTable.width( tableContainer.clientWidth ); 5679 } 5680 } 5681 else if ( scrollY ) { 5682 tmpTable.width( tableContainer.clientWidth ); 5683 } 5684 else if ( tableWidthAttr ) { 5685 tmpTable.width( tableWidthAttr ); 5686 } 5687 5688 // Get the width of each column in the constructed table - we need to 5689 // know the inner width (so it can be assigned to the other table's 5690 // cells) and the outer width so we can calculate the full width of the 5691 // table. This is safe since DataTables requires a unique cell for each 5692 // column, but if ever a header can span multiple columns, this will 5693 // need to be modified. 5694 var total = 0; 5695 for ( i=0 ; i<visibleColumns.length ; i++ ) { 5696 var cell = $(headerCells[i]); 5697 var border = cell.outerWidth() - cell.width(); 5698 5699 // Use getBounding... where possible (not IE8-) because it can give 5700 // sub-pixel accuracy, which we then want to round up! 5701 var bounding = browser.bBounding ? 5702 Math.ceil( headerCells[i].getBoundingClientRect().width ) : 5703 cell.outerWidth(); 5704 5705 // Total is tracked to remove any sub-pixel errors as the outerWidth 5706 // of the table might not equal the total given here (IE!). 5707 total += bounding; 5708 5709 // Width for each column to use 5710 columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border ); 5711 } 5712 5713 table.style.width = _fnStringToCss( total ); 5714 5715 // Finished with the table - ditch it 5716 holder.remove(); 5717 } 5718 5719 // If there is a width attr, we want to attach an event listener which 5720 // allows the table sizing to automatically adjust when the window is 5721 // resized. Use the width attr rather than CSS, since we can't know if the 5722 // CSS is a relative value or absolute - DOM read is always px. 5723 if ( tableWidthAttr ) { 5724 table.style.width = _fnStringToCss( tableWidthAttr ); 5725 } 5726 5727 if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) { 5728 var bindResize = function () { 5729 $(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () { 5730 _fnAdjustColumnSizing( oSettings ); 5731 } ) ); 5732 }; 5733 5734 // IE6/7 will crash if we bind a resize event handler on page load. 5735 // To be removed in 1.11 which drops IE6/7 support 5736 if ( ie67 ) { 5737 setTimeout( bindResize, 1000 ); 5738 } 5739 else { 5740 bindResize(); 5741 } 5742 5743 oSettings._reszEvt = true; 5744 } 5745 } 5746 5747 5748 /** 5749 * Throttle the calls to a function. Arguments and context are maintained for 5750 * the throttled function 5751 * @param {function} fn Function to be called 5752 * @param {int} [freq=200] call frequency in mS 5753 * @returns {function} wrapped function 5754 * @memberof DataTable#oApi 5755 */ 5756 var _fnThrottle = DataTable.util.throttle; 5757 5758 5759 /** 5760 * Convert a CSS unit width to pixels (e.g. 2em) 5761 * @param {string} width width to be converted 5762 * @param {node} parent parent to get the with for (required for relative widths) - optional 5763 * @returns {int} width in pixels 5764 * @memberof DataTable#oApi 5765 */ 5766 function _fnConvertToWidth ( width, parent ) 5767 { 5768 if ( ! width ) { 5769 return 0; 5770 } 5771 5772 var n = $('<div/>') 5773 .css( 'width', _fnStringToCss( width ) ) 5774 .appendTo( parent || document.body ); 5775 5776 var val = n[0].offsetWidth; 5777 n.remove(); 5778 5779 return val; 5780 } 5781 5782 5783 /** 5784 * Get the widest node 5785 * @param {object} settings dataTables settings object 5786 * @param {int} colIdx column of interest 5787 * @returns {node} widest table node 5788 * @memberof DataTable#oApi 5789 */ 5790 function _fnGetWidestNode( settings, colIdx ) 5791 { 5792 var idx = _fnGetMaxLenString( settings, colIdx ); 5793 if ( idx < 0 ) { 5794 return null; 5795 } 5796 5797 var data = settings.aoData[ idx ]; 5798 return ! data.nTr ? // Might not have been created when deferred rendering 5799 $('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] : 5800 data.anCells[ colIdx ]; 5801 } 5802 5803 5804 /** 5805 * Get the maximum strlen for each data column 5806 * @param {object} settings dataTables settings object 5807 * @param {int} colIdx column of interest 5808 * @returns {string} max string length for each column 5809 * @memberof DataTable#oApi 5810 */ 5811 function _fnGetMaxLenString( settings, colIdx ) 5812 { 5813 var s, max=-1, maxIdx = -1; 5814 5815 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 5816 s = _fnGetCellData( settings, i, colIdx, 'display' )+''; 5817 s = s.replace( __re_html_remove, '' ); 5818 s = s.replace( / /g, ' ' ); 5819 5820 if ( s.length > max ) { 5821 max = s.length; 5822 maxIdx = i; 5823 } 5824 } 5825 5826 return maxIdx; 5827 } 5828 5829 5830 /** 5831 * Append a CSS unit (only if required) to a string 5832 * @param {string} value to css-ify 5833 * @returns {string} value with css unit 5834 * @memberof DataTable#oApi 5835 */ 5836 function _fnStringToCss( s ) 5837 { 5838 if ( s === null ) { 5839 return '0px'; 5840 } 5841 5842 if ( typeof s == 'number' ) { 5843 return s < 0 ? 5844 '0px' : 5845 s+'px'; 5846 } 5847 5848 // Check it has a unit character already 5849 return s.match(/\d$/) ? 5850 s+'px' : 5851 s; 5852 } 5853 5854 5855 5856 function _fnSortFlatten ( settings ) 5857 { 5858 var 5859 i, iLen, k, kLen, 5860 aSort = [], 5861 aiOrig = [], 5862 aoColumns = settings.aoColumns, 5863 aDataSort, iCol, sType, srcCol, 5864 fixed = settings.aaSortingFixed, 5865 fixedObj = $.isPlainObject( fixed ), 5866 nestedSort = [], 5867 add = function ( a ) { 5868 if ( a.length && !
vendor: 38,761 bytes, lines 5868-7358
5868$.isArray( a[0] ) ) { 5869 // 1D array 5870 nestedSort.push( a ); 5871 } 5872 else { 5873 // 2D array 5874 $.merge( nestedSort, a ); 5875 } 5876 }; 5877 5878 // Build the sort array, with pre-fix and post-fix options if they have been 5879 // specified 5880 if ( $.isArray( fixed ) ) { 5881 add( fixed ); 5882 } 5883 5884 if ( fixedObj && fixed.pre ) { 5885 add( fixed.pre ); 5886 } 5887 5888 add( settings.aaSorting ); 5889 5890 if (fixedObj && fixed.post ) { 5891 add( fixed.post ); 5892 } 5893 5894 for ( i=0 ; i<nestedSort.length ; i++ ) 5895 { 5896 srcCol = nestedSort[i][0]; 5897 aDataSort = aoColumns[ srcCol ].aDataSort; 5898 5899 for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ ) 5900 { 5901 iCol = aDataSort[k]; 5902 sType = aoColumns[ iCol ].sType || 'string'; 5903 5904 if ( nestedSort[i]._idx === undefined ) { 5905 nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting ); 5906 } 5907 5908 aSort.push( { 5909 src: srcCol, 5910 col: iCol, 5911 dir: nestedSort[i][1], 5912 index: nestedSort[i]._idx, 5913 type: sType, 5914 formatter: DataTable.ext.type.order[ sType+"-pre" ] 5915 } ); 5916 } 5917 } 5918 5919 return aSort; 5920 } 5921 5922 /** 5923 * Change the order of the table 5924 * @param {object} oSettings dataTables settings object 5925 * @memberof DataTable#oApi 5926 * @todo This really needs split up! 5927 */ 5928 function _fnSort ( oSettings ) 5929 { 5930 var 5931 i, ien, iLen, j, jLen, k, kLen, 5932 sDataType, nTh, 5933 aiOrig = [], 5934 oExtSort = DataTable.ext.type.order, 5935 aoData = oSettings.aoData, 5936 aoColumns = oSettings.aoColumns, 5937 aDataSort, data, iCol, sType, oSort, 5938 formatters = 0, 5939 sortCol, 5940 displayMaster = oSettings.aiDisplayMaster, 5941 aSort; 5942 5943 // Resolve any column types that are unknown due to addition or invalidation 5944 // @todo Can this be moved into a 'data-ready' handler which is called when 5945 // data is going to be used in the table? 5946 _fnColumnTypes( oSettings ); 5947 5948 aSort = _fnSortFlatten( oSettings ); 5949 5950 for ( i=0, ien=aSort.length ; i<ien ; i++ ) { 5951 sortCol = aSort[i]; 5952 5953 // Track if we can use the fast sort algorithm 5954 if ( sortCol.formatter ) { 5955 formatters++; 5956 } 5957 5958 // Load the data needed for the sort, for each cell 5959 _fnSortData( oSettings, sortCol.col ); 5960 } 5961 5962 /* No sorting required if server-side or no sorting array */ 5963 if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 ) 5964 { 5965 // Create a value - key array of the current row positions such that we can use their 5966 // current position during the sort, if values match, in order to perform stable sorting 5967 for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) { 5968 aiOrig[ displayMaster[i] ] = i; 5969 } 5970 5971 /* Do the sort - here we want multi-column sorting based on a given data source (column) 5972 * and sorting function (from oSort) in a certain direction. It's reasonably complex to 5973 * follow on it's own, but this is what we want (example two column sorting): 5974 * fnLocalSorting = function(a,b){ 5975 * var iTest; 5976 * iTest = oSort['string-asc']('data11', 'data12'); 5977 * if (iTest !== 0) 5978 * return iTest; 5979 * iTest = oSort['numeric-desc']('data21', 'data22'); 5980 * if (iTest !== 0) 5981 * return iTest; 5982 * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] ); 5983 * } 5984 * Basically we have a test for each sorting column, if the data in that column is equal, 5985 * test the next column. If all columns match, then we use a numeric sort on the row 5986 * positions in the original data array to provide a stable sort. 5987 * 5988 * Note - I know it seems excessive to have two sorting methods, but the first is around 5989 * 15% faster, so the second is only maintained for backwards compatibility with sorting 5990 * methods which do not have a pre-sort formatting function. 5991 */ 5992 if ( formatters === aSort.length ) { 5993 // All sort types have formatting functions 5994 displayMaster.sort( function ( a, b ) { 5995 var 5996 x, y, k, test, sort, 5997 len=aSort.length, 5998 dataA = aoData[a]._aSortData, 5999 dataB = aoData[b]._aSortData; 6000 6001 for ( k=0 ; k<len ; k++ ) { 6002 sort = aSort[k]; 6003 6004 x = dataA[ sort.col ]; 6005 y = dataB[ sort.col ]; 6006 6007 test = x<y ? -1 : x>y ? 1 : 0; 6008 if ( test !== 0 ) { 6009 return sort.dir === 'asc' ? test : -test; 6010 } 6011 } 6012 6013 x = aiOrig[a]; 6014 y = aiOrig[b]; 6015 return x<y ? -1 : x>y ? 1 : 0; 6016 } ); 6017 } 6018 else { 6019 // Depreciated - remove in 1.11 (providing a plug-in option) 6020 // Not all sort types have formatting methods, so we have to call their sorting 6021 // methods. 6022 displayMaster.sort( function ( a, b ) { 6023 var 6024 x, y, k, l, test, sort, fn, 6025 len=aSort.length, 6026 dataA = aoData[a]._aSortData, 6027 dataB = aoData[b]._aSortData; 6028 6029 for ( k=0 ; k<len ; k++ ) { 6030 sort = aSort[k]; 6031 6032 x = dataA[ sort.col ]; 6033 y = dataB[ sort.col ]; 6034 6035 fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ]; 6036 test = fn( x, y ); 6037 if ( test !== 0 ) { 6038 return test; 6039 } 6040 } 6041 6042 x = aiOrig[a]; 6043 y = aiOrig[b]; 6044 return x<y ? -1 : x>y ? 1 : 0; 6045 } ); 6046 } 6047 } 6048 6049 /* Tell the draw function that we have sorted the data */ 6050 oSettings.bSorted = true; 6051 } 6052 6053 6054 function _fnSortAria ( settings ) 6055 { 6056 var label; 6057 var nextSort; 6058 var columns = settings.aoColumns; 6059 var aSort = _fnSortFlatten( settings ); 6060 var oAria = settings.oLanguage.oAria; 6061 6062 // ARIA attributes - need to loop all columns, to update all (removing old 6063 // attributes as needed) 6064 for ( var i=0, iLen=columns.length ; i<iLen ; i++ ) 6065 { 6066 var col = columns[i]; 6067 var asSorting = col.asSorting; 6068 var sTitle = col.sTitle.replace( /<.*?>/g, "" ); 6069 var th = col.nTh; 6070 6071 // IE7 is throwing an error when setting these properties with jQuery's 6072 // attr() and removeAttr() methods... 6073 th.removeAttribute('aria-sort'); 6074 6075 /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */ 6076 if ( col.bSortable ) { 6077 if ( aSort.length > 0 && aSort[0].col == i ) { 6078 th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" ); 6079 nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0]; 6080 } 6081 else { 6082 nextSort = asSorting[0]; 6083 } 6084 6085 label = sTitle + ( nextSort === "asc" ? 6086 oAria.sSortAscending : 6087 oAria.sSortDescending 6088 ); 6089 } 6090 else { 6091 label = sTitle; 6092 } 6093 6094 th.setAttribute('aria-label', label); 6095 } 6096 } 6097 6098 6099 /** 6100 * Function to run on user sort request 6101 * @param {object} settings dataTables settings object 6102 * @param {node} attachTo node to attach the handler to 6103 * @param {int} colIdx column sorting index 6104 * @param {boolean} [append=false] Append the requested sort to the existing 6105 * sort if true (i.e. multi-column sort) 6106 * @param {function} [callback] callback function 6107 * @memberof DataTable#oApi 6108 */ 6109 function _fnSortListener ( settings, colIdx, append, callback ) 6110 { 6111 var col = settings.aoColumns[ colIdx ]; 6112 var sorting = settings.aaSorting; 6113 var asSorting = col.asSorting; 6114 var nextSortIdx; 6115 var next = function ( a, overflow ) { 6116 var idx = a._idx; 6117 if ( idx === undefined ) { 6118 idx = $.inArray( a[1], asSorting ); 6119 } 6120 6121 return idx+1 < asSorting.length ? 6122 idx+1 : 6123 overflow ? 6124 null : 6125 0; 6126 }; 6127 6128 // Convert to 2D array if needed 6129 if ( typeof sorting[0] === 'number' ) { 6130 sorting = settings.aaSorting = [ sorting ]; 6131 } 6132 6133 // If appending the sort then we are multi-column sorting 6134 if ( append && settings.oFeatures.bSortMulti ) { 6135 // Are we already doing some kind of sort on this column? 6136 var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') ); 6137 6138 if ( sortIdx !== -1 ) { 6139 // Yes, modify the sort 6140 nextSortIdx = next( sorting[sortIdx], true ); 6141 6142 if ( nextSortIdx === null && sorting.length === 1 ) { 6143 nextSortIdx = 0; // can't remove sorting completely 6144 } 6145 6146 if ( nextSortIdx === null ) { 6147 sorting.splice( sortIdx, 1 ); 6148 } 6149 else { 6150 sorting[sortIdx][1] = asSorting[ nextSortIdx ]; 6151 sorting[sortIdx]._idx = nextSortIdx; 6152 } 6153 } 6154 else { 6155 // No sort on this column yet 6156 sorting.push( [ colIdx, asSorting[0], 0 ] ); 6157 sorting[sorting.length-1]._idx = 0; 6158 } 6159 } 6160 else if ( sorting.length && sorting[0][0] == colIdx ) { 6161 // Single column - already sorting on this column, modify the sort 6162 nextSortIdx = next( sorting[0] ); 6163 6164 sorting.length = 1; 6165 sorting[0][1] = asSorting[ nextSortIdx ]; 6166 sorting[0]._idx = nextSortIdx; 6167 } 6168 else { 6169 // Single column - sort only on this column 6170 sorting.length = 0; 6171 sorting.push( [ colIdx, asSorting[0] ] ); 6172 sorting[0]._idx = 0; 6173 } 6174 6175 // Run the sort by calling a full redraw 6176 _fnReDraw( settings ); 6177 6178 // callback used for async user interaction 6179 if ( typeof callback == 'function' ) { 6180 callback( settings ); 6181 } 6182 } 6183 6184 6185 /** 6186 * Attach a sort handler (click) to a node 6187 * @param {object} settings dataTables settings object 6188 * @param {node} attachTo node to attach the handler to 6189 * @param {int} colIdx column sorting index 6190 * @param {function} [callback] callback function 6191 * @memberof DataTable#oApi 6192 */ 6193 function _fnSortAttachListener ( settings, attachTo, colIdx, callback ) 6194 { 6195 var col = settings.aoColumns[ colIdx ]; 6196 6197 _fnBindAction( attachTo, {}, function (e) { 6198 /* If the column is not sortable - don't to anything */ 6199 if ( col.bSortable === false ) { 6200 return; 6201 } 6202 6203 // If processing is enabled use a timeout to allow the processing 6204 // display to be shown - otherwise to it synchronously 6205 if ( settings.oFeatures.bProcessing ) { 6206 _fnProcessingDisplay( settings, true ); 6207 6208 setTimeout( function() { 6209 _fnSortListener( settings, colIdx, e.shiftKey, callback ); 6210 6211 // In server-side processing, the draw callback will remove the 6212 // processing display 6213 if ( _fnDataSource( settings ) !== 'ssp' ) { 6214 _fnProcessingDisplay( settings, false ); 6215 } 6216 }, 0 ); 6217 } 6218 else { 6219 _fnSortListener( settings, colIdx, e.shiftKey, callback ); 6220 } 6221 } ); 6222 } 6223 6224 6225 /** 6226 * Set the sorting classes on table's body, Note: it is safe to call this function 6227 * when bSort and bSortClasses are false 6228 * @param {object} oSettings dataTables settings object 6229 * @memberof DataTable#oApi 6230 */ 6231 function _fnSortingClasses( settings ) 6232 { 6233 var oldSort = settings.aLastSort; 6234 var sortClass = settings.oClasses.sSortColumn; 6235 var sort = _fnSortFlatten( settings ); 6236 var features = settings.oFeatures; 6237 var i, ien, colIdx; 6238 6239 if ( features.bSort && features.bSortClasses ) { 6240 // Remove old sorting classes 6241 for ( i=0, ien=oldSort.length ; i<ien ; i++ ) { 6242 colIdx = oldSort[i].src; 6243 6244 // Remove column sorting 6245 $( _pluck( settings.aoData, 'anCells', colIdx ) ) 6246 .removeClass( sortClass + (i<2 ? i+1 : 3) ); 6247 } 6248 6249 // Add new column sorting 6250 for ( i=0, ien=sort.length ; i<ien ; i++ ) { 6251 colIdx = sort[i].src; 6252 6253 $( _pluck( settings.aoData, 'anCells', colIdx ) ) 6254 .addClass( sortClass + (i<2 ? i+1 : 3) ); 6255 } 6256 } 6257 6258 settings.aLastSort = sort; 6259 } 6260 6261 6262 // Get the data to sort a column, be it from cache, fresh (populating the 6263 // cache), or from a sort formatter 6264 function _fnSortData( settings, idx ) 6265 { 6266 // Custom sorting function - provided by the sort data type 6267 var column = settings.aoColumns[ idx ]; 6268 var customSort = DataTable.ext.order[ column.sSortDataType ]; 6269 var customData; 6270 6271 if ( customSort ) { 6272 customData = customSort.call( settings.oInstance, settings, idx, 6273 _fnColumnIndexToVisible( settings, idx ) 6274 ); 6275 } 6276 6277 // Use / populate cache 6278 var row, cellData; 6279 var formatter = DataTable.ext.type.order[ column.sType+"-pre" ]; 6280 6281 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 6282 row = settings.aoData[i]; 6283 6284 if ( ! row._aSortData ) { 6285 row._aSortData = []; 6286 } 6287 6288 if ( ! row._aSortData[idx] || customSort ) { 6289 cellData = customSort ? 6290 customData[i] : // If there was a custom sort function, use data from there 6291 _fnGetCellData( settings, i, idx, 'sort' ); 6292 6293 row._aSortData[ idx ] = formatter ? 6294 formatter( cellData ) : 6295 cellData; 6296 } 6297 } 6298 } 6299 6300 6301 6302 /** 6303 * Save the state of a table 6304 * @param {object} oSettings dataTables settings object 6305 * @memberof DataTable#oApi 6306 */ 6307 function _fnSaveState ( settings ) 6308 { 6309 if ( !settings.oFeatures.bStateSave || settings.bDestroying ) 6310 { 6311 return; 6312 } 6313 6314 /* Store the interesting variables */ 6315 var state = { 6316 time: +new Date(), 6317 start: settings._iDisplayStart, 6318 length: settings._iDisplayLength, 6319 order: $.extend( true, [], settings.aaSorting ), 6320 search: _fnSearchToCamel( settings.oPreviousSearch ), 6321 columns: $.map( settings.aoColumns, function ( col, i ) { 6322 return { 6323 visible: col.bVisible, 6324 search: _fnSearchToCamel( settings.aoPreSearchCols[i] ) 6325 }; 6326 } ) 6327 }; 6328 6329 _fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] ); 6330 6331 settings.oSavedState = state; 6332 settings.fnStateSaveCallback.call( settings.oInstance, settings, state ); 6333 } 6334 6335 6336 /** 6337 * Attempt to load a saved table state 6338 * @param {object} oSettings dataTables settings object 6339 * @param {object} oInit DataTables init object so we can override settings 6340 * @param {function} callback Callback to execute when the state has been loaded 6341 * @memberof DataTable#oApi 6342 */ 6343 function _fnLoadState ( settings, oInit, callback ) 6344 { 6345 var i, ien; 6346 var columns = settings.aoColumns; 6347 var loaded = function ( s ) { 6348 if ( ! s || ! s.time ) { 6349 callback(); 6350 return; 6351 } 6352 6353 // Allow custom and plug-in manipulation functions to alter the saved data set and 6354 // cancelling of loading by returning false 6355 var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] ); 6356 if ( $.inArray( false, abStateLoad ) !== -1 ) { 6357 callback(); 6358 return; 6359 } 6360 6361 // Reject old data 6362 var duration = settings.iStateDuration; 6363 if ( duration > 0 && s.time < +new Date() - (duration*1000) ) { 6364 callback(); 6365 return; 6366 } 6367 6368 // Number of columns have changed - all bets are off, no restore of settings 6369 if ( s.columns && columns.length !== s.columns.length ) { 6370 callback(); 6371 return; 6372 } 6373 6374 // Store the saved state so it might be accessed at any time 6375 settings.oLoadedState = $.extend( true, {}, s ); 6376 6377 // Restore key features - todo - for 1.11 this needs to be done by 6378 // subscribed events 6379 if ( s.start !== undefined ) { 6380 settings._iDisplayStart = s.start; 6381 settings.iInitDisplayStart = s.start; 6382 } 6383 if ( s.length !== undefined ) { 6384 settings._iDisplayLength = s.length; 6385 } 6386 6387 // Order 6388 if ( s.order !== undefined ) { 6389 settings.aaSorting = []; 6390 $.each( s.order, function ( i, col ) { 6391 settings.aaSorting.push( col[0] >= columns.length ? 6392 [ 0, col[1] ] : 6393 col 6394 ); 6395 } ); 6396 } 6397 6398 // Search 6399 if ( s.search !== undefined ) { 6400 $.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) ); 6401 } 6402 6403 // Columns 6404 // 6405 if ( s.columns ) { 6406 for ( i=0, ien=s.columns.length ; i<ien ; i++ ) { 6407 var col = s.columns[i]; 6408 6409 // Visibility 6410 if ( col.visible !== undefined ) { 6411 columns[i].bVisible = col.visible; 6412 } 6413 6414 // Search 6415 if ( col.search !== undefined ) { 6416 $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) ); 6417 } 6418 } 6419 } 6420 6421 _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] ); 6422 callback(); 6423 }; 6424 6425 if ( ! settings.oFeatures.bStateSave ) { 6426 callback(); 6427 return; 6428 } 6429 6430 var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded ); 6431 6432 if ( state !== undefined ) { 6433 loaded( state ); 6434 } 6435 // otherwise, wait for the loaded callback to be executed 6436 } 6437 6438 6439 /** 6440 * Return the settings object for a particular table 6441 * @param {node} table table we are using as a dataTable 6442 * @returns {object} Settings object - or null if not found 6443 * @memberof DataTable#oApi 6444 */ 6445 function _fnSettingsFromNode ( table ) 6446 { 6447 var settings = DataTable.settings; 6448 var idx = $.inArray( table, _pluck( settings, 'nTable' ) ); 6449 6450 return idx !== -1 ? 6451 settings[ idx ] : 6452 null; 6453 } 6454 6455 6456 /** 6457 * Log an error message 6458 * @param {object} settings dataTables settings object 6459 * @param {int} level log error messages, or display them to the user 6460 * @param {string} msg error message 6461 * @param {int} tn Technical note id to get more information about the error. 6462 * @memberof DataTable#oApi 6463 */ 6464 function _fnLog( settings, level, msg, tn ) 6465 { 6466 msg = 'DataTables warning: '+ 6467 (settings ? 'table id='+settings.sTableId+' - ' : '')+msg; 6468 6469 if ( tn ) { 6470 msg += '. For more information about this error, please see '+ 6471 'http://datatables.net/tn/'+tn; 6472 } 6473 6474 if ( ! level ) { 6475 // Backwards compatibility pre 1.10 6476 var ext = DataTable.ext; 6477 var type = ext.sErrMode || ext.errMode; 6478 6479 if ( settings ) { 6480 _fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] ); 6481 } 6482 6483 if ( type == 'alert' ) { 6484 alert( msg ); 6485 } 6486 else if ( type == 'throw' ) { 6487 throw new Error(msg); 6488 } 6489 else if ( typeof type == 'function' ) { 6490 type( settings, tn, msg ); 6491 } 6492 } 6493 else if ( window.console && console.log ) { 6494 console.log( msg ); 6495 } 6496 } 6497 6498 6499 /** 6500 * See if a property is defined on one object, if so assign it to the other object 6501 * @param {object} ret target object 6502 * @param {object} src source object 6503 * @param {string} name property 6504 * @param {string} [mappedName] name to map too - optional, name used if not given 6505 * @memberof DataTable#oApi 6506 */ 6507 function _fnMap( ret, src, name, mappedName ) 6508 { 6509 if ( $.isArray( name ) ) { 6510 $.each( name, function (i, val) { 6511 if ( $.isArray( val ) ) { 6512 _fnMap( ret, src, val[0], val[1] ); 6513 } 6514 else { 6515 _fnMap( ret, src, val ); 6516 } 6517 } ); 6518 6519 return; 6520 } 6521 6522 if ( mappedName === undefined ) { 6523 mappedName = name; 6524 } 6525 6526 if ( src[name] !== undefined ) { 6527 ret[mappedName] = src[name]; 6528 } 6529 } 6530 6531 6532 /** 6533 * Extend objects - very similar to jQuery.extend, but deep copy objects, and 6534 * shallow copy arrays. The reason we need to do this, is that we don't want to 6535 * deep copy array init values (such as aaSorting) since the dev wouldn't be 6536 * able to override them, but we do want to deep copy arrays. 6537 * @param {object} out Object to extend 6538 * @param {object} extender Object from which the properties will be applied to 6539 * out 6540 * @param {boolean} breakRefs If true, then arrays will be sliced to take an 6541 * independent copy with the exception of the `data` or `aaData` parameters 6542 * if they are present. This is so you can pass in a collection to 6543 * DataTables and have that used as your data source without breaking the 6544 * references 6545 * @returns {object} out Reference, just for convenience - out === the return. 6546 * @memberof DataTable#oApi 6547 * @todo This doesn't take account of arrays inside the deep copied objects. 6548 */ 6549 function _fnExtend( out, extender, breakRefs ) 6550 { 6551 var val; 6552 6553 for ( var prop in extender ) { 6554 if ( extender.hasOwnProperty(prop) ) { 6555 val = extender[prop]; 6556 6557 if ( $.isPlainObject( val ) ) { 6558 if ( ! $.isPlainObject( out[prop] ) ) { 6559 out[prop] = {}; 6560 } 6561 $.extend( true, out[prop], val ); 6562 } 6563 else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) { 6564 out[prop] = val.slice(); 6565 } 6566 else { 6567 out[prop] = val; 6568 } 6569 } 6570 } 6571 6572 return out; 6573 } 6574 6575 6576 /** 6577 * Bind an event handers to allow a click or return key to activate the callback. 6578 * This is good for accessibility since a return on the keyboard will have the 6579 * same effect as a click, if the element has focus. 6580 * @param {element} n Element to bind the action to 6581 * @param {object} oData Data object to pass to the triggered function 6582 * @param {function} fn Callback function for when the event is triggered 6583 * @memberof DataTable#oApi 6584 */ 6585 function _fnBindAction( n, oData, fn ) 6586 { 6587 $(n) 6588 .on( 'click.DT', oData, function (e) { 6589 $(n).trigger('blur'); // Remove focus outline for mouse users 6590 fn(e); 6591 } ) 6592 .on( 'keypress.DT', oData, function (e){ 6593 if ( e.which === 13 ) { 6594 e.preventDefault(); 6595 fn(e); 6596 } 6597 } ) 6598 .on( 'selectstart.DT', function () { 6599 /* Take the brutal approach to cancelling text selection */ 6600 return false; 6601 } ); 6602 } 6603 6604 6605 /** 6606 * Register a callback function. Easily allows a callback function to be added to 6607 * an array store of callback functions that can then all be called together. 6608 * @param {object} oSettings dataTables settings object 6609 * @param {string} sStore Name of the array storage for the callbacks in oSettings 6610 * @param {function} fn Function to be called back 6611 * @param {string} sName Identifying name for the callback (i.e. a label) 6612 * @memberof DataTable#oApi 6613 */ 6614 function _fnCallbackReg( oSettings, sStore, fn, sName ) 6615 { 6616 if ( fn ) 6617 { 6618 oSettings[sStore].push( { 6619 "fn": fn, 6620 "sName": sName 6621 } ); 6622 } 6623 } 6624 6625 6626 /** 6627 * Fire callback functions and trigger events. Note that the loop over the 6628 * callback array store is done backwards! Further note that you do not want to 6629 * fire off triggers in time sensitive applications (for example cell creation) 6630 * as its slow. 6631 * @param {object} settings dataTables settings object 6632 * @param {string} callbackArr Name of the array storage for the callbacks in 6633 * oSettings 6634 * @param {string} eventName Name of the jQuery custom event to trigger. If 6635 * null no trigger is fired 6636 * @param {array} args Array of arguments to pass to the callback function / 6637 * trigger 6638 * @memberof DataTable#oApi 6639 */ 6640 function _fnCallbackFire( settings, callbackArr, eventName, args ) 6641 { 6642 var ret = []; 6643 6644 if ( callbackArr ) { 6645 ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) { 6646 return val.fn.apply( settings.oInstance, args ); 6647 } ); 6648 } 6649 6650 if ( eventName !== null ) { 6651 var e = $.Event( eventName+'.dt' ); 6652 6653 $(settings.nTable).trigger( e, args ); 6654 6655 ret.push( e.result ); 6656 } 6657 6658 return ret; 6659 } 6660 6661 6662 function _fnLengthOverflow ( settings ) 6663 { 6664 var 6665 start = settings._iDisplayStart, 6666 end = settings.fnDisplayEnd(), 6667 len = settings._iDisplayLength; 6668 6669 /* If we have space to show extra rows (backing up from the end point - then do so */ 6670 if ( start >= end ) 6671 { 6672 start = end - len; 6673 } 6674 6675 // Keep the start record on the current page 6676 start -= (start % len); 6677 6678 if ( len === -1 || start < 0 ) 6679 { 6680 start = 0; 6681 } 6682 6683 settings._iDisplayStart = start; 6684 } 6685 6686 6687 function _fnRenderer( settings, type ) 6688 { 6689 var renderer = settings.renderer; 6690 var host = DataTable.ext.renderer[type]; 6691 6692 if ( $.isPlainObject( renderer ) && renderer[type] ) { 6693 // Specific renderer for this type. If available use it, otherwise use 6694 // the default. 6695 return host[renderer[type]] || host._; 6696 } 6697 else if ( typeof renderer === 'string' ) { 6698 // Common renderer - if there is one available for this type use it, 6699 // otherwise use the default 6700 return host[renderer] || host._; 6701 } 6702 6703 // Use the default 6704 return host._; 6705 } 6706 6707 6708 /** 6709 * Detect the data source being used for the table. Used to simplify the code 6710 * a little (ajax) and to make it compress a little smaller. 6711 * 6712 * @param {object} settings dataTables settings object 6713 * @returns {string} Data source 6714 * @memberof DataTable#oApi 6715 */ 6716 function _fnDataSource ( settings ) 6717 { 6718 if ( settings.oFeatures.bServerSide ) { 6719 return 'ssp'; 6720 } 6721 else if ( settings.ajax || settings.sAjaxSource ) { 6722 return 'ajax'; 6723 } 6724 return 'dom'; 6725 } 6726 6727 6728 6729 6730 /** 6731 * Computed structure of the DataTables API, defined by the options passed to 6732 * `DataTable.Api.register()` when building the API. 6733 * 6734 * The structure is built in order to speed creation and extension of the Api 6735 * objects since the extensions are effectively pre-parsed. 6736 * 6737 * The array is an array of objects with the following structure, where this 6738 * base array represents the Api prototype base: 6739 * 6740 * [ 6741 * { 6742 * name: 'data' -- string - Property name 6743 * val: function () {}, -- function - Api method (or undefined if just an object 6744 * methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result 6745 * propExt: [ ... ] -- array - Array of Api object definitions to extend the property 6746 * }, 6747 * { 6748 * name: 'row' 6749 * val: {}, 6750 * methodExt: [ ... ], 6751 * propExt: [ 6752 * { 6753 * name: 'data' 6754 * val: function () {}, 6755 * methodExt: [ ... ], 6756 * propExt: [ ... ] 6757 * }, 6758 * ... 6759 * ] 6760 * } 6761 * ] 6762 * 6763 * @type {Array} 6764 * @ignore 6765 */ 6766 var __apiStruct = []; 6767 6768 6769 /** 6770 * `Array.prototype` reference. 6771 * 6772 * @type object 6773 * @ignore 6774 */ 6775 var __arrayProto = Array.prototype; 6776 6777 6778 /** 6779 * Abstraction for `context` parameter of the `Api` constructor to allow it to 6780 * take several different forms for ease of use. 6781 * 6782 * Each of the input parameter types will be converted to a DataTables settings 6783 * object where possible. 6784 * 6785 * @param {string|node|jQuery|object} mixed DataTable identifier. Can be one 6786 * of: 6787 * 6788 * * `string` - jQuery selector. Any DataTables' matching the given selector 6789 * with be found and used. 6790 * * `node` - `TABLE` node which has already been formed into a DataTable. 6791 * * `jQuery` - A jQuery object of `TABLE` nodes. 6792 * * `object` - DataTables settings object 6793 * * `DataTables.Api` - API instance 6794 * @return {array|null} Matching DataTables settings objects. `null` or 6795 * `undefined` is returned if no matching DataTable is found. 6796 * @ignore 6797 */ 6798 var _toSettings = function ( mixed ) 6799 { 6800 var idx, jq; 6801 var settings = DataTable.settings; 6802 var tables = $.map( settings, function (el, i) { 6803 return el.nTable; 6804 } ); 6805 6806 if ( ! mixed ) { 6807 return []; 6808 } 6809 else if ( mixed.nTable && mixed.oApi ) { 6810 // DataTables settings object 6811 return [ mixed ]; 6812 } 6813 else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) { 6814 // Table node 6815 idx = $.inArray( mixed, tables ); 6816 return idx !== -1 ? [ settings[idx] ] : null; 6817 } 6818 else if ( mixed && typeof mixed.settings === 'function' ) { 6819 return mixed.settings().toArray(); 6820 } 6821 else if ( typeof mixed === 'string' ) { 6822 // jQuery selector 6823 jq = $(mixed); 6824 } 6825 else if ( mixed instanceof $ ) { 6826 // jQuery object (also DataTables instance) 6827 jq = mixed; 6828 } 6829 6830 if ( jq ) { 6831 return jq.map( function(i) { 6832 idx = $.inArray( this, tables ); 6833 return idx !== -1 ? settings[idx] : null; 6834 } ).toArray(); 6835 } 6836 }; 6837 6838 6839 /** 6840 * DataTables API class - used to control and interface with one or more 6841 * DataTables enhanced tables. 6842 * 6843 * The API class is heavily based on jQuery, presenting a chainable interface 6844 * that you can use to interact with tables. Each instance of the API class has 6845 * a "context" - i.e. the tables that it will operate on. This could be a single 6846 * table, all tables on a page or a sub-set thereof. 6847 * 6848 * Additionally the API is designed to allow you to easily work with the data in 6849 * the tables, retrieving and manipulating it as required. This is done by 6850 * presenting the API class as an array like interface. The contents of the 6851 * array depend upon the actions requested by each method (for example 6852 * `rows().nodes()` will return an array of nodes, while `rows().data()` will 6853 * return an array of objects or arrays depending upon your table's 6854 * configuration). The API object has a number of array like methods (`push`, 6855 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`, 6856 * `unique` etc) to assist your working with the data held in a table. 6857 * 6858 * Most methods (those which return an Api instance) are chainable, which means 6859 * the return from a method call also has all of the methods available that the 6860 * top level object had. For example, these two calls are equivalent: 6861 * 6862 * // Not chained 6863 * api.row.add( {...} ); 6864 * api.draw(); 6865 * 6866 * // Chained 6867 * api.row.add( {...} ).draw(); 6868 * 6869 * @class DataTable.Api 6870 * @param {array|object|string|jQuery} context DataTable identifier. This is 6871 * used to define which DataTables enhanced tables this API will operate on. 6872 * Can be one of: 6873 * 6874 * * `string` - jQuery selector. Any DataTables' matching the given selector 6875 * with be found and used. 6876 * * `node` - `TABLE` node which has already been formed into a DataTable. 6877 * * `jQuery` - A jQuery object of `TABLE` nodes. 6878 * * `object` - DataTables settings object 6879 * @param {array} [data] Data to initialise the Api instance with. 6880 * 6881 * @example 6882 * // Direct initialisation during DataTables construction 6883 * var api = $('#example').DataTable(); 6884 * 6885 * @example 6886 * // Initialisation using a DataTables jQuery object 6887 * var api = $('#example').dataTable().api(); 6888 * 6889 * @example 6890 * // Initialisation as a constructor 6891 * var api = new $.fn.DataTable.Api( 'table.dataTable' ); 6892 */ 6893 _Api = function ( context, data ) 6894 { 6895 if ( ! (this instanceof _Api) ) { 6896 return new _Api( context, data ); 6897 } 6898 6899 var settings = []; 6900 var ctxSettings = function ( o ) { 6901 var a = _toSettings( o ); 6902 if ( a ) { 6903 settings.push.apply( settings, a ); 6904 } 6905 }; 6906 6907 if ( $.isArray( context ) ) { 6908 for ( var i=0, ien=context.length ; i<ien ; i++ ) { 6909 ctxSettings( context[i] ); 6910 } 6911 } 6912 else { 6913 ctxSettings( context ); 6914 } 6915 6916 // Remove duplicates 6917 this.context = _unique( settings ); 6918 6919 // Initial data 6920 if ( data ) { 6921 $.merge( this, data ); 6922 } 6923 6924 // selector 6925 this.selector = { 6926 rows: null, 6927 cols: null, 6928 opts: null 6929 }; 6930 6931 _Api.extend( this, this, __apiStruct ); 6932 }; 6933 6934 DataTable.Api = _Api; 6935 6936 // Don't destroy the existing prototype, just extend it. Required for jQuery 2's 6937 // isPlainObject. 6938 $.extend( _Api.prototype, { 6939 any: function () 6940 { 6941 return this.count() !== 0; 6942 }, 6943 6944 6945 concat: __arrayProto.concat, 6946 6947 6948 context: [], // array of table settings objects 6949 6950 6951 count: function () 6952 { 6953 return this.flatten().length; 6954 }, 6955 6956 6957 each: function ( fn ) 6958 { 6959 for ( var i=0, ien=this.length ; i<ien; i++ ) { 6960 fn.call( this, this[i], i, this ); 6961 } 6962 6963 return this; 6964 }, 6965 6966 6967 eq: function ( idx ) 6968 { 6969 var ctx = this.context; 6970 6971 return ctx.length > idx ? 6972 new _Api( ctx[idx], this[idx] ) : 6973 null; 6974 }, 6975 6976 6977 filter: function ( fn ) 6978 { 6979 var a = []; 6980 6981 if ( __arrayProto.filter ) { 6982 a = __arrayProto.filter.call( this, fn, this ); 6983 } 6984 else { 6985 // Compatibility for browsers without EMCA-252-5 (JS 1.6) 6986 for ( var i=0, ien=this.length ; i<ien ; i++ ) { 6987 if ( fn.call( this, this[i], i, this ) ) { 6988 a.push( this[i] ); 6989 } 6990 } 6991 } 6992 6993 return new _Api( this.context, a ); 6994 }, 6995 6996 6997 flatten: function () 6998 { 6999 var a = []; 7000 return new _Api( this.context, a.concat.apply( a, this.toArray() ) ); 7001 }, 7002 7003 7004 join: __arrayProto.join, 7005 7006 7007 indexOf: __arrayProto.indexOf || function (obj, start) 7008 { 7009 for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) { 7010 if ( this[i] === obj ) { 7011 return i; 7012 } 7013 } 7014 return -1; 7015 }, 7016 7017 iterator: function ( flatten, type, fn, alwaysNew ) { 7018 var 7019 a = [], ret, 7020 i, ien, j, jen, 7021 context = this.context, 7022 rows, items, item, 7023 selector = this.selector; 7024 7025 // Argument shifting 7026 if ( typeof flatten === 'string' ) { 7027 alwaysNew = fn; 7028 fn = type; 7029 type = flatten; 7030 flatten = false; 7031 } 7032 7033 for ( i=0, ien=context.length ; i<ien ; i++ ) { 7034 var apiInst = new _Api( context[i] ); 7035 7036 if ( type === 'table' ) { 7037 ret = fn.call( apiInst, context[i], i ); 7038 7039 if ( ret !== undefined ) { 7040 a.push( ret ); 7041 } 7042 } 7043 else if ( type === 'columns' || type === 'rows' ) { 7044 // this has same length as context - one entry for each table 7045 ret = fn.call( apiInst, context[i], this[i], i ); 7046 7047 if ( ret !== undefined ) { 7048 a.push( ret ); 7049 } 7050 } 7051 else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) { 7052 // columns and rows share the same structure. 7053 // 'this' is an array of column indexes for each context 7054 items = this[i]; 7055 7056 if ( type === 'column-rows' ) { 7057 rows = _selector_row_indexes( context[i], selector.opts ); 7058 } 7059 7060 for ( j=0, jen=items.length ; j<jen ; j++ ) { 7061 item = items[j]; 7062 7063 if ( type === 'cell' ) { 7064 ret = fn.call( apiInst, context[i], item.row, item.column, i, j ); 7065 } 7066 else { 7067 ret = fn.call( apiInst, context[i], item, i, j, rows ); 7068 } 7069 7070 if ( ret !== undefined ) { 7071 a.push( ret ); 7072 } 7073 } 7074 } 7075 } 7076 7077 if ( a.length || alwaysNew ) { 7078 var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a ); 7079 var apiSelector = api.selector; 7080 apiSelector.rows = selector.rows; 7081 apiSelector.cols = selector.cols; 7082 apiSelector.opts = selector.opts; 7083 return api; 7084 } 7085 return this; 7086 }, 7087 7088 7089 lastIndexOf: __arrayProto.lastIndexOf || function (obj, start) 7090 { 7091 // Bit cheeky... 7092 return this.indexOf.apply( this.toArray.reverse(), arguments ); 7093 }, 7094 7095 7096 length: 0, 7097 7098 7099 map: function ( fn ) 7100 { 7101 var a = []; 7102 7103 if ( __arrayProto.map ) { 7104 a = __arrayProto.map.call( this, fn, this ); 7105 } 7106 else { 7107 // Compatibility for browsers without EMCA-252-5 (JS 1.6) 7108 for ( var i=0, ien=this.length ; i<ien ; i++ ) { 7109 a.push( fn.call( this, this[i], i ) ); 7110 } 7111 } 7112 7113 return new _Api( this.context, a ); 7114 }, 7115 7116 7117 pluck: function ( prop ) 7118 { 7119 return this.map( function ( el ) { 7120 return el[ prop ]; 7121 } ); 7122 }, 7123 7124 pop: __arrayProto.pop, 7125 7126 7127 push: __arrayProto.push, 7128 7129 7130 // Does not return an API instance 7131 reduce: __arrayProto.reduce || function ( fn, init ) 7132 { 7133 return _fnReduce( this, fn, init, 0, this.length, 1 ); 7134 }, 7135 7136 7137 reduceRight: __arrayProto.reduceRight || function ( fn, init ) 7138 { 7139 return _fnReduce( this, fn, init, this.length-1, -1, -1 ); 7140 }, 7141 7142 7143 reverse: __arrayProto.reverse, 7144 7145 7146 // Object with rows, columns and opts 7147 selector: null, 7148 7149 7150 shift: __arrayProto.shift, 7151 7152 7153 slice: function () { 7154 return new _Api( this.context, this ); 7155 }, 7156 7157 7158 sort: __arrayProto.sort, // ? name - order? 7159 7160 7161 splice: __arrayProto.splice, 7162 7163 7164 toArray: function () 7165 { 7166 return __arrayProto.slice.call( this ); 7167 }, 7168 7169 7170 to$: function () 7171 { 7172 return $( this ); 7173 }, 7174 7175 7176 toJQuery: function () 7177 { 7178 return $( this ); 7179 }, 7180 7181 7182 unique: function () 7183 { 7184 return new _Api( this.context, _unique(this) ); 7185 }, 7186 7187 7188 unshift: __arrayProto.unshift 7189 } ); 7190 7191 7192 _Api.extend = function ( scope, obj, ext ) 7193 { 7194 // Only extend API instances and static properties of the API 7195 if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) { 7196 return; 7197 } 7198 7199 var 7200 i, ien, 7201 struct, 7202 methodScoping = function ( scope, fn, struc ) { 7203 return function () { 7204 var ret = fn.apply( scope, arguments ); 7205 7206 // Method extension 7207 _Api.extend( ret, ret, struc.methodExt ); 7208 return ret; 7209 }; 7210 }; 7211 7212 for ( i=0, ien=ext.length ; i<ien ; i++ ) { 7213 struct = ext[i]; 7214 7215 // Value 7216 obj[ struct.name ] = struct.type === 'function' ? 7217 methodScoping( scope, struct.val, struct ) : 7218 struct.type === 'object' ? 7219 {} : 7220 struct.val; 7221 7222 obj[ struct.name ].__dt_wrapper = true; 7223 7224 // Property extension 7225 _Api.extend( scope, obj[ struct.name ], struct.propExt ); 7226 } 7227 }; 7228 7229 7230 // @todo - Is there need for an augment function? 7231 // _Api.augment = function ( inst, name ) 7232 // { 7233 // // Find src object in the structure from the name 7234 // var parts = name.split('.'); 7235 7236 // _Api.extend( inst, obj ); 7237 // }; 7238 7239 7240 // [ 7241 // { 7242 // name: 'data' -- string - Property name 7243 // val: function () {}, -- function - Api method (or undefined if just an object 7244 // methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result 7245 // propExt: [ ... ] -- array - Array of Api object definitions to extend the property 7246 // }, 7247 // { 7248 // name: 'row' 7249 // val: {}, 7250 // methodExt: [ ... ], 7251 // propExt: [ 7252 // { 7253 // name: 'data' 7254 // val: function () {}, 7255 // methodExt: [ ... ], 7256 // propExt: [ ... ] 7257 // }, 7258 // ... 7259 // ] 7260 // } 7261 // ] 7262 7263 _Api.register = _api_register = function ( name, val ) 7264 { 7265 if ( $.isArray( name ) ) { 7266 for ( var j=0, jen=name.length ; j<jen ; j++ ) { 7267 _Api.register( name[j], val ); 7268 } 7269 return; 7270 } 7271 7272 var 7273 i, ien, 7274 heir = name.split('.'), 7275 struct = __apiStruct, 7276 key, method; 7277 7278 var find = function ( src, name ) { 7279 for ( var i=0, ien=src.length ; i<ien ; i++ ) { 7280 if ( src[i].name === name ) { 7281 return src[i]; 7282 } 7283 } 7284 return null; 7285 }; 7286 7287 for ( i=0, ien=heir.length ; i<ien ; i++ ) { 7288 method = heir[i].indexOf('()') !== -1; 7289 key = method ? 7290 heir[i].replace('()', '') : 7291 heir[i]; 7292 7293 var src = find( struct, key ); 7294 if ( ! src ) { 7295 src = { 7296 name: key, 7297 val: {}, 7298 methodExt: [], 7299 propExt: [], 7300 type: 'object' 7301 }; 7302 struct.push( src ); 7303 } 7304 7305 if ( i === ien-1 ) { 7306 src.val = val; 7307 src.type = typeof val === 'function' ? 7308 'function' : 7309 $.isPlainObject( val ) ? 7310 'object' : 7311 'other'; 7312 } 7313 else { 7314 struct = method ? 7315 src.methodExt : 7316 src.propExt; 7317 } 7318 } 7319 }; 7320 7321 _Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) { 7322 _Api.register( pluralName, val ); 7323 7324 _Api.register( singularName, function () { 7325 var ret = val.apply( this, arguments ); 7326 7327 if ( ret === this ) { 7328 // Returned item is the API instance that was passed in, return it 7329 return this; 7330 } 7331 else if ( ret instanceof _Api ) { 7332 // New API instance returned, want the value from the first item 7333 // in the returned array for the singular result. 7334 return ret.length ? 7335 $.isArray( ret[0] ) ? 7336 new _Api( ret.context, ret[0] ) : // Array results are 'enhanced' 7337 ret[0] : 7338 undefined; 7339 } 7340 7341 // Non-API return - just fire it back 7342 return ret; 7343 } ); 7344 }; 7345 7346 7347 /** 7348 * Selector for HTML tables. Apply the given selector to the give array of 7349 * DataTables settings objects. 7350 * 7351 * @param {string|integer} [selector] jQuery selector string or integer 7352 * @param {array} Array of DataTables settings objects to be filtered 7353 * @return {array} 7354 * @ignore 7355 */ 7356 var __table_selector = function ( selector, a ) 7357 { 7358 if ( $
vendor: 10,923 bytes, lines 7358-7747
7358.isArray(selector) ) { 7359 return $.map( selector, function (item) { 7360 return __table_selector(item, a); 7361 } ); 7362 } 7363 7364 // Integer is used to pick out a table by index 7365 if ( typeof selector === 'number' ) { 7366 return [ a[ selector ] ]; 7367 } 7368 7369 // Perform a jQuery selector on the table nodes 7370 var nodes = $.map( a, function (el, i) { 7371 return el.nTable; 7372 } ); 7373 7374 return $(nodes) 7375 .filter( selector ) 7376 .map( function (i) { 7377 // Need to translate back from the table node to the settings 7378 var idx = $.inArray( this, nodes ); 7379 return a[ idx ]; 7380 } ) 7381 .toArray(); 7382 }; 7383 7384 7385 7386 /** 7387 * Context selector for the API's context (i.e. the tables the API instance 7388 * refers to. 7389 * 7390 * @name DataTable.Api#tables 7391 * @param {string|integer} [selector] Selector to pick which tables the iterator 7392 * should operate on. If not given, all tables in the current context are 7393 * used. This can be given as a jQuery selector (for example `':gt(0)'`) to 7394 * select multiple tables or as an integer to select a single table. 7395 * @returns {DataTable.Api} Returns a new API instance if a selector is given. 7396 */ 7397 _api_register( 'tables()', function ( selector ) { 7398 // A new instance is created if there was a selector specified 7399 return selector !== undefined && selector !== null ? 7400 new _Api( __table_selector( selector, this.context ) ) : 7401 this; 7402 } ); 7403 7404 7405 _api_register( 'table()', function ( selector ) { 7406 var tables = this.tables( selector ); 7407 var ctx = tables.context; 7408 7409 // Truncate to the first matched table 7410 return ctx.length ? 7411 new _Api( ctx[0] ) : 7412 tables; 7413 } ); 7414 7415 7416 _api_registerPlural( 'tables().nodes()', 'table().node()' , function () { 7417 return this.iterator( 'table', function ( ctx ) { 7418 return ctx.nTable; 7419 }, 1 ); 7420 } ); 7421 7422 7423 _api_registerPlural( 'tables().body()', 'table().body()' , function () { 7424 return this.iterator( 'table', function ( ctx ) { 7425 return ctx.nTBody; 7426 }, 1 ); 7427 } ); 7428 7429 7430 _api_registerPlural( 'tables().header()', 'table().header()' , function () { 7431 return this.iterator( 'table', function ( ctx ) { 7432 return ctx.nTHead; 7433 }, 1 ); 7434 } ); 7435 7436 7437 _api_registerPlural( 'tables().footer()', 'table().footer()' , function () { 7438 return this.iterator( 'table', function ( ctx ) { 7439 return ctx.nTFoot; 7440 }, 1 ); 7441 } ); 7442 7443 7444 _api_registerPlural( 'tables().containers()', 'table().container()' , function () { 7445 return this.iterator( 'table', function ( ctx ) { 7446 return ctx.nTableWrapper; 7447 }, 1 ); 7448 } ); 7449 7450 7451 7452 /** 7453 * Redraw the tables in the current context. 7454 */ 7455 _api_register( 'draw()', function ( paging ) { 7456 return this.iterator( 'table', function ( settings ) { 7457 if ( paging === 'page' ) { 7458 _fnDraw( settings ); 7459 } 7460 else { 7461 if ( typeof paging === 'string' ) { 7462 paging = paging === 'full-hold' ? 7463 false : 7464 true; 7465 } 7466 7467 _fnReDraw( settings, paging===false ); 7468 } 7469 } ); 7470 } ); 7471 7472 7473 7474 /** 7475 * Get the current page index. 7476 * 7477 * @return {integer} Current page index (zero based) 7478 *//** 7479 * Set the current page. 7480 * 7481 * Note that if you attempt to show a page which does not exist, DataTables will 7482 * not throw an error, but rather reset the paging. 7483 * 7484 * @param {integer|string} action The paging action to take. This can be one of: 7485 * * `integer` - The page index to jump to 7486 * * `string` - An action to take: 7487 * * `first` - Jump to first page. 7488 * * `next` - Jump to the next page 7489 * * `previous` - Jump to previous page 7490 * * `last` - Jump to the last page. 7491 * @returns {DataTables.Api} this 7492 */ 7493 _api_register( 'page()', function ( action ) { 7494 if ( action === undefined ) { 7495 return this.page.info().page; // not an expensive call 7496 } 7497 7498 // else, have an action to take on all tables 7499 return this.iterator( 'table', function ( settings ) { 7500 _fnPageChange( settings, action ); 7501 } ); 7502 } ); 7503 7504 7505 /** 7506 * Paging information for the first table in the current context. 7507 * 7508 * If you require paging information for another table, use the `table()` method 7509 * with a suitable selector. 7510 * 7511 * @return {object} Object with the following properties set: 7512 * * `page` - Current page index (zero based - i.e. the first page is `0`) 7513 * * `pages` - Total number of pages 7514 * * `start` - Display index for the first record shown on the current page 7515 * * `end` - Display index for the last record shown on the current page 7516 * * `length` - Display length (number of records). Note that generally `start 7517 * + length = end`, but this is not always true, for example if there are 7518 * only 2 records to show on the final page, with a length of 10. 7519 * * `recordsTotal` - Full data set length 7520 * * `recordsDisplay` - Data set length once the current filtering criterion 7521 * are applied. 7522 */ 7523 _api_register( 'page.info()', function ( action ) { 7524 if ( this.context.length === 0 ) { 7525 return undefined; 7526 } 7527 7528 var 7529 settings = this.context[0], 7530 start = settings._iDisplayStart, 7531 len = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1, 7532 visRecords = settings.fnRecordsDisplay(), 7533 all = len === -1; 7534 7535 return { 7536 "page": all ? 0 : Math.floor( start / len ), 7537 "pages": all ? 1 : Math.ceil( visRecords / len ), 7538 "start": start, 7539 "end": settings.fnDisplayEnd(), 7540 "length": len, 7541 "recordsTotal": settings.fnRecordsTotal(), 7542 "recordsDisplay": visRecords, 7543 "serverSide": _fnDataSource( settings ) === 'ssp' 7544 }; 7545 } ); 7546 7547 7548 /** 7549 * Get the current page length. 7550 * 7551 * @return {integer} Current page length. Note `-1` indicates that all records 7552 * are to be shown. 7553 *//** 7554 * Set the current page length. 7555 * 7556 * @param {integer} Page length to set. Use `-1` to show all records. 7557 * @returns {DataTables.Api} this 7558 */ 7559 _api_register( 'page.len()', function ( len ) { 7560 // Note that we can't call this function 'length()' because `length` 7561 // is a Javascript property of functions which defines how many arguments 7562 // the function expects. 7563 if ( len === undefined ) { 7564 return this.context.length !== 0 ? 7565 this.context[0]._iDisplayLength : 7566 undefined; 7567 } 7568 7569 // else, set the page length 7570 return this.iterator( 'table', function ( settings ) { 7571 _fnLengthChange( settings, len ); 7572 } ); 7573 } ); 7574 7575 7576 7577 var __reload = function ( settings, holdPosition, callback ) { 7578 // Use the draw event to trigger a callback 7579 if ( callback ) { 7580 var api = new _Api( settings ); 7581 7582 api.one( 'draw', function () { 7583 callback( api.ajax.json() ); 7584 } ); 7585 } 7586 7587 if ( _fnDataSource( settings ) == 'ssp' ) { 7588 _fnReDraw( settings, holdPosition ); 7589 } 7590 else { 7591 _fnProcessingDisplay( settings, true ); 7592 7593 // Cancel an existing request 7594 var xhr = settings.jqXHR; 7595 if ( xhr && xhr.readyState !== 4 ) { 7596 xhr.abort(); 7597 } 7598 7599 // Trigger xhr 7600 _fnBuildAjax( settings, [], function( json ) { 7601 _fnClearTable( settings ); 7602 7603 var data = _fnAjaxDataSrc( settings, json ); 7604 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 7605 _fnAddData( settings, data[i] ); 7606 } 7607 7608 _fnReDraw( settings, holdPosition ); 7609 _fnProcessingDisplay( settings, false ); 7610 } ); 7611 } 7612 }; 7613 7614 7615 /** 7616 * Get the JSON response from the last Ajax request that DataTables made to the 7617 * server. Note that this returns the JSON from the first table in the current 7618 * context. 7619 * 7620 * @return {object} JSON received from the server. 7621 */ 7622 _api_register( 'ajax.json()', function () { 7623 var ctx = this.context; 7624 7625 if ( ctx.length > 0 ) { 7626 return ctx[0].json; 7627 } 7628 7629 // else return undefined; 7630 } ); 7631 7632 7633 /** 7634 * Get the data submitted in the last Ajax request 7635 */ 7636 _api_register( 'ajax.params()', function () { 7637 var ctx = this.context; 7638 7639 if ( ctx.length > 0 ) { 7640 return ctx[0].oAjaxData; 7641 } 7642 7643 // else return undefined; 7644 } ); 7645 7646 7647 /** 7648 * Reload tables from the Ajax data source. Note that this function will 7649 * automatically re-draw the table when the remote data has been loaded. 7650 * 7651 * @param {boolean} [reset=true] Reset (default) or hold the current paging 7652 * position. A full re-sort and re-filter is performed when this method is 7653 * called, which is why the pagination reset is the default action. 7654 * @returns {DataTables.Api} this 7655 */ 7656 _api_register( 'ajax.reload()', function ( callback, resetPaging ) { 7657 return this.iterator( 'table', function (settings) { 7658 __reload( settings, resetPaging===false, callback ); 7659 } ); 7660 } ); 7661 7662 7663 /** 7664 * Get the current Ajax URL. Note that this returns the URL from the first 7665 * table in the current context. 7666 * 7667 * @return {string} Current Ajax source URL 7668 *//** 7669 * Set the Ajax URL. Note that this will set the URL for all tables in the 7670 * current context. 7671 * 7672 * @param {string} url URL to set. 7673 * @returns {DataTables.Api} this 7674 */ 7675 _api_register( 'ajax.url()', function ( url ) { 7676 var ctx = this.context; 7677 7678 if ( url === undefined ) { 7679 // get 7680 if ( ctx.length === 0 ) { 7681 return undefined; 7682 } 7683 ctx = ctx[0]; 7684 7685 return ctx.ajax ? 7686 $.isPlainObject( ctx.ajax ) ? 7687 ctx.ajax.url : 7688 ctx.ajax : 7689 ctx.sAjaxSource; 7690 } 7691 7692 // set 7693 return this.iterator( 'table', function ( settings ) { 7694 if ( $.isPlainObject( settings.ajax ) ) { 7695 settings.ajax.url = url; 7696 } 7697 else { 7698 settings.ajax = url; 7699 } 7700 // No need to consider sAjaxSource here since DataTables gives priority 7701 // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any 7702 // value of `sAjaxSource` redundant. 7703 } ); 7704 } ); 7705 7706 7707 /** 7708 * Load data from the newly set Ajax URL. Note that this method is only 7709 * available when `ajax.url()` is used to set a URL. Additionally, this method 7710 * has the same effect as calling `ajax.reload()` but is provided for 7711 * convenience when setting a new URL. Like `ajax.reload()` it will 7712 * automatically redraw the table once the remote data has been loaded. 7713 * 7714 * @returns {DataTables.Api} this 7715 */ 7716 _api_register( 'ajax.url().load()', function ( callback, resetPaging ) { 7717 // Same as a reload, but makes sense to present it for easy access after a 7718 // url change 7719 return this.iterator( 'table', function ( ctx ) { 7720 __reload( ctx, resetPaging===false, callback ); 7721 } ); 7722 } ); 7723 7724 7725 7726 7727 var _selector_run = function ( type, selector, selectFn, settings, opts ) 7728 { 7729 var 7730 out = [], res, 7731 a, i, ien, j, jen, 7732 selectorType = typeof selector; 7733 7734 // Can't just check for isArray here, as an API or jQuery instance might be 7735 // given with their array like look 7736 if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) { 7737 selector = [ selector ]; 7738 } 7739 7740 for ( i=0, ien=selector.length ; i<ien ; i++ ) { 7741 // Only split on simple strings - complex expressions will be jQuery selectors 7742 a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ? 7743 selector[i].split(',') : 7744 [ selector[i] ]; 7745 7746 for ( j=0, jen=a.length ; j<jen ; j++ ) { 7747 res = selectFn( typeof a[j] === 'string' ?
vendor: 2,006 bytes, lines 7747-7831
7747$.trim(a[j]) : a[j] ); 7748 7749 if ( res && res.length ) { 7750 out = out.concat( res ); 7751 } 7752 } 7753 } 7754 7755 // selector extensions 7756 var ext = _ext.selector[ type ]; 7757 if ( ext.length ) { 7758 for ( i=0, ien=ext.length ; i<ien ; i++ ) { 7759 out = ext[i]( settings, opts, out ); 7760 } 7761 } 7762 7763 return _unique( out ); 7764 }; 7765 7766 7767 var _selector_opts = function ( opts ) 7768 { 7769 if ( ! opts ) { 7770 opts = {}; 7771 } 7772 7773 // Backwards compatibility for 1.9- which used the terminology filter rather 7774 // than search 7775 if ( opts.filter && opts.search === undefined ) { 7776 opts.search = opts.filter; 7777 } 7778 7779 return $.extend( { 7780 search: 'none', 7781 order: 'current', 7782 page: 'all' 7783 }, opts ); 7784 }; 7785 7786 7787 var _selector_first = function ( inst ) 7788 { 7789 // Reduce the API instance to the first item found 7790 for ( var i=0, ien=inst.length ; i<ien ; i++ ) { 7791 if ( inst[i].length > 0 ) { 7792 // Assign the first element to the first item in the instance 7793 // and truncate the instance and context 7794 inst[0] = inst[i]; 7795 inst[0].length = 1; 7796 inst.length = 1; 7797 inst.context = [ inst.context[i] ]; 7798 7799 return inst; 7800 } 7801 } 7802 7803 // Not found - return an empty instance 7804 inst.length = 0; 7805 return inst; 7806 }; 7807 7808 7809 var _selector_row_indexes = function ( settings, opts ) 7810 { 7811 var 7812 i, ien, tmp, a=[], 7813 displayFiltered = settings.aiDisplay, 7814 displayMaster = settings.aiDisplayMaster; 7815 7816 var 7817 search = opts.search, // none, applied, removed 7818 order = opts.order, // applied, current, index (original - compatibility with 1.9) 7819 page = opts.page; // all, current 7820 7821 if ( _fnDataSource( settings ) == 'ssp' ) { 7822 // In server-side processing mode, most options are irrelevant since 7823 // rows not shown don't exist and the index order is the applied order 7824 // Removed is a special case - for consistency just return an empty 7825 // array 7826 return search === 'removed' ? 7827 [] : 7828 _range( 0, displayMaster.length ); 7829 } 7830 else if ( page == 'current' ) { 7831 // Current page implies that order=current and fitl
vendor: 9,343 bytes, lines 7831-8173
7831er=applied, since it is 7832 // fairly senseless otherwise, regardless of what order and search actually 7833 // are 7834 for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) { 7835 a.push( displayFiltered[i] ); 7836 } 7837 } 7838 else if ( order == 'current' || order == 'applied' ) { 7839 if ( search == 'none') { 7840 a = displayMaster.slice(); 7841 } 7842 else if ( search == 'applied' ) { 7843 a = displayFiltered.slice(); 7844 } 7845 else if ( search == 'removed' ) { 7846 // O(n+m) solution by creating a hash map 7847 var displayFilteredMap = {}; 7848 7849 for ( var i=0, ien=displayFiltered.length ; i<ien ; i++ ) { 7850 displayFilteredMap[displayFiltered[i]] = null; 7851 } 7852 7853 a = $.map( displayMaster, function (el) { 7854 return ! displayFilteredMap.hasOwnProperty(el) ? 7855 el : 7856 null; 7857 } ); 7858 } 7859 } 7860 else if ( order == 'index' || order == 'original' ) { 7861 for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 7862 if ( search == 'none' ) { 7863 a.push( i ); 7864 } 7865 else { // applied | removed 7866 tmp = $.inArray( i, displayFiltered ); 7867 7868 if ((tmp === -1 && search == 'removed') || 7869 (tmp >= 0 && search == 'applied') ) 7870 { 7871 a.push( i ); 7872 } 7873 } 7874 } 7875 } 7876 7877 return a; 7878 }; 7879 7880 7881 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 7882 * Rows 7883 * 7884 * {} - no selector - use all available rows 7885 * {integer} - row aoData index 7886 * {node} - TR node 7887 * {string} - jQuery selector to apply to the TR elements 7888 * {array} - jQuery array of nodes, or simply an array of TR nodes 7889 * 7890 */ 7891 var __row_selector = function ( settings, selector, opts ) 7892 { 7893 var rows; 7894 var run = function ( sel ) { 7895 var selInt = _intVal( sel ); 7896 var i, ien; 7897 var aoData = settings.aoData; 7898 7899 // Short cut - selector is a number and no options provided (default is 7900 // all records, so no need to check if the index is in there, since it 7901 // must be - dev error if the index doesn't exist). 7902 if ( selInt !== null && ! opts ) { 7903 return [ selInt ]; 7904 } 7905 7906 if ( ! rows ) { 7907 rows = _selector_row_indexes( settings, opts ); 7908 } 7909 7910 if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) { 7911 // Selector - integer 7912 return [ selInt ]; 7913 } 7914 else if ( sel === null || sel === undefined || sel === '' ) { 7915 // Selector - none 7916 return rows; 7917 } 7918 7919 // Selector - function 7920 if ( typeof sel === 'function' ) { 7921 return $.map( rows, function (idx) { 7922 var row = aoData[ idx ]; 7923 return sel( idx, row._aData, row.nTr ) ? idx : null; 7924 } ); 7925 } 7926 7927 // Selector - node 7928 if ( sel.nodeName ) { 7929 var rowIdx = sel._DT_RowIndex; // Property added by DT for fast lookup 7930 var cellIdx = sel._DT_CellIndex; 7931 7932 if ( rowIdx !== undefined ) { 7933 // Make sure that the row is actually still present in the table 7934 return aoData[ rowIdx ] && aoData[ rowIdx ].nTr === sel ? 7935 [ rowIdx ] : 7936 []; 7937 } 7938 else if ( cellIdx ) { 7939 return aoData[ cellIdx.row ] && aoData[ cellIdx.row ].nTr === sel.parentNode ? 7940 [ cellIdx.row ] : 7941 []; 7942 } 7943 else { 7944 var host = $(sel).closest('*[data-dt-row]'); 7945 return host.length ? 7946 [ host.data('dt-row') ] : 7947 []; 7948 } 7949 } 7950 7951 // ID selector. Want to always be able to select rows by id, regardless 7952 // of if the tr element has been created or not, so can't rely upon 7953 // jQuery here - hence a custom implementation. This does not match 7954 // Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything, 7955 // but to select it using a CSS selector engine (like Sizzle or 7956 // querySelect) it would need to need to be escaped for some characters. 7957 // DataTables simplifies this for row selectors since you can select 7958 // only a row. A # indicates an id any anything that follows is the id - 7959 // unescaped. 7960 if ( typeof sel === 'string' && sel.charAt(0) === '#' ) { 7961 // get row index from id 7962 var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ]; 7963 if ( rowObj !== undefined ) { 7964 return [ rowObj.idx ]; 7965 } 7966 7967 // need to fall through to jQuery in case there is DOM id that 7968 // matches 7969 } 7970 7971 // Get nodes in the order from the `rows` array with null values removed 7972 var nodes = _removeEmpty( 7973 _pluck_order( settings.aoData, rows, 'nTr' ) 7974 ); 7975 7976 // Selector - jQuery selector string, array of nodes or jQuery object/ 7977 // As jQuery's .filter() allows jQuery objects to be passed in filter, 7978 // it also allows arrays, so this will cope with all three options 7979 return $(nodes) 7980 .filter( sel ) 7981 .map( function () { 7982 return this._DT_RowIndex; 7983 } ) 7984 .toArray(); 7985 }; 7986 7987 return _selector_run( 'row', selector, run, settings, opts ); 7988 }; 7989 7990 7991 _api_register( 'rows()', function ( selector, opts ) { 7992 // argument shifting 7993 if ( selector === undefined ) { 7994 selector = ''; 7995 } 7996 else if ( $.isPlainObject( selector ) ) { 7997 opts = selector; 7998 selector = ''; 7999 } 8000 8001 opts = _selector_opts( opts ); 8002 8003 var inst = this.iterator( 'table', function ( settings ) { 8004 return __row_selector( settings, selector, opts ); 8005 }, 1 ); 8006 8007 // Want argument shifting here and in __row_selector? 8008 inst.selector.rows = selector; 8009 inst.selector.opts = opts; 8010 8011 return inst; 8012 } ); 8013 8014 _api_register( 'rows().nodes()', function () { 8015 return this.iterator( 'row', function ( settings, row ) { 8016 return settings.aoData[ row ].nTr || undefined; 8017 }, 1 ); 8018 } ); 8019 8020 _api_register( 'rows().data()', function () { 8021 return this.iterator( true, 'rows', function ( settings, rows ) { 8022 return _pluck_order( settings.aoData, rows, '_aData' ); 8023 }, 1 ); 8024 } ); 8025 8026 _api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) { 8027 return this.iterator( 'row', function ( settings, row ) { 8028 var r = settings.aoData[ row ]; 8029 return type === 'search' ? r._aFilterData : r._aSortData; 8030 }, 1 ); 8031 } ); 8032 8033 _api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) { 8034 return this.iterator( 'row', function ( settings, row ) { 8035 _fnInvalidate( settings, row, src ); 8036 } ); 8037 } ); 8038 8039 _api_registerPlural( 'rows().indexes()', 'row().index()', function () { 8040 return this.iterator( 'row', function ( settings, row ) { 8041 return row; 8042 }, 1 ); 8043 } ); 8044 8045 _api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) { 8046 var a = []; 8047 var context = this.context; 8048 8049 // `iterator` will drop undefined values, but in this case we want them 8050 for ( var i=0, ien=context.length ; i<ien ; i++ ) { 8051 for ( var j=0, jen=this[i].length ; j<jen ; j++ ) { 8052 var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData ); 8053 a.push( (hash === true ? '#' : '' )+ id ); 8054 } 8055 } 8056 8057 return new _Api( context, a ); 8058 } ); 8059 8060 _api_registerPlural( 'rows().remove()', 'row().remove()', function () { 8061 var that = this; 8062 8063 this.iterator( 'row', function ( settings, row, thatIdx ) { 8064 var data = settings.aoData; 8065 var rowData = data[ row ]; 8066 var i, ien, j, jen; 8067 var loopRow, loopCells; 8068 8069 data.splice( row, 1 ); 8070 8071 // Update the cached indexes 8072 for ( i=0, ien=data.length ; i<ien ; i++ ) { 8073 loopRow = data[i]; 8074 loopCells = loopRow.anCells; 8075 8076 // Rows 8077 if ( loopRow.nTr !== null ) { 8078 loopRow.nTr._DT_RowIndex = i; 8079 } 8080 8081 // Cells 8082 if ( loopCells !== null ) { 8083 for ( j=0, jen=loopCells.length ; j<jen ; j++ ) { 8084 loopCells[j]._DT_CellIndex.row = i; 8085 } 8086 } 8087 } 8088 8089 // Delete from the display arrays 8090 _fnDeleteIndex( settings.aiDisplayMaster, row ); 8091 _fnDeleteIndex( settings.aiDisplay, row ); 8092 _fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes 8093 8094 // For server-side processing tables - subtract the deleted row from the count 8095 if ( settings._iRecordsDisplay > 0 ) { 8096 settings._iRecordsDisplay--; 8097 } 8098 8099 // Check for an 'overflow' they case for displaying the table 8100 _fnLengthOverflow( settings ); 8101 8102 // Remove the row's ID reference if there is one 8103 var id = settings.rowIdFn( rowData._aData ); 8104 if ( id !== undefined ) { 8105 delete settings.aIds[ id ]; 8106 } 8107 } ); 8108 8109 this.iterator( 'table', function ( settings ) { 8110 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 8111 settings.aoData[i].idx = i; 8112 } 8113 } ); 8114 8115 return this; 8116 } ); 8117 8118 8119 _api_register( 'rows.add()', function ( rows ) { 8120 var newRows = this.iterator( 'table', function ( settings ) { 8121 var row, i, ien; 8122 var out = []; 8123 8124 for ( i=0, ien=rows.length ; i<ien ; i++ ) { 8125 row = rows[i]; 8126 8127 if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) { 8128 out.push( _fnAddTr( settings, row )[0] ); 8129 } 8130 else { 8131 out.push( _fnAddData( settings, row ) ); 8132 } 8133 } 8134 8135 return out; 8136 }, 1 ); 8137 8138 // Return an Api.rows() extended instance, so rows().nodes() etc can be used 8139 var modRows = this.rows( -1 ); 8140 modRows.pop(); 8141 $.merge( modRows, newRows ); 8142 8143 return modRows; 8144 } ); 8145 8146 8147 8148 8149 8150 /** 8151 * 8152 */ 8153 _api_register( 'row()', function ( selector, opts ) { 8154 return _selector_first( this.rows( selector, opts ) ); 8155 } ); 8156 8157 8158 _api_register( 'row().data()', function ( data ) { 8159 var ctx = this.context; 8160 8161 if ( data === undefined ) { 8162 // Get 8163 return ctx.length && this.length ? 8164 ctx[0].aoData[ this[0] ]._aData : 8165 undefined; 8166 } 8167 8168 // Set 8169 var row = ctx[0].aoData[ this[0] ]; 8170 row._aData = data; 8171 8172 // If the DOM has an id, and the data source is an array 8173 if (
vendor: 14,764 bytes, lines 8173-8736
8173$.isArray( data ) && row.nTr && row.nTr.id ) { 8174 _fnSetObjectDataFn( ctx[0].rowId )( data, row.nTr.id ); 8175 } 8176 8177 // Automatically invalidate 8178 _fnInvalidate( ctx[0], this[0], 'data' ); 8179 8180 return this; 8181 } ); 8182 8183 8184 _api_register( 'row().node()', function () { 8185 var ctx = this.context; 8186 8187 return ctx.length && this.length ? 8188 ctx[0].aoData[ this[0] ].nTr || null : 8189 null; 8190 } ); 8191 8192 8193 _api_register( 'row.add()', function ( row ) { 8194 // Allow a jQuery object to be passed in - only a single row is added from 8195 // it though - the first element in the set 8196 if ( row instanceof $ && row.length ) { 8197 row = row[0]; 8198 } 8199 8200 var rows = this.iterator( 'table', function ( settings ) { 8201 if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) { 8202 return _fnAddTr( settings, row )[0]; 8203 } 8204 return _fnAddData( settings, row ); 8205 } ); 8206 8207 // Return an Api.rows() extended instance, with the newly added row selected 8208 return this.row( rows[0] ); 8209 } ); 8210 8211 8212 8213 var __details_add = function ( ctx, row, data, klass ) 8214 { 8215 // Convert to array of TR elements 8216 var rows = []; 8217 var addRow = function ( r, k ) { 8218 // Recursion to allow for arrays of jQuery objects 8219 if ( $.isArray( r ) || r instanceof $ ) { 8220 for ( var i=0, ien=r.length ; i<ien ; i++ ) { 8221 addRow( r[i], k ); 8222 } 8223 return; 8224 } 8225 8226 // If we get a TR element, then just add it directly - up to the dev 8227 // to add the correct number of columns etc 8228 if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) { 8229 rows.push( r ); 8230 } 8231 else { 8232 // Otherwise create a row with a wrapper 8233 var created = $('<tr><td/></tr>').addClass( k ); 8234 $('td', created) 8235 .addClass( k ) 8236 .html( r ) 8237 [0].colSpan = _fnVisbleColumns( ctx ); 8238 8239 rows.push( created[0] ); 8240 } 8241 }; 8242 8243 addRow( data, klass ); 8244 8245 if ( row._details ) { 8246 row._details.detach(); 8247 } 8248 8249 row._details = $(rows); 8250 8251 // If the children were already shown, that state should be retained 8252 if ( row._detailsShow ) { 8253 row._details.insertAfter( row.nTr ); 8254 } 8255 }; 8256 8257 8258 var __details_remove = function ( api, idx ) 8259 { 8260 var ctx = api.context; 8261 8262 if ( ctx.length ) { 8263 var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ]; 8264 8265 if ( row && row._details ) { 8266 row._details.remove(); 8267 8268 row._detailsShow = undefined; 8269 row._details = undefined; 8270 } 8271 } 8272 }; 8273 8274 8275 var __details_display = function ( api, show ) { 8276 var ctx = api.context; 8277 8278 if ( ctx.length && api.length ) { 8279 var row = ctx[0].aoData[ api[0] ]; 8280 8281 if ( row._details ) { 8282 row._detailsShow = show; 8283 8284 if ( show ) { 8285 row._details.insertAfter( row.nTr ); 8286 } 8287 else { 8288 row._details.detach(); 8289 } 8290 8291 __details_events( ctx[0] ); 8292 } 8293 } 8294 }; 8295 8296 8297 var __details_events = function ( settings ) 8298 { 8299 var api = new _Api( settings ); 8300 var namespace = '.dt.DT_details'; 8301 var drawEvent = 'draw'+namespace; 8302 var colvisEvent = 'column-visibility'+namespace; 8303 var destroyEvent = 'destroy'+namespace; 8304 var data = settings.aoData; 8305 8306 api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent ); 8307 8308 if ( _pluck( data, '_details' ).length > 0 ) { 8309 // On each draw, insert the required elements into the document 8310 api.on( drawEvent, function ( e, ctx ) { 8311 if ( settings !== ctx ) { 8312 return; 8313 } 8314 8315 api.rows( {page:'current'} ).eq(0).each( function (idx) { 8316 // Internal data grab 8317 var row = data[ idx ]; 8318 8319 if ( row._detailsShow ) { 8320 row._details.insertAfter( row.nTr ); 8321 } 8322 } ); 8323 } ); 8324 8325 // Column visibility change - update the colspan 8326 api.on( colvisEvent, function ( e, ctx, idx, vis ) { 8327 if ( settings !== ctx ) { 8328 return; 8329 } 8330 8331 // Update the colspan for the details rows (note, only if it already has 8332 // a colspan) 8333 var row, visible = _fnVisbleColumns( ctx ); 8334 8335 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 8336 row = data[i]; 8337 8338 if ( row._details ) { 8339 row._details.children('td[colspan]').attr('colspan', visible ); 8340 } 8341 } 8342 } ); 8343 8344 // Table destroyed - nuke any child rows 8345 api.on( destroyEvent, function ( e, ctx ) { 8346 if ( settings !== ctx ) { 8347 return; 8348 } 8349 8350 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 8351 if ( data[i]._details ) { 8352 __details_remove( api, i ); 8353 } 8354 } 8355 } ); 8356 } 8357 }; 8358 8359 // Strings for the method names to help minification 8360 var _emp = ''; 8361 var _child_obj = _emp+'row().child'; 8362 var _child_mth = _child_obj+'()'; 8363 8364 // data can be: 8365 // tr 8366 // string 8367 // jQuery or array of any of the above 8368 _api_register( _child_mth, function ( data, klass ) { 8369 var ctx = this.context; 8370 8371 if ( data === undefined ) { 8372 // get 8373 return ctx.length && this.length ? 8374 ctx[0].aoData[ this[0] ]._details : 8375 undefined; 8376 } 8377 else if ( data === true ) { 8378 // show 8379 this.child.show(); 8380 } 8381 else if ( data === false ) { 8382 // remove 8383 __details_remove( this ); 8384 } 8385 else if ( ctx.length && this.length ) { 8386 // set 8387 __details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass ); 8388 } 8389 8390 return this; 8391 } ); 8392 8393 8394 _api_register( [ 8395 _child_obj+'.show()', 8396 _child_mth+'.show()' // only when `child()` was called with parameters (without 8397 ], function ( show ) { // it returns an object and this method is not executed) 8398 __details_display( this, true ); 8399 return this; 8400 } ); 8401 8402 8403 _api_register( [ 8404 _child_obj+'.hide()', 8405 _child_mth+'.hide()' // only when `child()` was called with parameters (without 8406 ], function () { // it returns an object and this method is not executed) 8407 __details_display( this, false ); 8408 return this; 8409 } ); 8410 8411 8412 _api_register( [ 8413 _child_obj+'.remove()', 8414 _child_mth+'.remove()' // only when `child()` was called with parameters (without 8415 ], function () { // it returns an object and this method is not executed) 8416 __details_remove( this ); 8417 return this; 8418 } ); 8419 8420 8421 _api_register( _child_obj+'.isShown()', function () { 8422 var ctx = this.context; 8423 8424 if ( ctx.length && this.length ) { 8425 // _detailsShown as false or undefined will fall through to return false 8426 return ctx[0].aoData[ this[0] ]._detailsShow || false; 8427 } 8428 return false; 8429 } ); 8430 8431 8432 8433 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 8434 * Columns 8435 * 8436 * {integer} - column index (>=0 count from left, <0 count from right) 8437 * "{integer}:visIdx" - visible column index (i.e. translate to column index) (>=0 count from left, <0 count from right) 8438 * "{integer}:visible" - alias for {integer}:visIdx (>=0 count from left, <0 count from right) 8439 * "{string}:name" - column name 8440 * "{string}" - jQuery selector on column header nodes 8441 * 8442 */ 8443 8444 // can be an array of these items, comma separated list, or an array of comma 8445 // separated lists 8446 8447 var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/; 8448 8449 8450 // r1 and r2 are redundant - but it means that the parameters match for the 8451 // iterator callback in columns().data() 8452 var __columnData = function ( settings, column, r1, r2, rows ) { 8453 var a = []; 8454 for ( var row=0, ien=rows.length ; row<ien ; row++ ) { 8455 a.push( _fnGetCellData( settings, rows[row], column ) ); 8456 } 8457 return a; 8458 }; 8459 8460 8461 var __column_selector = function ( settings, selector, opts ) 8462 { 8463 var 8464 columns = settings.aoColumns, 8465 names = _pluck( columns, 'sName' ), 8466 nodes = _pluck( columns, 'nTh' ); 8467 8468 var run = function ( s ) { 8469 var selInt = _intVal( s ); 8470 8471 // Selector - all 8472 if ( s === '' ) { 8473 return _range( columns.length ); 8474 } 8475 8476 // Selector - index 8477 if ( selInt !== null ) { 8478 return [ selInt >= 0 ? 8479 selInt : // Count from left 8480 columns.length + selInt // Count from right (+ because its a negative value) 8481 ]; 8482 } 8483 8484 // Selector = function 8485 if ( typeof s === 'function' ) { 8486 var rows = _selector_row_indexes( settings, opts ); 8487 8488 return $.map( columns, function (col, idx) { 8489 return s( 8490 idx, 8491 __columnData( settings, idx, 0, 0, rows ), 8492 nodes[ idx ] 8493 ) ? idx : null; 8494 } ); 8495 } 8496 8497 // jQuery or string selector 8498 var match = typeof s === 'string' ? 8499 s.match( __re_column_selector ) : 8500 ''; 8501 8502 if ( match ) { 8503 switch( match[2] ) { 8504 case 'visIdx': 8505 case 'visible': 8506 var idx = parseInt( match[1], 10 ); 8507 // Visible index given, convert to column index 8508 if ( idx < 0 ) { 8509 // Counting from the right 8510 var visColumns = $.map( columns, function (col,i) { 8511 return col.bVisible ? i : null; 8512 } ); 8513 return [ visColumns[ visColumns.length + idx ] ]; 8514 } 8515 // Counting from the left 8516 return [ _fnVisibleToColumnIndex( settings, idx ) ]; 8517 8518 case 'name': 8519 // match by name. `names` is column index complete and in order 8520 return $.map( names, function (name, i) { 8521 return name === match[1] ? i : null; 8522 } ); 8523 8524 default: 8525 return []; 8526 } 8527 } 8528 8529 // Cell in the table body 8530 if ( s.nodeName && s._DT_CellIndex ) { 8531 return [ s._DT_CellIndex.column ]; 8532 } 8533 8534 // jQuery selector on the TH elements for the columns 8535 var jqResult = $( nodes ) 8536 .filter( s ) 8537 .map( function () { 8538 return $.inArray( this, nodes ); // `nodes` is column index complete and in order 8539 } ) 8540 .toArray(); 8541 8542 if ( jqResult.length || ! s.nodeName ) { 8543 return jqResult; 8544 } 8545 8546 // Otherwise a node which might have a `dt-column` data attribute, or be 8547 // a child or such an element 8548 var host = $(s).closest('*[data-dt-column]'); 8549 return host.length ? 8550 [ host.data('dt-column') ] : 8551 []; 8552 }; 8553 8554 return _selector_run( 'column', selector, run, settings, opts ); 8555 }; 8556 8557 8558 var __setColumnVis = function ( settings, column, vis ) { 8559 var 8560 cols = settings.aoColumns, 8561 col = cols[ column ], 8562 data = settings.aoData, 8563 row, cells, i, ien, tr; 8564 8565 // Get 8566 if ( vis === undefined ) { 8567 return col.bVisible; 8568 } 8569 8570 // Set 8571 // No change 8572 if ( col.bVisible === vis ) { 8573 return; 8574 } 8575 8576 if ( vis ) { 8577 // Insert column 8578 // Need to decide if we should use appendChild or insertBefore 8579 var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 ); 8580 8581 for ( i=0, ien=data.length ; i<ien ; i++ ) { 8582 tr = data[i].nTr; 8583 cells = data[i].anCells; 8584 8585 if ( tr ) { 8586 // insertBefore can act like appendChild if 2nd arg is null 8587 tr.insertBefore( cells[ column ], cells[ insertBefore ] || null ); 8588 } 8589 } 8590 } 8591 else { 8592 // Remove column 8593 $( _pluck( settings.aoData, 'anCells', column ) ).detach(); 8594 } 8595 8596 // Common actions 8597 col.bVisible = vis; 8598 }; 8599 8600 8601 _api_register( 'columns()', function ( selector, opts ) { 8602 // argument shifting 8603 if ( selector === undefined ) { 8604 selector = ''; 8605 } 8606 else if ( $.isPlainObject( selector ) ) { 8607 opts = selector; 8608 selector = ''; 8609 } 8610 8611 opts = _selector_opts( opts ); 8612 8613 var inst = this.iterator( 'table', function ( settings ) { 8614 return __column_selector( settings, selector, opts ); 8615 }, 1 ); 8616 8617 // Want argument shifting here and in _row_selector? 8618 inst.selector.cols = selector; 8619 inst.selector.opts = opts; 8620 8621 return inst; 8622 } ); 8623 8624 _api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) { 8625 return this.iterator( 'column', function ( settings, column ) { 8626 return settings.aoColumns[column].nTh; 8627 }, 1 ); 8628 } ); 8629 8630 _api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) { 8631 return this.iterator( 'column', function ( settings, column ) { 8632 return settings.aoColumns[column].nTf; 8633 }, 1 ); 8634 } ); 8635 8636 _api_registerPlural( 'columns().data()', 'column().data()', function () { 8637 return this.iterator( 'column-rows', __columnData, 1 ); 8638 } ); 8639 8640 _api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () { 8641 return this.iterator( 'column', function ( settings, column ) { 8642 return settings.aoColumns[column].mData; 8643 }, 1 ); 8644 } ); 8645 8646 _api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) { 8647 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) { 8648 return _pluck_order( settings.aoData, rows, 8649 type === 'search' ? '_aFilterData' : '_aSortData', column 8650 ); 8651 }, 1 ); 8652 } ); 8653 8654 _api_registerPlural( 'columns().nodes()', 'column().nodes()', function () { 8655 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) { 8656 return _pluck_order( settings.aoData, rows, 'anCells', column ) ; 8657 }, 1 ); 8658 } ); 8659 8660 _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) { 8661 var that = this; 8662 var ret = this.iterator( 'column', function ( settings, column ) { 8663 if ( vis === undefined ) { 8664 return settings.aoColumns[ column ].bVisible; 8665 } // else 8666 __setColumnVis( settings, column, vis ); 8667 } ); 8668 8669 // Group the column visibility changes 8670 if ( vis !== undefined ) { 8671 this.iterator( 'table', function ( settings ) { 8672 // Redraw the header after changes 8673 _fnDrawHead( settings, settings.aoHeader ); 8674 _fnDrawHead( settings, settings.aoFooter ); 8675 8676 // Update colspan for no records display. Child rows and extensions will use their own 8677 // listeners to do this - only need to update the empty table item here 8678 if ( ! settings.aiDisplay.length ) { 8679 $(settings.nTBody).find('td[colspan]').attr('colspan', _fnVisbleColumns(settings)); 8680 } 8681 8682 _fnSaveState( settings ); 8683 8684 // Second loop once the first is done for events 8685 that.iterator( 'column', function ( settings, column ) { 8686 _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] ); 8687 } ); 8688 8689 if ( calc === undefined || calc ) { 8690 that.columns.adjust(); 8691 } 8692 }); 8693 } 8694 8695 return ret; 8696 } ); 8697 8698 _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) { 8699 return this.iterator( 'column', function ( settings, column ) { 8700 return type === 'visible' ? 8701 _fnColumnIndexToVisible( settings, column ) : 8702 column; 8703 }, 1 ); 8704 } ); 8705 8706 _api_register( 'columns.adjust()', function () { 8707 return this.iterator( 'table', function ( settings ) { 8708 _fnAdjustColumnSizing( settings ); 8709 }, 1 ); 8710 } ); 8711 8712 _api_register( 'column.index()', function ( type, idx ) { 8713 if ( this.context.length !== 0 ) { 8714 var ctx = this.context[0]; 8715 8716 if ( type === 'fromVisible' || type === 'toData' ) { 8717 return _fnVisibleToColumnIndex( ctx, idx ); 8718 } 8719 else if ( type === 'fromData' || type === 'toVisible' ) { 8720 return _fnColumnIndexToVisible( ctx, idx ); 8721 } 8722 } 8723 } ); 8724 8725 _api_register( 'column()', function ( selector, opts ) { 8726 return _selector_first( this.columns( selector, opts ) ); 8727 } ); 8728 8729 8730 8731 var __cell_selector = function ( settings, selector, opts ) 8732 { 8733 var data = settings.aoData; 8734 var rows = _selector_row_indexes( settings, opts ); 8735 var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) ); 8736 var allCells = $( [].concat.apply([], cells)
vendor: 7,274 bytes, lines 8736-9008
8736); 8737 var row; 8738 var columns = settings.aoColumns.length; 8739 var a, i, ien, j, o, host; 8740 8741 var run = function ( s ) { 8742 var fnSelector = typeof s === 'function'; 8743 8744 if ( s === null || s === undefined || fnSelector ) { 8745 // All cells and function selectors 8746 a = []; 8747 8748 for ( i=0, ien=rows.length ; i<ien ; i++ ) { 8749 row = rows[i]; 8750 8751 for ( j=0 ; j<columns ; j++ ) { 8752 o = { 8753 row: row, 8754 column: j 8755 }; 8756 8757 if ( fnSelector ) { 8758 // Selector - function 8759 host = data[ row ]; 8760 8761 if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) { 8762 a.push( o ); 8763 } 8764 } 8765 else { 8766 // Selector - all 8767 a.push( o ); 8768 } 8769 } 8770 } 8771 8772 return a; 8773 } 8774 8775 // Selector - index 8776 if ( $.isPlainObject( s ) ) { 8777 // Valid cell index and its in the array of selectable rows 8778 return s.column !== undefined && s.row !== undefined && $.inArray( s.row, rows ) !== -1 ? 8779 [s] : 8780 []; 8781 } 8782 8783 // Selector - jQuery filtered cells 8784 var jqResult = allCells 8785 .filter( s ) 8786 .map( function (i, el) { 8787 return { // use a new object, in case someone changes the values 8788 row: el._DT_CellIndex.row, 8789 column: el._DT_CellIndex.column 8790 }; 8791 } ) 8792 .toArray(); 8793 8794 if ( jqResult.length || ! s.nodeName ) { 8795 return jqResult; 8796 } 8797 8798 // Otherwise the selector is a node, and there is one last option - the 8799 // element might be a child of an element which has dt-row and dt-column 8800 // data attributes 8801 host = $(s).closest('*[data-dt-row]'); 8802 return host.length ? 8803 [ { 8804 row: host.data('dt-row'), 8805 column: host.data('dt-column') 8806 } ] : 8807 []; 8808 }; 8809 8810 return _selector_run( 'cell', selector, run, settings, opts ); 8811 }; 8812 8813 8814 8815 8816 _api_register( 'cells()', function ( rowSelector, columnSelector, opts ) { 8817 // Argument shifting 8818 if ( $.isPlainObject( rowSelector ) ) { 8819 // Indexes 8820 if ( rowSelector.row === undefined ) { 8821 // Selector options in first parameter 8822 opts = rowSelector; 8823 rowSelector = null; 8824 } 8825 else { 8826 // Cell index objects in first parameter 8827 opts = columnSelector; 8828 columnSelector = null; 8829 } 8830 } 8831 if ( $.isPlainObject( columnSelector ) ) { 8832 opts = columnSelector; 8833 columnSelector = null; 8834 } 8835 8836 // Cell selector 8837 if ( columnSelector === null || columnSelector === undefined ) { 8838 return this.iterator( 'table', function ( settings ) { 8839 return __cell_selector( settings, rowSelector, _selector_opts( opts ) ); 8840 } ); 8841 } 8842 8843 // The default built in options need to apply to row and columns 8844 var internalOpts = opts ? { 8845 page: opts.page, 8846 order: opts.order, 8847 search: opts.search 8848 } : {}; 8849 8850 // Row + column selector 8851 var columns = this.columns( columnSelector, internalOpts ); 8852 var rows = this.rows( rowSelector, internalOpts ); 8853 var i, ien, j, jen; 8854 8855 var cellsNoOpts = this.iterator( 'table', function ( settings, idx ) { 8856 var a = []; 8857 8858 for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) { 8859 for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) { 8860 a.push( { 8861 row: rows[idx][i], 8862 column: columns[idx][j] 8863 } ); 8864 } 8865 } 8866 8867 return a; 8868 }, 1 ); 8869 8870 // There is currently only one extension which uses a cell selector extension 8871 // It is a _major_ performance drag to run this if it isn't needed, so this is 8872 // an extension specific check at the moment 8873 var cells = opts && opts.selected ? 8874 this.cells( cellsNoOpts, opts ) : 8875 cellsNoOpts; 8876 8877 $.extend( cells.selector, { 8878 cols: columnSelector, 8879 rows: rowSelector, 8880 opts: opts 8881 } ); 8882 8883 return cells; 8884 } ); 8885 8886 8887 _api_registerPlural( 'cells().nodes()', 'cell().node()', function () { 8888 return this.iterator( 'cell', function ( settings, row, column ) { 8889 var data = settings.aoData[ row ]; 8890 8891 return data && data.anCells ? 8892 data.anCells[ column ] : 8893 undefined; 8894 }, 1 ); 8895 } ); 8896 8897 8898 _api_register( 'cells().data()', function () { 8899 return this.iterator( 'cell', function ( settings, row, column ) { 8900 return _fnGetCellData( settings, row, column ); 8901 }, 1 ); 8902 } ); 8903 8904 8905 _api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) { 8906 type = type === 'search' ? '_aFilterData' : '_aSortData'; 8907 8908 return this.iterator( 'cell', function ( settings, row, column ) { 8909 return settings.aoData[ row ][ type ][ column ]; 8910 }, 1 ); 8911 } ); 8912 8913 8914 _api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) { 8915 return this.iterator( 'cell', function ( settings, row, column ) { 8916 return _fnGetCellData( settings, row, column, type ); 8917 }, 1 ); 8918 } ); 8919 8920 8921 _api_registerPlural( 'cells().indexes()', 'cell().index()', function () { 8922 return this.iterator( 'cell', function ( settings, row, column ) { 8923 return { 8924 row: row, 8925 column: column, 8926 columnVisible: _fnColumnIndexToVisible( settings, column ) 8927 }; 8928 }, 1 ); 8929 } ); 8930 8931 8932 _api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) { 8933 return this.iterator( 'cell', function ( settings, row, column ) { 8934 _fnInvalidate( settings, row, src, column ); 8935 } ); 8936 } ); 8937 8938 8939 8940 _api_register( 'cell()', function ( rowSelector, columnSelector, opts ) { 8941 return _selector_first( this.cells( rowSelector, columnSelector, opts ) ); 8942 } ); 8943 8944 8945 _api_register( 'cell().data()', function ( data ) { 8946 var ctx = this.context; 8947 var cell = this[0]; 8948 8949 if ( data === undefined ) { 8950 // Get 8951 return ctx.length && cell.length ? 8952 _fnGetCellData( ctx[0], cell[0].row, cell[0].column ) : 8953 undefined; 8954 } 8955 8956 // Set 8957 _fnSetCellData( ctx[0], cell[0].row, cell[0].column, data ); 8958 _fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column ); 8959 8960 return this; 8961 } ); 8962 8963 8964 8965 /** 8966 * Get current ordering (sorting) that has been applied to the table. 8967 * 8968 * @returns {array} 2D array containing the sorting information for the first 8969 * table in the current context. Each element in the parent array represents 8970 * a column being sorted upon (i.e. multi-sorting with two columns would have 8971 * 2 inner arrays). The inner arrays may have 2 or 3 elements. The first is 8972 * the column index that the sorting condition applies to, the second is the 8973 * direction of the sort (`desc` or `asc`) and, optionally, the third is the 8974 * index of the sorting order from the `column.sorting` initialisation array. 8975 *//** 8976 * Set the ordering for the table. 8977 * 8978 * @param {integer} order Column index to sort upon. 8979 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`) 8980 * @returns {DataTables.Api} this 8981 *//** 8982 * Set the ordering for the table. 8983 * 8984 * @param {array} order 1D array of sorting information to be applied. 8985 * @param {array} [...] Optional additional sorting conditions 8986 * @returns {DataTables.Api} this 8987 *//** 8988 * Set the ordering for the table. 8989 * 8990 * @param {array} order 2D array of sorting information to be applied. 8991 * @returns {DataTables.Api} this 8992 */ 8993 _api_register( 'order()', function ( order, dir ) { 8994 var ctx = this.context; 8995 8996 if ( order === undefined ) { 8997 // get 8998 return ctx.length !== 0 ? 8999 ctx[0].aaSorting : 9000 undefined; 9001 } 9002 9003 // set 9004 if ( typeof order === 'number' ) { 9005 // Simple column / direction passed in 9006 order = [ [ order, dir ] ]; 9007 } 9008 else if ( order.length && !
vendor: 15,088 bytes, lines 9008-9564
9008$.isArray( order[0] ) ) { 9009 // Arguments passed in (list of 1D arrays) 9010 order = Array.prototype.slice.call( arguments ); 9011 } 9012 // otherwise a 2D array was passed in 9013 9014 return this.iterator( 'table', function ( settings ) { 9015 settings.aaSorting = order.slice(); 9016 } ); 9017 } ); 9018 9019 9020 /** 9021 * Attach a sort listener to an element for a given column 9022 * 9023 * @param {node|jQuery|string} node Identifier for the element(s) to attach the 9024 * listener to. This can take the form of a single DOM node, a jQuery 9025 * collection of nodes or a jQuery selector which will identify the node(s). 9026 * @param {integer} column the column that a click on this node will sort on 9027 * @param {function} [callback] callback function when sort is run 9028 * @returns {DataTables.Api} this 9029 */ 9030 _api_register( 'order.listener()', function ( node, column, callback ) { 9031 return this.iterator( 'table', function ( settings ) { 9032 _fnSortAttachListener( settings, node, column, callback ); 9033 } ); 9034 } ); 9035 9036 9037 _api_register( 'order.fixed()', function ( set ) { 9038 if ( ! set ) { 9039 var ctx = this.context; 9040 var fixed = ctx.length ? 9041 ctx[0].aaSortingFixed : 9042 undefined; 9043 9044 return $.isArray( fixed ) ? 9045 { pre: fixed } : 9046 fixed; 9047 } 9048 9049 return this.iterator( 'table', function ( settings ) { 9050 settings.aaSortingFixed = $.extend( true, {}, set ); 9051 } ); 9052 } ); 9053 9054 9055 // Order by the selected column(s) 9056 _api_register( [ 9057 'columns().order()', 9058 'column().order()' 9059 ], function ( dir ) { 9060 var that = this; 9061 9062 return this.iterator( 'table', function ( settings, i ) { 9063 var sort = []; 9064 9065 $.each( that[i], function (j, col) { 9066 sort.push( [ col, dir ] ); 9067 } ); 9068 9069 settings.aaSorting = sort; 9070 } ); 9071 } ); 9072 9073 9074 9075 _api_register( 'search()', function ( input, regex, smart, caseInsen ) { 9076 var ctx = this.context; 9077 9078 if ( input === undefined ) { 9079 // get 9080 return ctx.length !== 0 ? 9081 ctx[0].oPreviousSearch.sSearch : 9082 undefined; 9083 } 9084 9085 // set 9086 return this.iterator( 'table', function ( settings ) { 9087 if ( ! settings.oFeatures.bFilter ) { 9088 return; 9089 } 9090 9091 _fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, { 9092 "sSearch": input+"", 9093 "bRegex": regex === null ? false : regex, 9094 "bSmart": smart === null ? true : smart, 9095 "bCaseInsensitive": caseInsen === null ? true : caseInsen 9096 } ), 1 ); 9097 } ); 9098 } ); 9099 9100 9101 _api_registerPlural( 9102 'columns().search()', 9103 'column().search()', 9104 function ( input, regex, smart, caseInsen ) { 9105 return this.iterator( 'column', function ( settings, column ) { 9106 var preSearch = settings.aoPreSearchCols; 9107 9108 if ( input === undefined ) { 9109 // get 9110 return preSearch[ column ].sSearch; 9111 } 9112 9113 // set 9114 if ( ! settings.oFeatures.bFilter ) { 9115 return; 9116 } 9117 9118 $.extend( preSearch[ column ], { 9119 "sSearch": input+"", 9120 "bRegex": regex === null ? false : regex, 9121 "bSmart": smart === null ? true : smart, 9122 "bCaseInsensitive": caseInsen === null ? true : caseInsen 9123 } ); 9124 9125 _fnFilterComplete( settings, settings.oPreviousSearch, 1 ); 9126 } ); 9127 } 9128 ); 9129 9130 /* 9131 * State API methods 9132 */ 9133 9134 _api_register( 'state()', function () { 9135 return this.context.length ? 9136 this.context[0].oSavedState : 9137 null; 9138 } ); 9139 9140 9141 _api_register( 'state.clear()', function () { 9142 return this.iterator( 'table', function ( settings ) { 9143 // Save an empty object 9144 settings.fnStateSaveCallback.call( settings.oInstance, settings, {} ); 9145 } ); 9146 } ); 9147 9148 9149 _api_register( 'state.loaded()', function () { 9150 return this.context.length ? 9151 this.context[0].oLoadedState : 9152 null; 9153 } ); 9154 9155 9156 _api_register( 'state.save()', function () { 9157 return this.iterator( 'table', function ( settings ) { 9158 _fnSaveState( settings ); 9159 } ); 9160 } ); 9161 9162 9163 9164 /** 9165 * Provide a common method for plug-ins to check the version of DataTables being 9166 * used, in order to ensure compatibility. 9167 * 9168 * @param {string} version Version string to check for, in the format "X.Y.Z". 9169 * Note that the formats "X" and "X.Y" are also acceptable. 9170 * @returns {boolean} true if this version of DataTables is greater or equal to 9171 * the required version, or false if this version of DataTales is not 9172 * suitable 9173 * @static 9174 * @dtopt API-Static 9175 * 9176 * @example 9177 * alert( $.fn.dataTable.versionCheck( '1.9.0' ) ); 9178 */ 9179 DataTable.versionCheck = DataTable.fnVersionCheck = function( version ) 9180 { 9181 var aThis = DataTable.version.split('.'); 9182 var aThat = version.split('.'); 9183 var iThis, iThat; 9184 9185 for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) { 9186 iThis = parseInt( aThis[i], 10 ) || 0; 9187 iThat = parseInt( aThat[i], 10 ) || 0; 9188 9189 // Parts are the same, keep comparing 9190 if (iThis === iThat) { 9191 continue; 9192 } 9193 9194 // Parts are different, return immediately 9195 return iThis > iThat; 9196 } 9197 9198 return true; 9199 }; 9200 9201 9202 /** 9203 * Check if a `<table>` node is a DataTable table already or not. 9204 * 9205 * @param {node|jquery|string} table Table node, jQuery object or jQuery 9206 * selector for the table to test. Note that if more than more than one 9207 * table is passed on, only the first will be checked 9208 * @returns {boolean} true the table given is a DataTable, or false otherwise 9209 * @static 9210 * @dtopt API-Static 9211 * 9212 * @example 9213 * if ( ! $.fn.DataTable.isDataTable( '#example' ) ) { 9214 * $('#example').dataTable(); 9215 * } 9216 */ 9217 DataTable.isDataTable = DataTable.fnIsDataTable = function ( table ) 9218 { 9219 var t = $(table).get(0); 9220 var is = false; 9221 9222 if ( table instanceof DataTable.Api ) { 9223 return true; 9224 } 9225 9226 $.each( DataTable.settings, function (i, o) { 9227 var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null; 9228 var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null; 9229 9230 if ( o.nTable === t || head === t || foot === t ) { 9231 is = true; 9232 } 9233 } ); 9234 9235 return is; 9236 }; 9237 9238 9239 /** 9240 * Get all DataTable tables that have been initialised - optionally you can 9241 * select to get only currently visible tables. 9242 * 9243 * @param {boolean} [visible=false] Flag to indicate if you want all (default) 9244 * or visible tables only. 9245 * @returns {array} Array of `table` nodes (not DataTable instances) which are 9246 * DataTables 9247 * @static 9248 * @dtopt API-Static 9249 * 9250 * @example 9251 * $.each( $.fn.dataTable.tables(true), function () { 9252 * $(table).DataTable().columns.adjust(); 9253 * } ); 9254 */ 9255 DataTable.tables = DataTable.fnTables = function ( visible ) 9256 { 9257 var api = false; 9258 9259 if ( $.isPlainObject( visible ) ) { 9260 api = visible.api; 9261 visible = visible.visible; 9262 } 9263 9264 var a = $.map( DataTable.settings, function (o) { 9265 if ( !visible || (visible && $(o.nTable).is(':visible')) ) { 9266 return o.nTable; 9267 } 9268 } ); 9269 9270 return api ? 9271 new _Api( a ) : 9272 a; 9273 }; 9274 9275 9276 /** 9277 * Convert from camel case parameters to Hungarian notation. This is made public 9278 * for the extensions to provide the same ability as DataTables core to accept 9279 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase 9280 * parameters. 9281 * 9282 * @param {object} src The model object which holds all parameters that can be 9283 * mapped. 9284 * @param {object} user The object to convert from camel case to Hungarian. 9285 * @param {boolean} force When set to `true`, properties which already have a 9286 * Hungarian value in the `user` object will be overwritten. Otherwise they 9287 * won't be. 9288 */ 9289 DataTable.camelToHungarian = _fnCamelToHungarian; 9290 9291 9292 9293 /** 9294 * 9295 */ 9296 _api_register( '$()', function ( selector, opts ) { 9297 var 9298 rows = this.rows( opts ).nodes(), // Get all rows 9299 jqRows = $(rows); 9300 9301 return $( [].concat( 9302 jqRows.filter( selector ).toArray(), 9303 jqRows.find( selector ).toArray() 9304 ) ); 9305 } ); 9306 9307 9308 // jQuery functions to operate on the tables 9309 $.each( [ 'on', 'one', 'off' ], function (i, key) { 9310 _api_register( key+'()', function ( /* event, handler */ ) { 9311 var args = Array.prototype.slice.call(arguments); 9312 9313 // Add the `dt` namespace automatically if it isn't already present 9314 args[0] = $.map( args[0].split( /\s/ ), function ( e ) { 9315 return ! e.match(/\.dt\b/) ? 9316 e+'.dt' : 9317 e; 9318 } ).join( ' ' ); 9319 9320 var inst = $( this.tables().nodes() ); 9321 inst[key].apply( inst, args ); 9322 return this; 9323 } ); 9324 } ); 9325 9326 9327 _api_register( 'clear()', function () { 9328 return this.iterator( 'table', function ( settings ) { 9329 _fnClearTable( settings ); 9330 } ); 9331 } ); 9332 9333 9334 _api_register( 'settings()', function () { 9335 return new _Api( this.context, this.context ); 9336 } ); 9337 9338 9339 _api_register( 'init()', function () { 9340 var ctx = this.context; 9341 return ctx.length ? ctx[0].oInit : null; 9342 } ); 9343 9344 9345 _api_register( 'data()', function () { 9346 return this.iterator( 'table', function ( settings ) { 9347 return _pluck( settings.aoData, '_aData' ); 9348 } ).flatten(); 9349 } ); 9350 9351 9352 _api_register( 'destroy()', function ( remove ) { 9353 remove = remove || false; 9354 9355 return this.iterator( 'table', function ( settings ) { 9356 var orig = settings.nTableWrapper.parentNode; 9357 var classes = settings.oClasses; 9358 var table = settings.nTable; 9359 var tbody = settings.nTBody; 9360 var thead = settings.nTHead; 9361 var tfoot = settings.nTFoot; 9362 var jqTable = $(table); 9363 var jqTbody = $(tbody); 9364 var jqWrapper = $(settings.nTableWrapper); 9365 var rows = $.map( settings.aoData, function (r) { return r.nTr; } ); 9366 var i, ien; 9367 9368 // Flag to note that the table is currently being destroyed - no action 9369 // should be taken 9370 settings.bDestroying = true; 9371 9372 // Fire off the destroy callbacks for plug-ins etc 9373 _fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] ); 9374 9375 // If not being removed from the document, make all columns visible 9376 if ( ! remove ) { 9377 new _Api( settings ).columns().visible( true ); 9378 } 9379 9380 // Blitz all `DT` namespaced events (these are internal events, the 9381 // lowercase, `dt` events are user subscribed and they are responsible 9382 // for removing them 9383 jqWrapper.off('.DT').find(':not(tbody *)').off('.DT'); 9384 $(window).off('.DT-'+settings.sInstance); 9385 9386 // When scrolling we had to break the table up - restore it 9387 if ( table != thead.parentNode ) { 9388 jqTable.children('thead').detach(); 9389 jqTable.append( thead ); 9390 } 9391 9392 if ( tfoot && table != tfoot.parentNode ) { 9393 jqTable.children('tfoot').detach(); 9394 jqTable.append( tfoot ); 9395 } 9396 9397 settings.aaSorting = []; 9398 settings.aaSortingFixed = []; 9399 _fnSortingClasses( settings ); 9400 9401 $( rows ).removeClass( settings.asStripeClasses.join(' ') ); 9402 9403 $('th, td', thead).removeClass( classes.sSortable+' '+ 9404 classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone 9405 ); 9406 9407 // Add the TR elements back into the table in their original order 9408 jqTbody.children().detach(); 9409 jqTbody.append( rows ); 9410 9411 // Remove the DataTables generated nodes, events and classes 9412 var removedMethod = remove ? 'remove' : 'detach'; 9413 jqTable[ removedMethod ](); 9414 jqWrapper[ removedMethod ](); 9415 9416 // If we need to reattach the table to the document 9417 if ( ! remove && orig ) { 9418 // insertBefore acts like appendChild if !arg[1] 9419 orig.insertBefore( table, settings.nTableReinsertBefore ); 9420 9421 // Restore the width of the original table - was read from the style property, 9422 // so we can restore directly to that 9423 jqTable 9424 .css( 'width', settings.sDestroyWidth ) 9425 .removeClass( classes.sTable ); 9426 9427 // If the were originally stripe classes - then we add them back here. 9428 // Note this is not fool proof (for example if not all rows had stripe 9429 // classes - but it's a good effort without getting carried away 9430 ien = settings.asDestroyStripes.length; 9431 9432 if ( ien ) { 9433 jqTbody.children().each( function (i) { 9434 $(this).addClass( settings.asDestroyStripes[i % ien] ); 9435 } ); 9436 } 9437 } 9438 9439 /* Remove the settings object from the settings array */ 9440 var idx = $.inArray( settings, DataTable.settings ); 9441 if ( idx !== -1 ) { 9442 DataTable.settings.splice( idx, 1 ); 9443 } 9444 } ); 9445 } ); 9446 9447 9448 // Add the `every()` method for rows, columns and cells in a compact form 9449 $.each( [ 'column', 'row', 'cell' ], function ( i, type ) { 9450 _api_register( type+'s().every()', function ( fn ) { 9451 var opts = this.selector.opts; 9452 var api = this; 9453 9454 return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) { 9455 // Rows and columns: 9456 // arg1 - index 9457 // arg2 - table counter 9458 // arg3 - loop counter 9459 // arg4 - undefined 9460 // Cells: 9461 // arg1 - row index 9462 // arg2 - column index 9463 // arg3 - table counter 9464 // arg4 - loop counter 9465 fn.call( 9466 api[ type ]( 9467 arg1, 9468 type==='cell' ? arg2 : opts, 9469 type==='cell' ? opts : undefined 9470 ), 9471 arg1, arg2, arg3, arg4 9472 ); 9473 } ); 9474 } ); 9475 } ); 9476 9477 9478 // i18n method for extensions to be able to use the language object from the 9479 // DataTable 9480 _api_register( 'i18n()', function ( token, def, plural ) { 9481 var ctx = this.context[0]; 9482 var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage ); 9483 9484 if ( resolved === undefined ) { 9485 resolved = def; 9486 } 9487 9488 if ( plural !== undefined && $.isPlainObject( resolved ) ) { 9489 resolved = resolved[ plural ] !== undefined ? 9490 resolved[ plural ] : 9491 resolved._; 9492 } 9493 9494 return resolved.replace( '%d', plural ); // nb: plural might be undefined, 9495 } ); 9496 /** 9497 * Version string for plug-ins to check compatibility. Allowed format is 9498 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used 9499 * only for non-release builds. See http://semver.org/ for more information. 9500 * @member 9501 * @type string 9502 * @default Version number 9503 */ 9504 DataTable.version = "1.10.21"; 9505 9506 /** 9507 * Private data store, containing all of the settings objects that are 9508 * created for the tables on a given page. 9509 * 9510 * Note that the `DataTable.settings` object is aliased to 9511 * `jQuery.fn.dataTableExt` through which it may be accessed and 9512 * manipulated, or `jQuery.fn.dataTable.settings`. 9513 * @member 9514 * @type array 9515 * @default [] 9516 * @private 9517 */ 9518 DataTable.settings = []; 9519 9520 /** 9521 * Object models container, for the various models that DataTables has 9522 * available to it. These models define the objects that are used to hold 9523 * the active state and configuration of the table. 9524 * @namespace 9525 */ 9526 DataTable.models = {}; 9527 9528 9529 9530 /** 9531 * Template object for the way in which DataTables holds information about 9532 * search information for the global filter and individual column filters. 9533 * @namespace 9534 */ 9535 DataTable.models.oSearch = { 9536 /** 9537 * Flag to indicate if the filtering should be case insensitive or not 9538 * @type boolean 9539 * @default true 9540 */ 9541 "bCaseInsensitive": true, 9542 9543 /** 9544 * Applied search term 9545 * @type string 9546 * @default <i>Empty string</i> 9547 */ 9548 "sSearch": "", 9549 9550 /** 9551 * Flag to indicate if the search term should be interpreted as a 9552 * regular expression (true) or not (false) and therefore and special 9553 * regex characters escaped. 9554 * @type boolean 9555 * @default false 9556 */ 9557 "bRegex": false, 9558 9559 /** 9560 * Flag to indicate if DataTables is to use its smart filtering or not. 9561 * @type boolean 9562 * @default true 9563 */ 9564 "bSmart": tru
vendor: 11,217 bytes, lines 9564-9922
9564e 9565 }; 9566 9567 9568 9569 9570 /** 9571 * Template object for the way in which DataTables holds information about 9572 * each individual row. This is the object format used for the settings 9573 * aoData array. 9574 * @namespace 9575 */ 9576 DataTable.models.oRow = { 9577 /** 9578 * TR element for the row 9579 * @type node 9580 * @default null 9581 */ 9582 "nTr": null, 9583 9584 /** 9585 * Array of TD elements for each row. This is null until the row has been 9586 * created. 9587 * @type array nodes 9588 * @default [] 9589 */ 9590 "anCells": null, 9591 9592 /** 9593 * Data object from the original data source for the row. This is either 9594 * an array if using the traditional form of DataTables, or an object if 9595 * using mData options. The exact type will depend on the passed in 9596 * data from the data source, or will be an array if using DOM a data 9597 * source. 9598 * @type array|object 9599 * @default [] 9600 */ 9601 "_aData": [], 9602 9603 /** 9604 * Sorting data cache - this array is ostensibly the same length as the 9605 * number of columns (although each index is generated only as it is 9606 * needed), and holds the data that is used for sorting each column in the 9607 * row. We do this cache generation at the start of the sort in order that 9608 * the formatting of the sort data need be done only once for each cell 9609 * per sort. This array should not be read from or written to by anything 9610 * other than the master sorting methods. 9611 * @type array 9612 * @default null 9613 * @private 9614 */ 9615 "_aSortData": null, 9616 9617 /** 9618 * Per cell filtering data cache. As per the sort data cache, used to 9619 * increase the performance of the filtering in DataTables 9620 * @type array 9621 * @default null 9622 * @private 9623 */ 9624 "_aFilterData": null, 9625 9626 /** 9627 * Filtering data cache. This is the same as the cell filtering cache, but 9628 * in this case a string rather than an array. This is easily computed with 9629 * a join on `_aFilterData`, but is provided as a cache so the join isn't 9630 * needed on every search (memory traded for performance) 9631 * @type array 9632 * @default null 9633 * @private 9634 */ 9635 "_sFilterRow": null, 9636 9637 /** 9638 * Cache of the class name that DataTables has applied to the row, so we 9639 * can quickly look at this variable rather than needing to do a DOM check 9640 * on className for the nTr property. 9641 * @type string 9642 * @default <i>Empty string</i> 9643 * @private 9644 */ 9645 "_sRowStripe": "", 9646 9647 /** 9648 * Denote if the original data source was from the DOM, or the data source 9649 * object. This is used for invalidating data, so DataTables can 9650 * automatically read data from the original source, unless uninstructed 9651 * otherwise. 9652 * @type string 9653 * @default null 9654 * @private 9655 */ 9656 "src": null, 9657 9658 /** 9659 * Index in the aoData array. This saves an indexOf lookup when we have the 9660 * object, but want to know the index 9661 * @type integer 9662 * @default -1 9663 * @private 9664 */ 9665 "idx": -1 9666 }; 9667 9668 9669 /** 9670 * Template object for the column information object in DataTables. This object 9671 * is held in the settings aoColumns array and contains all the information that 9672 * DataTables needs about each individual column. 9673 * 9674 * Note that this object is related to {@link DataTable.defaults.column} 9675 * but this one is the internal data store for DataTables's cache of columns. 9676 * It should NOT be manipulated outside of DataTables. Any configuration should 9677 * be done through the initialisation options. 9678 * @namespace 9679 */ 9680 DataTable.models.oColumn = { 9681 /** 9682 * Column index. This could be worked out on-the-fly with $.inArray, but it 9683 * is faster to just hold it as a variable 9684 * @type integer 9685 * @default null 9686 */ 9687 "idx": null, 9688 9689 /** 9690 * A list of the columns that sorting should occur on when this column 9691 * is sorted. That this property is an array allows multi-column sorting 9692 * to be defined for a column (for example first name / last name columns 9693 * would benefit from this). The values are integers pointing to the 9694 * columns to be sorted on (typically it will be a single integer pointing 9695 * at itself, but that doesn't need to be the case). 9696 * @type array 9697 */ 9698 "aDataSort": null, 9699 9700 /** 9701 * Define the sorting directions that are applied to the column, in sequence 9702 * as the column is repeatedly sorted upon - i.e. the first value is used 9703 * as the sorting direction when the column if first sorted (clicked on). 9704 * Sort it again (click again) and it will move on to the next index. 9705 * Repeat until loop. 9706 * @type array 9707 */ 9708 "asSorting": null, 9709 9710 /** 9711 * Flag to indicate if the column is searchable, and thus should be included 9712 * in the filtering or not. 9713 * @type boolean 9714 */ 9715 "bSearchable": null, 9716 9717 /** 9718 * Flag to indicate if the column is sortable or not. 9719 * @type boolean 9720 */ 9721 "bSortable": null, 9722 9723 /** 9724 * Flag to indicate if the column is currently visible in the table or not 9725 * @type boolean 9726 */ 9727 "bVisible": null, 9728 9729 /** 9730 * Store for manual type assignment using the `column.type` option. This 9731 * is held in store so we can manipulate the column's `sType` property. 9732 * @type string 9733 * @default null 9734 * @private 9735 */ 9736 "_sManualType": null, 9737 9738 /** 9739 * Flag to indicate if HTML5 data attributes should be used as the data 9740 * source for filtering or sorting. True is either are. 9741 * @type boolean 9742 * @default false 9743 * @private 9744 */ 9745 "_bAttrSrc": false, 9746 9747 /** 9748 * Developer definable function that is called whenever a cell is created (Ajax source, 9749 * etc) or processed for input (DOM source). This can be used as a compliment to mRender 9750 * allowing you to modify the DOM element (add background colour for example) when the 9751 * element is available. 9752 * @type function 9753 * @param {element} nTd The TD node that has been created 9754 * @param {*} sData The Data for the cell 9755 * @param {array|object} oData The data for the whole row 9756 * @param {int} iRow The row index for the aoData data store 9757 * @default null 9758 */ 9759 "fnCreatedCell": null, 9760 9761 /** 9762 * Function to get data from a cell in a column. You should <b>never</b> 9763 * access data directly through _aData internally in DataTables - always use 9764 * the method attached to this property. It allows mData to function as 9765 * required. This function is automatically assigned by the column 9766 * initialisation method 9767 * @type function 9768 * @param {array|object} oData The data array/object for the array 9769 * (i.e. aoData[]._aData) 9770 * @param {string} sSpecific The specific data type you want to get - 9771 * 'display', 'type' 'filter' 'sort' 9772 * @returns {*} The data for the cell from the given row's data 9773 * @default null 9774 */ 9775 "fnGetData": null, 9776 9777 /** 9778 * Function to set data for a cell in the column. You should <b>never</b> 9779 * set the data directly to _aData internally in DataTables - always use 9780 * this method. It allows mData to function as required. This function 9781 * is automatically assigned by the column initialisation method 9782 * @type function 9783 * @param {array|object} oData The data array/object for the array 9784 * (i.e. aoData[]._aData) 9785 * @param {*} sValue Value to set 9786 * @default null 9787 */ 9788 "fnSetData": null, 9789 9790 /** 9791 * Property to read the value for the cells in the column from the data 9792 * source array / object. If null, then the default content is used, if a 9793 * function is given then the return from the function is used. 9794 * @type function|int|string|null 9795 * @default null 9796 */ 9797 "mData": null, 9798 9799 /** 9800 * Partner property to mData which is used (only when defined) to get 9801 * the data - i.e. it is basically the same as mData, but without the 9802 * 'set' option, and also the data fed to it is the result from mData. 9803 * This is the rendering method to match the data method of mData. 9804 * @type function|int|string|null 9805 * @default null 9806 */ 9807 "mRender": null, 9808 9809 /** 9810 * Unique header TH/TD element for this column - this is what the sorting 9811 * listener is attached to (if sorting is enabled.) 9812 * @type node 9813 * @default null 9814 */ 9815 "nTh": null, 9816 9817 /** 9818 * Unique footer TH/TD element for this column (if there is one). Not used 9819 * in DataTables as such, but can be used for plug-ins to reference the 9820 * footer for each column. 9821 * @type node 9822 * @default null 9823 */ 9824 "nTf": null, 9825 9826 /** 9827 * The class to apply to all TD elements in the table's TBODY for the column 9828 * @type string 9829 * @default null 9830 */ 9831 "sClass": null, 9832 9833 /** 9834 * When DataTables calculates the column widths to assign to each column, 9835 * it finds the longest string in each column and then constructs a 9836 * temporary table and reads the widths from that. The problem with this 9837 * is that "mmm" is much wider then "iiii", but the latter is a longer 9838 * string - thus the calculation can go wrong (doing it properly and putting 9839 * it into an DOM object and measuring that is horribly(!) slow). Thus as 9840 * a "work around" we provide this option. It will append its value to the 9841 * text that is found to be the longest string for the column - i.e. padding. 9842 * @type string 9843 */ 9844 "sContentPadding": null, 9845 9846 /** 9847 * Allows a default value to be given for a column's data, and will be used 9848 * whenever a null data source is encountered (this can be because mData 9849 * is set to null, or because the data source itself is null). 9850 * @type string 9851 * @default null 9852 */ 9853 "sDefaultContent": null, 9854 9855 /** 9856 * Name for the column, allowing reference to the column by name as well as 9857 * by index (needs a lookup to work by name). 9858 * @type string 9859 */ 9860 "sName": null, 9861 9862 /** 9863 * Custom sorting data type - defines which of the available plug-ins in 9864 * afnSortData the custom sorting will use - if any is defined. 9865 * @type string 9866 * @default std 9867 */ 9868 "sSortDataType": 'std', 9869 9870 /** 9871 * Class to be applied to the header element when sorting on this column 9872 * @type string 9873 * @default null 9874 */ 9875 "sSortingClass": null, 9876 9877 /** 9878 * Class to be applied to the header element when sorting on this column - 9879 * when jQuery UI theming is used. 9880 * @type string 9881 * @default null 9882 */ 9883 "sSortingClassJUI": null, 9884 9885 /** 9886 * Title of the column - what is seen in the TH element (nTh). 9887 * @type string 9888 */ 9889 "sTitle": null, 9890 9891 /** 9892 * Column sorting and filtering type 9893 * @type string 9894 * @default null 9895 */ 9896 "sType": null, 9897 9898 /** 9899 * Width of the column 9900 * @type string 9901 * @default null 9902 */ 9903 "sWidth": null, 9904 9905 /** 9906 * Width of the column when it was first "encountered" 9907 * @type string 9908 * @default null 9909 */ 9910 "sWidthOrig": null 9911 }; 9912 9913 9914 /* 9915 * Developer note: The properties of the object below are given in Hungarian 9916 * notation, that was used as the interface for DataTables prior to v1.10, however 9917 * from v1.10 onwards the primary interface is camel case. In order to avoid 9918 * breaking backwards compatibility utterly with this change, the Hungarian 9919 * version is still, internally the primary interface, but is is not documented 9920 * - hence the @name tags in each doc comment. This allows a Javascript function 9921 * to create a map from Hungarian notation to camel case (going the other direction 9922 * would require each property to be listed, which would a
9922t around 3K to the size 9923 * of DataTables, while this method is about a 0.5K hit
vendor: 57,106 bytes, lines 9923-11701
9923. 9924 * 9925 * Ultimately this does pave the way for Hungarian notation to be dropped 9926 * completely, but that is a massive amount of work and will break current 9927 * installs (therefore is on-hold until v2). 9928 */ 9929 9930 /** 9931 * Initialisation options that can be given to DataTables at initialisation 9932 * time. 9933 * @namespace 9934 */ 9935 DataTable.defaults = { 9936 /** 9937 * An array of data to use for the table, passed in at initialisation which 9938 * will be used in preference to any data which is already in the DOM. This is 9939 * particularly useful for constructing tables purely in Javascript, for 9940 * example with a custom Ajax call. 9941 * @type array 9942 * @default null 9943 * 9944 * @dtopt Option 9945 * @name DataTable.defaults.data 9946 * 9947 * @example 9948 * // Using a 2D array data source 9949 * $(document).ready( function () { 9950 * $('#example').dataTable( { 9951 * "data": [ 9952 * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'], 9953 * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'], 9954 * ], 9955 * "columns": [ 9956 * { "title": "Engine" }, 9957 * { "title": "Browser" }, 9958 * { "title": "Platform" }, 9959 * { "title": "Version" }, 9960 * { "title": "Grade" } 9961 * ] 9962 * } ); 9963 * } ); 9964 * 9965 * @example 9966 * // Using an array of objects as a data source (`data`) 9967 * $(document).ready( function () { 9968 * $('#example').dataTable( { 9969 * "data": [ 9970 * { 9971 * "engine": "Trident", 9972 * "browser": "Internet Explorer 4.0", 9973 * "platform": "Win 95+", 9974 * "version": 4, 9975 * "grade": "X" 9976 * }, 9977 * { 9978 * "engine": "Trident", 9979 * "browser": "Internet Explorer 5.0", 9980 * "platform": "Win 95+", 9981 * "version": 5, 9982 * "grade": "C" 9983 * } 9984 * ], 9985 * "columns": [ 9986 * { "title": "Engine", "data": "engine" }, 9987 * { "title": "Browser", "data": "browser" }, 9988 * { "title": "Platform", "data": "platform" }, 9989 * { "title": "Version", "data": "version" }, 9990 * { "title": "Grade", "data": "grade" } 9991 * ] 9992 * } ); 9993 * } ); 9994 */ 9995 "aaData": null, 9996 9997 9998 /** 9999 * If ordering is enabled, then DataTables will perform a first pass sort on 10000 * initialisation. You can define which column(s) the sort is performed 10001 * upon, and the sorting direction, with this variable. The `sorting` array 10002 * should contain an array for each column to be sorted initially containing 10003 * the column's index and a direction string ('asc' or 'desc'). 10004 * @type array 10005 * @default [[0,'asc']] 10006 * 10007 * @dtopt Option 10008 * @name DataTable.defaults.order 10009 * 10010 * @example 10011 * // Sort by 3rd column first, and then 4th column 10012 * $(document).ready( function() { 10013 * $('#example').dataTable( { 10014 * "order": [[2,'asc'], [3,'desc']] 10015 * } ); 10016 * } ); 10017 * 10018 * // No initial sorting 10019 * $(document).ready( function() { 10020 * $('#example').dataTable( { 10021 * "order": [] 10022 * } ); 10023 * } ); 10024 */ 10025 "aaSorting": [[0,'asc']], 10026 10027 10028 /** 10029 * This parameter is basically identical to the `sorting` parameter, but 10030 * cannot be overridden by user interaction with the table. What this means 10031 * is that you could have a column (visible or hidden) which the sorting 10032 * will always be forced on first - any sorting after that (from the user) 10033 * will then be performed as required. This can be useful for grouping rows 10034 * together. 10035 * @type array 10036 * @default null 10037 * 10038 * @dtopt Option 10039 * @name DataTable.defaults.orderFixed 10040 * 10041 * @example 10042 * $(document).ready( function() { 10043 * $('#example').dataTable( { 10044 * "orderFixed": [[0,'asc']] 10045 * } ); 10046 * } ) 10047 */ 10048 "aaSortingFixed": [], 10049 10050 10051 /** 10052 * DataTables can be instructed to load data to display in the table from a 10053 * Ajax source. This option defines how that Ajax call is made and where to. 10054 * 10055 * The `ajax` property has three different modes of operation, depending on 10056 * how it is defined. These are: 10057 * 10058 * * `string` - Set the URL from where the data should be loaded from. 10059 * * `object` - Define properties for `jQuery.ajax`. 10060 * * `function` - Custom data get function 10061 * 10062 * `string` 10063 * -------- 10064 * 10065 * As a string, the `ajax` property simply defines the URL from which 10066 * DataTables will load data. 10067 * 10068 * `object` 10069 * -------- 10070 * 10071 * As an object, the parameters in the object are passed to 10072 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control 10073 * of the Ajax request. DataTables has a number of default parameters which 10074 * you can override using this option. Please refer to the jQuery 10075 * documentation for a full description of the options available, although 10076 * the following parameters provide additional options in DataTables or 10077 * require special consideration: 10078 * 10079 * * `data` - As with jQuery, `data` can be provided as an object, but it 10080 * can also be used as a function to manipulate the data DataTables sends 10081 * to the server. The function takes a single parameter, an object of 10082 * parameters with the values that DataTables has readied for sending. An 10083 * object may be returned which will be merged into the DataTables 10084 * defaults, or you can add the items to the object that was passed in and 10085 * not return anything from the function. This supersedes `fnServerParams` 10086 * from DataTables 1.9-. 10087 * 10088 * * `dataSrc` - By default DataTables will look for the property `data` (or 10089 * `aaData` for compatibility with DataTables 1.9-) when obtaining data 10090 * from an Ajax source or for server-side processing - this parameter 10091 * allows that property to be changed. You can use Javascript dotted 10092 * object notation to get a data source for multiple levels of nesting, or 10093 * it my be used as a function. As a function it takes a single parameter, 10094 * the JSON returned from the server, which can be manipulated as 10095 * required, with the returned value being that used by DataTables as the 10096 * data source for the table. This supersedes `sAjaxDataProp` from 10097 * DataTables 1.9-. 10098 * 10099 * * `success` - Should not be overridden it is used internally in 10100 * DataTables. To manipulate / transform the data returned by the server 10101 * use `ajax.dataSrc`, or use `ajax` as a function (see below). 10102 * 10103 * `function` 10104 * ---------- 10105 * 10106 * As a function, making the Ajax call is left up to yourself allowing 10107 * complete control of the Ajax request. Indeed, if desired, a method other 10108 * than Ajax could be used to obtain the required data, such as Web storage 10109 * or an AIR database. 10110 * 10111 * The function is given four parameters and no return is required. The 10112 * parameters are: 10113 * 10114 * 1. _object_ - Data to send to the server 10115 * 2. _function_ - Callback function that must be executed when the required 10116 * data has been obtained. That data should be passed into the callback 10117 * as the only parameter 10118 * 3. _object_ - DataTables settings object for the table 10119 * 10120 * Note that this supersedes `fnServerData` from DataTables 1.9-. 10121 * 10122 * @type string|object|function 10123 * @default null 10124 * 10125 * @dtopt Option 10126 * @name DataTable.defaults.ajax 10127 * @since 1.10.0 10128 * 10129 * @example 10130 * // Get JSON data from a file via Ajax. 10131 * // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default). 10132 * $('#example').dataTable( { 10133 * "ajax": "data.json" 10134 * } ); 10135 * 10136 * @example 10137 * // Get JSON data from a file via Ajax, using `dataSrc` to change 10138 * // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`) 10139 * $('#example').dataTable( { 10140 * "ajax": { 10141 * "url": "data.json", 10142 * "dataSrc": "tableData" 10143 * } 10144 * } ); 10145 * 10146 * @example 10147 * // Get JSON data from a file via Ajax, using `dataSrc` to read data 10148 * // from a plain array rather than an array in an object 10149 * $('#example').dataTable( { 10150 * "ajax": { 10151 * "url": "data.json", 10152 * "dataSrc": "" 10153 * } 10154 * } ); 10155 * 10156 * @example 10157 * // Manipulate the data returned from the server - add a link to data 10158 * // (note this can, should, be done using `render` for the column - this 10159 * // is just a simple example of how the data can be manipulated). 10160 * $('#example').dataTable( { 10161 * "ajax": { 10162 * "url": "data.json", 10163 * "dataSrc": function ( json ) { 10164 * for ( var i=0, ien=json.length ; i<ien ; i++ ) { 10165 * json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>'; 10166 * } 10167 * return json; 10168 * } 10169 * } 10170 * } ); 10171 * 10172 * @example 10173 * // Add data to the request 10174 * $('#example').dataTable( { 10175 * "ajax": { 10176 * "url": "data.json", 10177 * "data": function ( d ) { 10178 * return { 10179 * "extra_search": $('#extra').val() 10180 * }; 10181 * } 10182 * } 10183 * } ); 10184 * 10185 * @example 10186 * // Send request as POST 10187 * $('#example').dataTable( { 10188 * "ajax": { 10189 * "url": "data.json", 10190 * "type": "POST" 10191 * } 10192 * } ); 10193 * 10194 * @example 10195 * // Get the data from localStorage (could interface with a form for 10196 * // adding, editing and removing rows). 10197 * $('#example').dataTable( { 10198 * "ajax": function (data, callback, settings) { 10199 * callback( 10200 * JSON.parse( localStorage.getItem('dataTablesData') ) 10201 * ); 10202 * } 10203 * } ); 10204 */ 10205 "ajax": null, 10206 10207 10208 /** 10209 * This parameter allows you to readily specify the entries in the length drop 10210 * down menu that DataTables shows when pagination is enabled. It can be 10211 * either a 1D array of options which will be used for both the displayed 10212 * option and the value, or a 2D array which will use the array in the first 10213 * position as the value, and the array in the second position as the 10214 * displayed options (useful for language strings such as 'All'). 10215 * 10216 * Note that the `pageLength` property will be automatically set to the 10217 * first value given in this array, unless `pageLength` is also provided. 10218 * @type array 10219 * @default [ 10, 25, 50, 100 ] 10220 * 10221 * @dtopt Option 10222 * @name DataTable.defaults.lengthMenu 10223 * 10224 * @example 10225 * $(document).ready( function() { 10226 * $('#example').dataTable( { 10227 * "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]] 10228 * } ); 10229 * } ); 10230 */ 10231 "aLengthMenu": [ 10, 25, 50, 100 ], 10232 10233 10234 /** 10235 * The `columns` option in the initialisation parameter allows you to define 10236 * details about the way individual columns behave. For a full list of 10237 * column options that can be set, please see 10238 * {@link DataTable.defaults.column}. Note that if you use `columns` to 10239 * define your columns, you must have an entry in the array for every single 10240 * column that you have in your table (these can be null if you don't which 10241 * to specify any options). 10242 * @member 10243 * 10244 * @name DataTable.defaults.column 10245 */ 10246 "aoColumns": null, 10247 10248 /** 10249 * Very similar to `columns`, `columnDefs` allows you to target a specific 10250 * column, multiple columns, or all columns, using the `targets` property of 10251 * each object in the array. This allows great flexibility when creating 10252 * tables, as the `columnDefs` arrays can be of any length, targeting the 10253 * columns you specifically want. `columnDefs` may use any of the column 10254 * options available: {@link DataTable.defaults.column}, but it _must_ 10255 * have `targets` defined in each object in the array. Values in the `targets` 10256 * array may be: 10257 * <ul> 10258 * <li>a string - class name will be matched on the TH for the column</li> 10259 * <li>0 or a positive integer - column index counting from the left</li> 10260 * <li>a negative integer - column index counting from the right</li> 10261 * <li>the string "_all" - all columns (i.e. assign a default)</li> 10262 * </ul> 10263 * @member 10264 * 10265 * @name DataTable.defaults.columnDefs 10266 */ 10267 "aoColumnDefs": null, 10268 10269 10270 /** 10271 * Basically the same as `search`, this parameter defines the individual column 10272 * filtering state at initialisation time. The array must be of the same size 10273 * as the number of columns, and each element be an object with the parameters 10274 * `search` and `escapeRegex` (the latter is optional). 'null' is also 10275 * accepted and the default will be used. 10276 * @type array 10277 * @default [] 10278 * 10279 * @dtopt Option 10280 * @name DataTable.defaults.searchCols 10281 * 10282 * @example 10283 * $(document).ready( function() { 10284 * $('#example').dataTable( { 10285 * "searchCols": [ 10286 * null, 10287 * { "search": "My filter" }, 10288 * null, 10289 * { "search": "^[0-9]", "escapeRegex": false } 10290 * ] 10291 * } ); 10292 * } ) 10293 */ 10294 "aoSearchCols": [], 10295 10296 10297 /** 10298 * An array of CSS classes that should be applied to displayed rows. This 10299 * array may be of any length, and DataTables will apply each class 10300 * sequentially, looping when required. 10301 * @type array 10302 * @default null <i>Will take the values determined by the `oClasses.stripe*` 10303 * options</i> 10304 * 10305 * @dtopt Option 10306 * @name DataTable.defaults.stripeClasses 10307 * 10308 * @example 10309 * $(document).ready( function() { 10310 * $('#example').dataTable( { 10311 * "stripeClasses": [ 'strip1', 'strip2', 'strip3' ] 10312 * } ); 10313 * } ) 10314 */ 10315 "asStripeClasses": null, 10316 10317 10318 /** 10319 * Enable or disable automatic column width calculation. This can be disabled 10320 * as an optimisation (it takes some time to calculate the widths) if the 10321 * tables widths are passed in using `columns`. 10322 * @type boolean 10323 * @default true 10324 * 10325 * @dtopt Features 10326 * @name DataTable.defaults.autoWidth 10327 * 10328 * @example 10329 * $(document).ready( function () { 10330 * $('#example').dataTable( { 10331 * "autoWidth": false 10332 * } ); 10333 * } ); 10334 */ 10335 "bAutoWidth": true, 10336 10337 10338 /** 10339 * Deferred rendering can provide DataTables with a huge speed boost when you 10340 * are using an Ajax or JS data source for the table. This option, when set to 10341 * true, will cause DataTables to defer the creation of the table elements for 10342 * each row until they are needed for a draw - saving a significant amount of 10343 * time. 10344 * @type boolean 10345 * @default false 10346 * 10347 * @dtopt Features 10348 * @name DataTable.defaults.deferRender 10349 * 10350 * @example 10351 * $(document).ready( function() { 10352 * $('#example').dataTable( { 10353 * "ajax": "sources/arrays.txt", 10354 * "deferRender": true 10355 * } ); 10356 * } ); 10357 */ 10358 "bDeferRender": false, 10359 10360 10361 /** 10362 * Replace a DataTable which matches the given selector and replace it with 10363 * one which has the properties of the new initialisation object passed. If no 10364 * table matches the selector, then the new DataTable will be constructed as 10365 * per normal. 10366 * @type boolean 10367 * @default false 10368 * 10369 * @dtopt Options 10370 * @name DataTable.defaults.destroy 10371 * 10372 * @example 10373 * $(document).ready( function() { 10374 * $('#example').dataTable( { 10375 * "srollY": "200px", 10376 * "paginate": false 10377 * } ); 10378 * 10379 * // Some time later.... 10380 * $('#example').dataTable( { 10381 * "filter": false, 10382 * "destroy": true 10383 * } ); 10384 * } ); 10385 */ 10386 "bDestroy": false, 10387 10388 10389 /** 10390 * Enable or disable filtering of data. Filtering in DataTables is "smart" in 10391 * that it allows the end user to input multiple words (space separated) and 10392 * will match a row containing those words, even if not in the order that was 10393 * specified (this allow matching across multiple columns). Note that if you 10394 * wish to use filtering in DataTables this must remain 'true' - to remove the 10395 * default filtering input box and retain filtering abilities, please use 10396 * {@link DataTable.defaults.dom}. 10397 * @type boolean 10398 * @default true 10399 * 10400 * @dtopt Features 10401 * @name DataTable.defaults.searching 10402 * 10403 * @example 10404 * $(document).ready( function () { 10405 * $('#example').dataTable( { 10406 * "searching": false 10407 * } ); 10408 * } ); 10409 */ 10410 "bFilter": true, 10411 10412 10413 /** 10414 * Enable or disable the table information display. This shows information 10415 * about the data that is currently visible on the page, including information 10416 * about filtered data if that action is being performed. 10417 * @type boolean 10418 * @default true 10419 * 10420 * @dtopt Features 10421 * @name DataTable.defaults.info 10422 * 10423 * @example 10424 * $(document).ready( function () { 10425 * $('#example').dataTable( { 10426 * "info": false 10427 * } ); 10428 * } ); 10429 */ 10430 "bInfo": true, 10431 10432 10433 /** 10434 * Allows the end user to select the size of a formatted page from a select 10435 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`). 10436 * @type boolean 10437 * @default true 10438 * 10439 * @dtopt Features 10440 * @name DataTable.defaults.lengthChange 10441 * 10442 * @example 10443 * $(document).ready( function () { 10444 * $('#example').dataTable( { 10445 * "lengthChange": false 10446 * } ); 10447 * } ); 10448 */ 10449 "bLengthChange": true, 10450 10451 10452 /** 10453 * Enable or disable pagination. 10454 * @type boolean 10455 * @default true 10456 * 10457 * @dtopt Features 10458 * @name DataTable.defaults.paging 10459 * 10460 * @example 10461 * $(document).ready( function () { 10462 * $('#example').dataTable( { 10463 * "paging": false 10464 * } ); 10465 * } ); 10466 */ 10467 "bPaginate": true, 10468 10469 10470 /** 10471 * Enable or disable the display of a 'processing' indicator when the table is 10472 * being processed (e.g. a sort). This is particularly useful for tables with 10473 * large amounts of data where it can take a noticeable amount of time to sort 10474 * the entries. 10475 * @type boolean 10476 * @default false 10477 * 10478 * @dtopt Features 10479 * @name DataTable.defaults.processing 10480 * 10481 * @example 10482 * $(document).ready( function () { 10483 * $('#example').dataTable( { 10484 * "processing": true 10485 * } ); 10486 * } ); 10487 */ 10488 "bProcessing": false, 10489 10490 10491 /** 10492 * Retrieve the DataTables object for the given selector. Note that if the 10493 * table has already been initialised, this parameter will cause DataTables 10494 * to simply return the object that has already been set up - it will not take 10495 * account of any changes you might have made to the initialisation object 10496 * passed to DataTables (setting this parameter to true is an acknowledgement 10497 * that you understand this). `destroy` can be used to reinitialise a table if 10498 * you need. 10499 * @type boolean 10500 * @default false 10501 * 10502 * @dtopt Options 10503 * @name DataTable.defaults.retrieve 10504 * 10505 * @example 10506 * $(document).ready( function() { 10507 * initTable(); 10508 * tableActions(); 10509 * } ); 10510 * 10511 * function initTable () 10512 * { 10513 * return $('#example').dataTable( { 10514 * "scrollY": "200px", 10515 * "paginate": false, 10516 * "retrieve": true 10517 * } ); 10518 * } 10519 * 10520 * function tableActions () 10521 * { 10522 * var table = initTable(); 10523 * // perform API operations with oTable 10524 * } 10525 */ 10526 "bRetrieve": false, 10527 10528 10529 /** 10530 * When vertical (y) scrolling is enabled, DataTables will force the height of 10531 * the table's viewport to the given height at all times (useful for layout). 10532 * However, this can look odd when filtering data down to a small data set, 10533 * and the footer is left "floating" further down. This parameter (when 10534 * enabled) will cause DataTables to collapse the table's viewport down when 10535 * the result set will fit within the given Y height. 10536 * @type boolean 10537 * @default false 10538 * 10539 * @dtopt Options 10540 * @name DataTable.defaults.scrollCollapse 10541 * 10542 * @example 10543 * $(document).ready( function() { 10544 * $('#example').dataTable( { 10545 * "scrollY": "200", 10546 * "scrollCollapse": true 10547 * } ); 10548 * } ); 10549 */ 10550 "bScrollCollapse": false, 10551 10552 10553 /** 10554 * Configure DataTables to use server-side processing. Note that the 10555 * `ajax` parameter must also be given in order to give DataTables a 10556 * source to obtain the required data for each draw. 10557 * @type boolean 10558 * @default false 10559 * 10560 * @dtopt Features 10561 * @dtopt Server-side 10562 * @name DataTable.defaults.serverSide 10563 * 10564 * @example 10565 * $(document).ready( function () { 10566 * $('#example').dataTable( { 10567 * "serverSide": true, 10568 * "ajax": "xhr.php" 10569 * } ); 10570 * } ); 10571 */ 10572 "bServerSide": false, 10573 10574 10575 /** 10576 * Enable or disable sorting of columns. Sorting of individual columns can be 10577 * disabled by the `sortable` option for each column. 10578 * @type boolean 10579 * @default true 10580 * 10581 * @dtopt Features 10582 * @name DataTable.defaults.ordering 10583 * 10584 * @example 10585 * $(document).ready( function () { 10586 * $('#example').dataTable( { 10587 * "ordering": false 10588 * } ); 10589 * } ); 10590 */ 10591 "bSort": true, 10592 10593 10594 /** 10595 * Enable or display DataTables' ability to sort multiple columns at the 10596 * same time (activated by shift-click by the user). 10597 * @type boolean 10598 * @default true 10599 * 10600 * @dtopt Options 10601 * @name DataTable.defaults.orderMulti 10602 * 10603 * @example 10604 * // Disable multiple column sorting ability 10605 * $(document).ready( function () { 10606 * $('#example').dataTable( { 10607 * "orderMulti": false 10608 * } ); 10609 * } ); 10610 */ 10611 "bSortMulti": true, 10612 10613 10614 /** 10615 * Allows control over whether DataTables should use the top (true) unique 10616 * cell that is found for a single column, or the bottom (false - default). 10617 * This is useful when using complex headers. 10618 * @type boolean 10619 * @default false 10620 * 10621 * @dtopt Options 10622 * @name DataTable.defaults.orderCellsTop 10623 * 10624 * @example 10625 * $(document).ready( function() { 10626 * $('#example').dataTable( { 10627 * "orderCellsTop": true 10628 * } ); 10629 * } ); 10630 */ 10631 "bSortCellsTop": false, 10632 10633 10634 /** 10635 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and 10636 * `sorting\_3` to the columns which are currently being sorted on. This is 10637 * presented as a feature switch as it can increase processing time (while 10638 * classes are removed and added) so for large data sets you might want to 10639 * turn this off. 10640 * @type boolean 10641 * @default true 10642 * 10643 * @dtopt Features 10644 * @name DataTable.defaults.orderClasses 10645 * 10646 * @example 10647 * $(document).ready( function () { 10648 * $('#example').dataTable( { 10649 * "orderClasses": false 10650 * } ); 10651 * } ); 10652 */ 10653 "bSortClasses": true, 10654 10655 10656 /** 10657 * Enable or disable state saving. When enabled HTML5 `localStorage` will be 10658 * used to save table display information such as pagination information, 10659 * display length, filtering and sorting. As such when the end user reloads 10660 * the page the display display will match what thy had previously set up. 10661 * 10662 * Due to the use of `localStorage` the default state saving is not supported 10663 * in IE6 or 7. If state saving is required in those browsers, use 10664 * `stateSaveCallback` to provide a storage solution such as cookies. 10665 * @type boolean 10666 * @default false 10667 * 10668 * @dtopt Features 10669 * @name DataTable.defaults.stateSave 10670 * 10671 * @example 10672 * $(document).ready( function () { 10673 * $('#example').dataTable( { 10674 * "stateSave": true 10675 * } ); 10676 * } ); 10677 */ 10678 "bStateSave": false, 10679 10680 10681 /** 10682 * This function is called when a TR element is created (and all TD child 10683 * elements have been inserted), or registered if using a DOM source, allowing 10684 * manipulation of the TR element (adding classes etc). 10685 * @type function 10686 * @param {node} row "TR" element for the current row 10687 * @param {array} data Raw data array for this row 10688 * @param {int} dataIndex The index of this row in the internal aoData array 10689 * 10690 * @dtopt Callbacks 10691 * @name DataTable.defaults.createdRow 10692 * 10693 * @example 10694 * $(document).ready( function() { 10695 * $('#example').dataTable( { 10696 * "createdRow": function( row, data, dataIndex ) { 10697 * // Bold the grade for all 'A' grade browsers 10698 * if ( data[4] == "A" ) 10699 * { 10700 * $('td:eq(4)', row).html( '<b>A</b>' ); 10701 * } 10702 * } 10703 * } ); 10704 * } ); 10705 */ 10706 "fnCreatedRow": null, 10707 10708 10709 /** 10710 * This function is called on every 'draw' event, and allows you to 10711 * dynamically modify any aspect you want about the created DOM. 10712 * @type function 10713 * @param {object} settings DataTables settings object 10714 * 10715 * @dtopt Callbacks 10716 * @name DataTable.defaults.drawCallback 10717 * 10718 * @example 10719 * $(document).ready( function() { 10720 * $('#example').dataTable( { 10721 * "drawCallback": function( settings ) { 10722 * alert( 'DataTables has redrawn the table' ); 10723 * } 10724 * } ); 10725 * } ); 10726 */ 10727 "fnDrawCallback": null, 10728 10729 10730 /** 10731 * Identical to fnHeaderCallback() but for the table footer this function 10732 * allows you to modify the table footer on every 'draw' event. 10733 * @type function 10734 * @param {node} foot "TR" element for the footer 10735 * @param {array} data Full table data (as derived from the original HTML) 10736 * @param {int} start Index for the current display starting point in the 10737 * display array 10738 * @param {int} end Index for the current display ending point in the 10739 * display array 10740 * @param {array int} display Index array to translate the visual position 10741 * to the full data array 10742 * 10743 * @dtopt Callbacks 10744 * @name DataTable.defaults.footerCallback 10745 * 10746 * @example 10747 * $(document).ready( function() { 10748 * $('#example').dataTable( { 10749 * "footerCallback": function( tfoot, data, start, end, display ) { 10750 * tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start; 10751 * } 10752 * } ); 10753 * } ) 10754 */ 10755 "fnFooterCallback": null, 10756 10757 10758 /** 10759 * When rendering large numbers in the information element for the table 10760 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers 10761 * to have a comma separator for the 'thousands' units (e.g. 1 million is 10762 * rendered as "1,000,000") to help readability for the end user. This 10763 * function will override the default method DataTables uses. 10764 * @type function 10765 * @member 10766 * @param {int} toFormat number to be formatted 10767 * @returns {string} formatted string for DataTables to show the number 10768 * 10769 * @dtopt Callbacks 10770 * @name DataTable.defaults.formatNumber 10771 * 10772 * @example 10773 * // Format a number using a single quote for the separator (note that 10774 * // this can also be done with the language.thousands option) 10775 * $(document).ready( function() { 10776 * $('#example').dataTable( { 10777 * "formatNumber": function ( toFormat ) { 10778 * return toFormat.toString().replace( 10779 * /\B(?=(\d{3})+(?!\d))/g, "'" 10780 * ); 10781 * }; 10782 * } ); 10783 * } ); 10784 */ 10785 "fnFormatNumber": function ( toFormat ) { 10786 return toFormat.toString().replace( 10787 /\B(?=(\d{3})+(?!\d))/g, 10788 this.oLanguage.sThousands 10789 ); 10790 }, 10791 10792 10793 /** 10794 * This function is called on every 'draw' event, and allows you to 10795 * dynamically modify the header row. This can be used to calculate and 10796 * display useful information about the table. 10797 * @type function 10798 * @param {node} head "TR" element for the header 10799 * @param {array} data Full table data (as derived from the original HTML) 10800 * @param {int} start Index for the current display starting point in the 10801 * display array 10802 * @param {int} end Index for the current display ending point in the 10803 * display array 10804 * @param {array int} display Index array to translate the visual position 10805 * to the full data array 10806 * 10807 * @dtopt Callbacks 10808 * @name DataTable.defaults.headerCallback 10809 * 10810 * @example 10811 * $(document).ready( function() { 10812 * $('#example').dataTable( { 10813 * "fheaderCallback": function( head, data, start, end, display ) { 10814 * head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records"; 10815 * } 10816 * } ); 10817 * } ) 10818 */ 10819 "fnHeaderCallback": null, 10820 10821 10822 /** 10823 * The information element can be used to convey information about the current 10824 * state of the table. Although the internationalisation options presented by 10825 * DataTables are quite capable of dealing with most customisations, there may 10826 * be times where you wish to customise the string further. This callback 10827 * allows you to do exactly that. 10828 * @type function 10829 * @param {object} oSettings DataTables settings object 10830 * @param {int} start Starting position in data for the draw 10831 * @param {int} end End position in data for the draw 10832 * @param {int} max Total number of rows in the table (regardless of 10833 * filtering) 10834 * @param {int} total Total number of rows in the data set, after filtering 10835 * @param {string} pre The string that DataTables has formatted using it's 10836 * own rules 10837 * @returns {string} The string to be displayed in the information element. 10838 * 10839 * @dtopt Callbacks 10840 * @name DataTable.defaults.infoCallback 10841 * 10842 * @example 10843 * $('#example').dataTable( { 10844 * "infoCallback": function( settings, start, end, max, total, pre ) { 10845 * return start +" to "+ end; 10846 * } 10847 * } ); 10848 */ 10849 "fnInfoCallback": null, 10850 10851 10852 /** 10853 * Called when the table has been initialised. Normally DataTables will 10854 * initialise sequentially and there will be no need for this function, 10855 * however, this does not hold true when using external language information 10856 * since that is obtained using an async XHR call. 10857 * @type function 10858 * @param {object} settings DataTables settings object 10859 * @param {object} json The JSON object request from the server - only 10860 * present if client-side Ajax sourced data is used 10861 * 10862 * @dtopt Callbacks 10863 * @name DataTable.defaults.initComplete 10864 * 10865 * @example 10866 * $(document).ready( function() { 10867 * $('#example').dataTable( { 10868 * "initComplete": function(settings, json) { 10869 * alert( 'DataTables has finished its initialisation.' ); 10870 * } 10871 * } ); 10872 * } ) 10873 */ 10874 "fnInitComplete": null, 10875 10876 10877 /** 10878 * Called at the very start of each table draw and can be used to cancel the 10879 * draw by returning false, any other return (including undefined) results in 10880 * the full draw occurring). 10881 * @type function 10882 * @param {object} settings DataTables settings object 10883 * @returns {boolean} False will cancel the draw, anything else (including no 10884 * return) will allow it to complete. 10885 * 10886 * @dtopt Callbacks 10887 * @name DataTable.defaults.preDrawCallback 10888 * 10889 * @example 10890 * $(document).ready( function() { 10891 * $('#example').dataTable( { 10892 * "preDrawCallback": function( settings ) { 10893 * if ( $('#test').val() == 1 ) { 10894 * return false; 10895 * } 10896 * } 10897 * } ); 10898 * } ); 10899 */ 10900 "fnPreDrawCallback": null, 10901 10902 10903 /** 10904 * This function allows you to 'post process' each row after it have been 10905 * generated for each table draw, but before it is rendered on screen. This 10906 * function might be used for setting the row class name etc. 10907 * @type function 10908 * @param {node} row "TR" element for the current row 10909 * @param {array} data Raw data array for this row 10910 * @param {int} displayIndex The display index for the current table draw 10911 * @param {int} displayIndexFull The index of the data in the full list of 10912 * rows (after filtering) 10913 * 10914 * @dtopt Callbacks 10915 * @name DataTable.defaults.rowCallback 10916 * 10917 * @example 10918 * $(document).ready( function() { 10919 * $('#example').dataTable( { 10920 * "rowCallback": function( row, data, displayIndex, displayIndexFull ) { 10921 * // Bold the grade for all 'A' grade browsers 10922 * if ( data[4] == "A" ) { 10923 * $('td:eq(4)', row).html( '<b>A</b>' ); 10924 * } 10925 * } 10926 * } ); 10927 * } ); 10928 */ 10929 "fnRowCallback": null, 10930 10931 10932 /** 10933 * __Deprecated__ The functionality provided by this parameter has now been 10934 * superseded by that provided through `ajax`, which should be used instead. 10935 * 10936 * This parameter allows you to override the default function which obtains 10937 * the data from the server so something more suitable for your application. 10938 * For example you could use POST data, or pull information from a Gears or 10939 * AIR database. 10940 * @type function 10941 * @member 10942 * @param {string} source HTTP source to obtain the data from (`ajax`) 10943 * @param {array} data A key/value pair object containing the data to send 10944 * to the server 10945 * @param {function} callback to be called on completion of the data get 10946 * process that will draw the data on the page. 10947 * @param {object} settings DataTables settings object 10948 * 10949 * @dtopt Callbacks 10950 * @dtopt Server-side 10951 * @name DataTable.defaults.serverData 10952 * 10953 * @deprecated 1.10. Please use `ajax` for this functionality now. 10954 */ 10955 "fnServerData": null, 10956 10957 10958 /** 10959 * __Deprecated__ The functionality provided by this parameter has now been 10960 * superseded by that provided through `ajax`, which should be used instead. 10961 * 10962 * It is often useful to send extra data to the server when making an Ajax 10963 * request - for example custom filtering information, and this callback 10964 * function makes it trivial to send extra information to the server. The 10965 * passed in parameter is the data set that has been constructed by 10966 * DataTables, and you can add to this or modify it as you require. 10967 * @type function 10968 * @param {array} data Data array (array of objects which are name/value 10969 * pairs) that has been constructed by DataTables and will be sent to the 10970 * server. In the case of Ajax sourced data with server-side processing 10971 * this will be an empty array, for server-side processing there will be a 10972 * significant number of parameters! 10973 * @returns {undefined} Ensure that you modify the data array passed in, 10974 * as this is passed by reference. 10975 * 10976 * @dtopt Callbacks 10977 * @dtopt Server-side 10978 * @name DataTable.defaults.serverParams 10979 * 10980 * @deprecated 1.10. Please use `ajax` for this functionality now. 10981 */ 10982 "fnServerParams": null, 10983 10984 10985 /** 10986 * Load the table state. With this function you can define from where, and how, the 10987 * state of a table is loaded. By default DataTables will load from `localStorage` 10988 * but you might wish to use a server-side database or cookies. 10989 * @type function 10990 * @member 10991 * @param {object} settings DataTables settings object 10992 * @param {object} callback Callback that can be executed when done. It 10993 * should be passed the loaded state object. 10994 * @return {object} The DataTables state object to be loaded 10995 * 10996 * @dtopt Callbacks 10997 * @name DataTable.defaults.stateLoadCallback 10998 * 10999 * @example 11000 * $(document).ready( function() { 11001 * $('#example').dataTable( { 11002 * "stateSave": true, 11003 * "stateLoadCallback": function (settings, callback) { 11004 * $.ajax( { 11005 * "url": "/state_load", 11006 * "dataType": "json", 11007 * "success": function (json) { 11008 * callback( json ); 11009 * } 11010 * } ); 11011 * } 11012 * } ); 11013 * } ); 11014 */ 11015 "fnStateLoadCallback": function ( settings ) { 11016 try { 11017 return JSON.parse( 11018 (settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem( 11019 'DataTables_'+settings.sInstance+'_'+location.pathname 11020 ) 11021 ); 11022 } catch (e) { 11023 return {}; 11024 } 11025 }, 11026 11027 11028 /** 11029 * Callback which allows modification of the saved state prior to loading that state. 11030 * This callback is called when the table is loading state from the stored data, but 11031 * prior to the settings object being modified by the saved state. Note that for 11032 * plug-in authors, you should use the `stateLoadParams` event to load parameters for 11033 * a plug-in. 11034 * @type function 11035 * @param {object} settings DataTables settings object 11036 * @param {object} data The state object that is to be loaded 11037 * 11038 * @dtopt Callbacks 11039 * @name DataTable.defaults.stateLoadParams 11040 * 11041 * @example 11042 * // Remove a saved filter, so filtering is never loaded 11043 * $(document).ready( function() { 11044 * $('#example').dataTable( { 11045 * "stateSave": true, 11046 * "stateLoadParams": function (settings, data) { 11047 * data.oSearch.sSearch = ""; 11048 * } 11049 * } ); 11050 * } ); 11051 * 11052 * @example 11053 * // Disallow state loading by returning false 11054 * $(document).ready( function() { 11055 * $('#example').dataTable( { 11056 * "stateSave": true, 11057 * "stateLoadParams": function (settings, data) { 11058 * return false; 11059 * } 11060 * } ); 11061 * } ); 11062 */ 11063 "fnStateLoadParams": null, 11064 11065 11066 /** 11067 * Callback that is called when the state has been loaded from the state saving method 11068 * and the DataTables settings object has been modified as a result of the loaded state. 11069 * @type function 11070 * @param {object} settings DataTables settings object 11071 * @param {object} data The state object that was loaded 11072 * 11073 * @dtopt Callbacks 11074 * @name DataTable.defaults.stateLoaded 11075 * 11076 * @example 11077 * // Show an alert with the filtering value that was saved 11078 * $(document).ready( function() { 11079 * $('#example').dataTable( { 11080 * "stateSave": true, 11081 * "stateLoaded": function (settings, data) { 11082 * alert( 'Saved filter was: '+data.oSearch.sSearch ); 11083 * } 11084 * } ); 11085 * } ); 11086 */ 11087 "fnStateLoaded": null, 11088 11089 11090 /** 11091 * Save the table state. This function allows you to define where and how the state 11092 * information for the table is stored By default DataTables will use `localStorage` 11093 * but you might wish to use a server-side database or cookies. 11094 * @type function 11095 * @member 11096 * @param {object} settings DataTables settings object 11097 * @param {object} data The state object to be saved 11098 * 11099 * @dtopt Callbacks 11100 * @name DataTable.defaults.stateSaveCallback 11101 * 11102 * @example 11103 * $(document).ready( function() { 11104 * $('#example').dataTable( { 11105 * "stateSave": true, 11106 * "stateSaveCallback": function (settings, data) { 11107 * // Send an Ajax request to the server with the state object 11108 * $.ajax( { 11109 * "url": "/state_save", 11110 * "data": data, 11111 * "dataType": "json", 11112 * "method": "POST" 11113 * "success": function () {} 11114 * } ); 11115 * } 11116 * } ); 11117 * } ); 11118 */ 11119 "fnStateSaveCallback": function ( settings, data ) { 11120 try { 11121 (settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem( 11122 'DataTables_'+settings.sInstance+'_'+location.pathname, 11123 JSON.stringify( data ) 11124 ); 11125 } catch (e) {} 11126 }, 11127 11128 11129 /** 11130 * Callback which allows modification of the state to be saved. Called when the table 11131 * has changed state a new state save is required. This method allows modification of 11132 * the state saving object prior to actually doing the save, including addition or 11133 * other state properties or modification. Note that for plug-in authors, you should 11134 * use the `stateSaveParams` event to save parameters for a plug-in. 11135 * @type function 11136 * @param {object} settings DataTables settings object 11137 * @param {object} data The state object to be saved 11138 * 11139 * @dtopt Callbacks 11140 * @name DataTable.defaults.stateSaveParams 11141 * 11142 * @example 11143 * // Remove a saved filter, so filtering is never saved 11144 * $(document).ready( function() { 11145 * $('#example').dataTable( { 11146 * "stateSave": true, 11147 * "stateSaveParams": function (settings, data) { 11148 * data.oSearch.sSearch = ""; 11149 * } 11150 * } ); 11151 * } ); 11152 */ 11153 "fnStateSaveParams": null, 11154 11155 11156 /** 11157 * Duration for which the saved state information is considered valid. After this period 11158 * has elapsed the state will be returned to the default. 11159 * Value is given in seconds. 11160 * @type int 11161 * @default 7200 <i>(2 hours)</i> 11162 * 11163 * @dtopt Options 11164 * @name DataTable.defaults.stateDuration 11165 * 11166 * @example 11167 * $(document).ready( function() { 11168 * $('#example').dataTable( { 11169 * "stateDuration": 60*60*24; // 1 day 11170 * } ); 11171 * } ) 11172 */ 11173 "iStateDuration": 7200, 11174 11175 11176 /** 11177 * When enabled DataTables will not make a request to the server for the first 11178 * page draw - rather it will use the data already on the page (no sorting etc 11179 * will be applied to it), thus saving on an XHR at load time. `deferLoading` 11180 * is used to indicate that deferred loading is required, but it is also used 11181 * to tell DataTables how many records there are in the full table (allowing 11182 * the information element and pagination to be displayed correctly). In the case 11183 * where a filtering is applied to the table on initial load, this can be 11184 * indicated by giving the parameter as an array, where the first element is 11185 * the number of records available after filtering and the second element is the 11186 * number of records without filtering (allowing the table information element 11187 * to be shown correctly). 11188 * @type int | array 11189 * @default null 11190 * 11191 * @dtopt Options 11192 * @name DataTable.defaults.deferLoading 11193 * 11194 * @example 11195 * // 57 records available in the table, no filtering applied 11196 * $(document).ready( function() { 11197 * $('#example').dataTable( { 11198 * "serverSide": true, 11199 * "ajax": "scripts/server_processing.php", 11200 * "deferLoading": 57 11201 * } ); 11202 * } ); 11203 * 11204 * @example 11205 * // 57 records after filtering, 100 without filtering (an initial filter applied) 11206 * $(document).ready( function() { 11207 * $('#example').dataTable( { 11208 * "serverSide": true, 11209 * "ajax": "scripts/server_processing.php", 11210 * "deferLoading": [ 57, 100 ], 11211 * "search": { 11212 * "search": "my_filter" 11213 * } 11214 * } ); 11215 * } ); 11216 */ 11217 "iDeferLoading": null, 11218 11219 11220 /** 11221 * Number of rows to display on a single page when using pagination. If 11222 * feature enabled (`lengthChange`) then the end user will be able to override 11223 * this to a custom setting using a pop-up menu. 11224 * @type int 11225 * @default 10 11226 * 11227 * @dtopt Options 11228 * @name DataTable.defaults.pageLength 11229 * 11230 * @example 11231 * $(document).ready( function() { 11232 * $('#example').dataTable( { 11233 * "pageLength": 50 11234 * } ); 11235 * } ) 11236 */ 11237 "iDisplayLength": 10, 11238 11239 11240 /** 11241 * Define the starting point for data display when using DataTables with 11242 * pagination. Note that this parameter is the number of records, rather than 11243 * the page number, so if you have 10 records per page and want to start on 11244 * the third page, it should be "20". 11245 * @type int 11246 * @default 0 11247 * 11248 * @dtopt Options 11249 * @name DataTable.defaults.displayStart 11250 * 11251 * @example 11252 * $(document).ready( function() { 11253 * $('#example').dataTable( { 11254 * "displayStart": 20 11255 * } ); 11256 * } ) 11257 */ 11258 "iDisplayStart": 0, 11259 11260 11261 /** 11262 * By default DataTables allows keyboard navigation of the table (sorting, paging, 11263 * and filtering) by adding a `tabindex` attribute to the required elements. This 11264 * allows you to tab through the controls and press the enter key to activate them. 11265 * The tabindex is default 0, meaning that the tab follows the flow of the document. 11266 * You can overrule this using this parameter if you wish. Use a value of -1 to 11267 * disable built-in keyboard navigation. 11268 * @type int 11269 * @default 0 11270 * 11271 * @dtopt Options 11272 * @name DataTable.defaults.tabIndex 11273 * 11274 * @example 11275 * $(document).ready( function() { 11276 * $('#example').dataTable( { 11277 * "tabIndex": 1 11278 * } ); 11279 * } ); 11280 */ 11281 "iTabIndex": 0, 11282 11283 11284 /** 11285 * Classes that DataTables assigns to the various components and features 11286 * that it adds to the HTML table. This allows classes to be configured 11287 * during initialisation in addition to through the static 11288 * {@link DataTable.ext.oStdClasses} object). 11289 * @namespace 11290 * @name DataTable.defaults.classes 11291 */ 11292 "oClasses": {}, 11293 11294 11295 /** 11296 * All strings that DataTables uses in the user interface that it creates 11297 * are defined in this object, allowing you to modified them individually or 11298 * completely replace them all as required. 11299 * @namespace 11300 * @name DataTable.defaults.language 11301 */ 11302 "oLanguage": { 11303 /** 11304 * Strings that are used for WAI-ARIA labels and controls only (these are not 11305 * actually visible on the page, but will be read by screenreaders, and thus 11306 * must be internationalised as well). 11307 * @namespace 11308 * @name DataTable.defaults.language.aria 11309 */ 11310 "oAria": { 11311 /** 11312 * ARIA label that is added to the table headers when the column may be 11313 * sorted ascending by activing the column (click or return when focused). 11314 * Note that the column header is prefixed to this string. 11315 * @type string 11316 * @default : activate to sort column ascending 11317 * 11318 * @dtopt Language 11319 * @name DataTable.defaults.language.aria.sortAscending 11320 * 11321 * @example 11322 * $(document).ready( function() { 11323 * $('#example').dataTable( { 11324 * "language": { 11325 * "aria": { 11326 * "sortAscending": " - click/return to sort ascending" 11327 * } 11328 * } 11329 * } ); 11330 * } ); 11331 */ 11332 "sSortAscending": ": activate to sort column ascending", 11333 11334 /** 11335 * ARIA label that is added to the table headers when the column may be 11336 * sorted descending by activing the column (click or return when focused). 11337 * Note that the column header is prefixed to this string. 11338 * @type string 11339 * @default : activate to sort column ascending 11340 * 11341 * @dtopt Language 11342 * @name DataTable.defaults.language.aria.sortDescending 11343 * 11344 * @example 11345 * $(document).ready( function() { 11346 * $('#example').dataTable( { 11347 * "language": { 11348 * "aria": { 11349 * "sortDescending": " - click/return to sort descending" 11350 * } 11351 * } 11352 * } ); 11353 * } ); 11354 */ 11355 "sSortDescending": ": activate to sort column descending" 11356 }, 11357 11358 /** 11359 * Pagination string used by DataTables for the built-in pagination 11360 * control types. 11361 * @namespace 11362 * @name DataTable.defaults.language.paginate 11363 */ 11364 "oPaginate": { 11365 /** 11366 * Text to use when using the 'full_numbers' type of pagination for the 11367 * button to take the user to the first page. 11368 * @type string 11369 * @default First 11370 * 11371 * @dtopt Language 11372 * @name DataTable.defaults.language.paginate.first 11373 * 11374 * @example 11375 * $(document).ready( function() { 11376 * $('#example').dataTable( { 11377 * "language": { 11378 * "paginate": { 11379 * "first": "First page" 11380 * } 11381 * } 11382 * } ); 11383 * } ); 11384 */ 11385 "sFirst": "First", 11386 11387 11388 /** 11389 * Text to use when using the 'full_numbers' type of pagination for the 11390 * button to take the user to the last page. 11391 * @type string 11392 * @default Last 11393 * 11394 * @dtopt Language 11395 * @name DataTable.defaults.language.paginate.last 11396 * 11397 * @example 11398 * $(document).ready( function() { 11399 * $('#example').dataTable( { 11400 * "language": { 11401 * "paginate": { 11402 * "last": "Last page" 11403 * } 11404 * } 11405 * } ); 11406 * } ); 11407 */ 11408 "sLast": "Last", 11409 11410 11411 /** 11412 * Text to use for the 'next' pagination button (to take the user to the 11413 * next page). 11414 * @type string 11415 * @default Next 11416 * 11417 * @dtopt Language 11418 * @name DataTable.defaults.language.paginate.next 11419 * 11420 * @example 11421 * $(document).ready( function() { 11422 * $('#example').dataTable( { 11423 * "language": { 11424 * "paginate": { 11425 * "next": "Next page" 11426 * } 11427 * } 11428 * } ); 11429 * } ); 11430 */ 11431 "sNext": "Next", 11432 11433 11434 /** 11435 * Text to use for the 'previous' pagination button (to take the user to 11436 * the previous page). 11437 * @type string 11438 * @default Previous 11439 * 11440 * @dtopt Language 11441 * @name DataTable.defaults.language.paginate.previous 11442 * 11443 * @example 11444 * $(document).ready( function() { 11445 * $('#example').dataTable( { 11446 * "language": { 11447 * "paginate": { 11448 * "previous": "Previous page" 11449 * } 11450 * } 11451 * } ); 11452 * } ); 11453 */ 11454 "sPrevious": "Previous" 11455 }, 11456 11457 /** 11458 * This string is shown in preference to `zeroRecords` when the table is 11459 * empty of data (regardless of filtering). Note that this is an optional 11460 * parameter - if it is not given, the value of `zeroRecords` will be used 11461 * instead (either the default or given value). 11462 * @type string 11463 * @default No data available in table 11464 * 11465 * @dtopt Language 11466 * @name DataTable.defaults.language.emptyTable 11467 * 11468 * @example 11469 * $(document).ready( function() { 11470 * $('#example').dataTable( { 11471 * "language": { 11472 * "emptyTable": "No data available in table" 11473 * } 11474 * } ); 11475 * } ); 11476 */ 11477 "sEmptyTable": "No data available in table", 11478 11479 11480 /** 11481 * This string gives information to the end user about the information 11482 * that is current on display on the page. The following tokens can be 11483 * used in the string and will be dynamically replaced as the table 11484 * display updates. This tokens can be placed anywhere in the string, or 11485 * removed as needed by the language requires: 11486 * 11487 * * `\_START\_` - Display index of the first record on the current page 11488 * * `\_END\_` - Display index of the last record on the current page 11489 * * `\_TOTAL\_` - Number of records in the table after filtering 11490 * * `\_MAX\_` - Number of records in the table without filtering 11491 * * `\_PAGE\_` - Current page number 11492 * * `\_PAGES\_` - Total number of pages of data in the table 11493 * 11494 * @type string 11495 * @default Showing _START_ to _END_ of _TOTAL_ entries 11496 * 11497 * @dtopt Language 11498 * @name DataTable.defaults.language.info 11499 * 11500 * @example 11501 * $(document).ready( function() { 11502 * $('#example').dataTable( { 11503 * "language": { 11504 * "info": "Showing page _PAGE_ of _PAGES_" 11505 * } 11506 * } ); 11507 * } ); 11508 */ 11509 "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries", 11510 11511 11512 /** 11513 * Display information string for when the table is empty. Typically the 11514 * format of this string should match `info`. 11515 * @type string 11516 * @default Showing 0 to 0 of 0 entries 11517 * 11518 * @dtopt Language 11519 * @name DataTable.defaults.language.infoEmpty 11520 * 11521 * @example 11522 * $(document).ready( function() { 11523 * $('#example').dataTable( { 11524 * "language": { 11525 * "infoEmpty": "No entries to show" 11526 * } 11527 * } ); 11528 * } ); 11529 */ 11530 "sInfoEmpty": "Showing 0 to 0 of 0 entries", 11531 11532 11533 /** 11534 * When a user filters the information in a table, this string is appended 11535 * to the information (`info`) to give an idea of how strong the filtering 11536 * is. The variable _MAX_ is dynamically updated. 11537 * @type string 11538 * @default (filtered from _MAX_ total entries) 11539 * 11540 * @dtopt Language 11541 * @name DataTable.defaults.language.infoFiltered 11542 * 11543 * @example 11544 * $(document).ready( function() { 11545 * $('#example').dataTable( { 11546 * "language": { 11547 * "infoFiltered": " - filtering from _MAX_ records" 11548 * } 11549 * } ); 11550 * } ); 11551 */ 11552 "sInfoFiltered": "(filtered from _MAX_ total entries)", 11553 11554 11555 /** 11556 * If can be useful to append extra information to the info string at times, 11557 * and this variable does exactly that. This information will be appended to 11558 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are 11559 * being used) at all times. 11560 * @type string 11561 * @default <i>Empty string</i> 11562 * 11563 * @dtopt Language 11564 * @name DataTable.defaults.language.infoPostFix 11565 * 11566 * @example 11567 * $(document).ready( function() { 11568 * $('#example').dataTable( { 11569 * "language": { 11570 * "infoPostFix": "All records shown are derived from real information." 11571 * } 11572 * } ); 11573 * } ); 11574 */ 11575 "sInfoPostFix": "", 11576 11577 11578 /** 11579 * This decimal place operator is a little different from the other 11580 * language options since DataTables doesn't output floating point 11581 * numbers, so it won't ever use this for display of a number. Rather, 11582 * what this parameter does is modify the sort methods of the table so 11583 * that numbers which are in a format which has a character other than 11584 * a period (`.`) as a decimal place will be sorted numerically. 11585 * 11586 * Note that numbers with different decimal places cannot be shown in 11587 * the same table and still be sortable, the table must be consistent. 11588 * However, multiple different tables on the page can use different 11589 * decimal place characters. 11590 * @type string 11591 * @default 11592 * 11593 * @dtopt Language 11594 * @name DataTable.defaults.language.decimal 11595 * 11596 * @example 11597 * $(document).ready( function() { 11598 * $('#example').dataTable( { 11599 * "language": { 11600 * "decimal": "," 11601 * "thousands": "." 11602 * } 11603 * } ); 11604 * } ); 11605 */ 11606 "sDecimal": "", 11607 11608 11609 /** 11610 * DataTables has a build in number formatter (`formatNumber`) which is 11611 * used to format large numbers that are used in the table information. 11612 * By default a comma is used, but this can be trivially changed to any 11613 * character you wish with this parameter. 11614 * @type string 11615 * @default , 11616 * 11617 * @dtopt Language 11618 * @name DataTable.defaults.language.thousands 11619 * 11620 * @example 11621 * $(document).ready( function() { 11622 * $('#example').dataTable( { 11623 * "language": { 11624 * "thousands": "'" 11625 * } 11626 * } ); 11627 * } ); 11628 */ 11629 "sThousands": ",", 11630 11631 11632 /** 11633 * Detail the action that will be taken when the drop down menu for the 11634 * pagination length option is changed. The '_MENU_' variable is replaced 11635 * with a default select list of 10, 25, 50 and 100, and can be replaced 11636 * with a custom select box if required. 11637 * @type string 11638 * @default Show _MENU_ entries 11639 * 11640 * @dtopt Language 11641 * @name DataTable.defaults.language.lengthMenu 11642 * 11643 * @example 11644 * // Language change only 11645 * $(document).ready( function() { 11646 * $('#example').dataTable( { 11647 * "language": { 11648 * "lengthMenu": "Display _MENU_ records" 11649 * } 11650 * } ); 11651 * } ); 11652 * 11653 * @example 11654 * // Language and options change 11655 * $(document).ready( function() { 11656 * $('#example').dataTable( { 11657 * "language": { 11658 * "lengthMenu": 'Display <select>'+ 11659 * '<option value="10">10</option>'+ 11660 * '<option value="20">20</option>'+ 11661 * '<option value="30">30</option>'+ 11662 * '<option value="40">40</option>'+ 11663 * '<option value="50">50</option>'+ 11664 * '<option value="-1">All</option>'+ 11665 * '</select> records' 11666 * } 11667 * } ); 11668 * } ); 11669 */ 11670 "sLengthMenu": "Show _MENU_ entries", 11671 11672 11673 /** 11674 * When using Ajax sourced data and during the first draw when DataTables is 11675 * gathering the data, this message is shown in an empty row in the table to 11676 * indicate to the end user the the data is being loaded. Note that this 11677 * parameter is not used when loading data by server-side processing, just 11678 * Ajax sourced data with client-side processing. 11679 * @type string 11680 * @default Loading... 11681 * 11682 * @dtopt Language 11683 * @name DataTable.defaults.language.loadingRecords 11684 * 11685 * @example 11686 * $(document).ready( function() { 11687 * $('#example').dataTable( { 11688 * "language": { 11689 * "loadingRecords": "Please wait - loading..." 11690 * } 11691 * } ); 11692 * } ); 11693 */ 11694 "sLoadingRecords": "Loading...", 11695 11696 11697 /** 11698 * Text which is displayed when the table is processing a user action 11699 * (usually a sort command or similar). 11700 * @type string 11701 *
11701 @default Processing... 11702 * 11703 * @dtopt Language 11704 * @name DataTable.defaults.language.processing 11705 * 11706 * @example 11707 * $(document).ready( function() { 11708 * $('#example').dataTable( { 11709 * "language": { 11710 * "processing": "DataTables is currently busy" 11711 * } 11712 * } ); 11713 * } ); 11714 */ 11715 "sProcessing": "Processing...
vendor: 42,942 bytes, lines 11715-13009
11715", 11716 11717 11718 /** 11719 * Details the actions that will be taken when the user types into the 11720 * filtering input text box. The variable "_INPUT_", if used in the string, 11721 * is replaced with the HTML text box for the filtering input allowing 11722 * control over where it appears in the string. If "_INPUT_" is not given 11723 * then the input box is appended to the string automatically. 11724 * @type string 11725 * @default Search: 11726 * 11727 * @dtopt Language 11728 * @name DataTable.defaults.language.search 11729 * 11730 * @example 11731 * // Input text box will be appended at the end automatically 11732 * $(document).ready( function() { 11733 * $('#example').dataTable( { 11734 * "language": { 11735 * "search": "Filter records:" 11736 * } 11737 * } ); 11738 * } ); 11739 * 11740 * @example 11741 * // Specify where the filter should appear 11742 * $(document).ready( function() { 11743 * $('#example').dataTable( { 11744 * "language": { 11745 * "search": "Apply filter _INPUT_ to table" 11746 * } 11747 * } ); 11748 * } ); 11749 */ 11750 "sSearch": "Search:", 11751 11752 11753 /** 11754 * Assign a `placeholder` attribute to the search `input` element 11755 * @type string 11756 * @default 11757 * 11758 * @dtopt Language 11759 * @name DataTable.defaults.language.searchPlaceholder 11760 */ 11761 "sSearchPlaceholder": "", 11762 11763 11764 /** 11765 * All of the language information can be stored in a file on the 11766 * server-side, which DataTables will look up if this parameter is passed. 11767 * It must store the URL of the language file, which is in a JSON format, 11768 * and the object has the same properties as the oLanguage object in the 11769 * initialiser object (i.e. the above parameters). Please refer to one of 11770 * the example language files to see how this works in action. 11771 * @type string 11772 * @default <i>Empty string - i.e. disabled</i> 11773 * 11774 * @dtopt Language 11775 * @name DataTable.defaults.language.url 11776 * 11777 * @example 11778 * $(document).ready( function() { 11779 * $('#example').dataTable( { 11780 * "language": { 11781 * "url": "http://www.sprymedia.co.uk/dataTables/lang.txt" 11782 * } 11783 * } ); 11784 * } ); 11785 */ 11786 "sUrl": "", 11787 11788 11789 /** 11790 * Text shown inside the table records when the is no information to be 11791 * displayed after filtering. `emptyTable` is shown when there is simply no 11792 * information in the table at all (regardless of filtering). 11793 * @type string 11794 * @default No matching records found 11795 * 11796 * @dtopt Language 11797 * @name DataTable.defaults.language.zeroRecords 11798 * 11799 * @example 11800 * $(document).ready( function() { 11801 * $('#example').dataTable( { 11802 * "language": { 11803 * "zeroRecords": "No records to display" 11804 * } 11805 * } ); 11806 * } ); 11807 */ 11808 "sZeroRecords": "No matching records found" 11809 }, 11810 11811 11812 /** 11813 * This parameter allows you to have define the global filtering state at 11814 * initialisation time. As an object the `search` parameter must be 11815 * defined, but all other parameters are optional. When `regex` is true, 11816 * the search string will be treated as a regular expression, when false 11817 * (default) it will be treated as a straight string. When `smart` 11818 * DataTables will use it's smart filtering methods (to word match at 11819 * any point in the data), when false this will not be done. 11820 * @namespace 11821 * @extends DataTable.models.oSearch 11822 * 11823 * @dtopt Options 11824 * @name DataTable.defaults.search 11825 * 11826 * @example 11827 * $(document).ready( function() { 11828 * $('#example').dataTable( { 11829 * "search": {"search": "Initial search"} 11830 * } ); 11831 * } ) 11832 */ 11833 "oSearch": $.extend( {}, DataTable.models.oSearch ), 11834 11835 11836 /** 11837 * __Deprecated__ The functionality provided by this parameter has now been 11838 * superseded by that provided through `ajax`, which should be used instead. 11839 * 11840 * By default DataTables will look for the property `data` (or `aaData` for 11841 * compatibility with DataTables 1.9-) when obtaining data from an Ajax 11842 * source or for server-side processing - this parameter allows that 11843 * property to be changed. You can use Javascript dotted object notation to 11844 * get a data source for multiple levels of nesting. 11845 * @type string 11846 * @default data 11847 * 11848 * @dtopt Options 11849 * @dtopt Server-side 11850 * @name DataTable.defaults.ajaxDataProp 11851 * 11852 * @deprecated 1.10. Please use `ajax` for this functionality now. 11853 */ 11854 "sAjaxDataProp": "data", 11855 11856 11857 /** 11858 * __Deprecated__ The functionality provided by this parameter has now been 11859 * superseded by that provided through `ajax`, which should be used instead. 11860 * 11861 * You can instruct DataTables to load data from an external 11862 * source using this parameter (use aData if you want to pass data in you 11863 * already have). Simply provide a url a JSON object can be obtained from. 11864 * @type string 11865 * @default null 11866 * 11867 * @dtopt Options 11868 * @dtopt Server-side 11869 * @name DataTable.defaults.ajaxSource 11870 * 11871 * @deprecated 1.10. Please use `ajax` for this functionality now. 11872 */ 11873 "sAjaxSource": null, 11874 11875 11876 /** 11877 * This initialisation variable allows you to specify exactly where in the 11878 * DOM you want DataTables to inject the various controls it adds to the page 11879 * (for example you might want the pagination controls at the top of the 11880 * table). DIV elements (with or without a custom class) can also be added to 11881 * aid styling. The follow syntax is used: 11882 * <ul> 11883 * <li>The following options are allowed: 11884 * <ul> 11885 * <li>'l' - Length changing</li> 11886 * <li>'f' - Filtering input</li> 11887 * <li>'t' - The table!</li> 11888 * <li>'i' - Information</li> 11889 * <li>'p' - Pagination</li> 11890 * <li>'r' - pRocessing</li> 11891 * </ul> 11892 * </li> 11893 * <li>The following constants are allowed: 11894 * <ul> 11895 * <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li> 11896 * <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li> 11897 * </ul> 11898 * </li> 11899 * <li>The following syntax is expected: 11900 * <ul> 11901 * <li>'<' and '>' - div elements</li> 11902 * <li>'<"class" and '>' - div with a class</li> 11903 * <li>'<"#id" and '>' - div with an ID</li> 11904 * </ul> 11905 * </li> 11906 * <li>Examples: 11907 * <ul> 11908 * <li>'<"wrapper"flipt>'</li> 11909 * <li>'<lf<t>ip>'</li> 11910 * </ul> 11911 * </li> 11912 * </ul> 11913 * @type string 11914 * @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b> 11915 * <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i> 11916 * 11917 * @dtopt Options 11918 * @name DataTable.defaults.dom 11919 * 11920 * @example 11921 * $(document).ready( function() { 11922 * $('#example').dataTable( { 11923 * "dom": '<"top"i>rt<"bottom"flp><"clear">' 11924 * } ); 11925 * } ); 11926 */ 11927 "sDom": "lfrtip", 11928 11929 11930 /** 11931 * Search delay option. This will throttle full table searches that use the 11932 * DataTables provided search input element (it does not effect calls to 11933 * `dt-api search()`, providing a delay before the search is made. 11934 * @type integer 11935 * @default 0 11936 * 11937 * @dtopt Options 11938 * @name DataTable.defaults.searchDelay 11939 * 11940 * @example 11941 * $(document).ready( function() { 11942 * $('#example').dataTable( { 11943 * "searchDelay": 200 11944 * } ); 11945 * } ) 11946 */ 11947 "searchDelay": null, 11948 11949 11950 /** 11951 * DataTables features six different built-in options for the buttons to 11952 * display for pagination control: 11953 * 11954 * * `numbers` - Page number buttons only 11955 * * `simple` - 'Previous' and 'Next' buttons only 11956 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers 11957 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons 11958 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers 11959 * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers 11960 * 11961 * Further methods can be added using {@link DataTable.ext.oPagination}. 11962 * @type string 11963 * @default simple_numbers 11964 * 11965 * @dtopt Options 11966 * @name DataTable.defaults.pagingType 11967 * 11968 * @example 11969 * $(document).ready( function() { 11970 * $('#example').dataTable( { 11971 * "pagingType": "full_numbers" 11972 * } ); 11973 * } ) 11974 */ 11975 "sPaginationType": "simple_numbers", 11976 11977 11978 /** 11979 * Enable horizontal scrolling. When a table is too wide to fit into a 11980 * certain layout, or you have a large number of columns in the table, you 11981 * can enable x-scrolling to show the table in a viewport, which can be 11982 * scrolled. This property can be `true` which will allow the table to 11983 * scroll horizontally when needed, or any CSS unit, or a number (in which 11984 * case it will be treated as a pixel measurement). Setting as simply `true` 11985 * is recommended. 11986 * @type boolean|string 11987 * @default <i>blank string - i.e. disabled</i> 11988 * 11989 * @dtopt Features 11990 * @name DataTable.defaults.scrollX 11991 * 11992 * @example 11993 * $(document).ready( function() { 11994 * $('#example').dataTable( { 11995 * "scrollX": true, 11996 * "scrollCollapse": true 11997 * } ); 11998 * } ); 11999 */ 12000 "sScrollX": "", 12001 12002 12003 /** 12004 * This property can be used to force a DataTable to use more width than it 12005 * might otherwise do when x-scrolling is enabled. For example if you have a 12006 * table which requires to be well spaced, this parameter is useful for 12007 * "over-sizing" the table, and thus forcing scrolling. This property can by 12008 * any CSS unit, or a number (in which case it will be treated as a pixel 12009 * measurement). 12010 * @type string 12011 * @default <i>blank string - i.e. disabled</i> 12012 * 12013 * @dtopt Options 12014 * @name DataTable.defaults.scrollXInner 12015 * 12016 * @example 12017 * $(document).ready( function() { 12018 * $('#example').dataTable( { 12019 * "scrollX": "100%", 12020 * "scrollXInner": "110%" 12021 * } ); 12022 * } ); 12023 */ 12024 "sScrollXInner": "", 12025 12026 12027 /** 12028 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable 12029 * to the given height, and enable scrolling for any data which overflows the 12030 * current viewport. This can be used as an alternative to paging to display 12031 * a lot of data in a small area (although paging and scrolling can both be 12032 * enabled at the same time). This property can be any CSS unit, or a number 12033 * (in which case it will be treated as a pixel measurement). 12034 * @type string 12035 * @default <i>blank string - i.e. disabled</i> 12036 * 12037 * @dtopt Features 12038 * @name DataTable.defaults.scrollY 12039 * 12040 * @example 12041 * $(document).ready( function() { 12042 * $('#example').dataTable( { 12043 * "scrollY": "200px", 12044 * "paginate": false 12045 * } ); 12046 * } ); 12047 */ 12048 "sScrollY": "", 12049 12050 12051 /** 12052 * __Deprecated__ The functionality provided by this parameter has now been 12053 * superseded by that provided through `ajax`, which should be used instead. 12054 * 12055 * Set the HTTP method that is used to make the Ajax call for server-side 12056 * processing or Ajax sourced data. 12057 * @type string 12058 * @default GET 12059 * 12060 * @dtopt Options 12061 * @dtopt Server-side 12062 * @name DataTable.defaults.serverMethod 12063 * 12064 * @deprecated 1.10. Please use `ajax` for this functionality now. 12065 */ 12066 "sServerMethod": "GET", 12067 12068 12069 /** 12070 * DataTables makes use of renderers when displaying HTML elements for 12071 * a table. These renderers can be added or modified by plug-ins to 12072 * generate suitable mark-up for a site. For example the Bootstrap 12073 * integration plug-in for DataTables uses a paging button renderer to 12074 * display pagination buttons in the mark-up required by Bootstrap. 12075 * 12076 * For further information about the renderers available see 12077 * DataTable.ext.renderer 12078 * @type string|object 12079 * @default null 12080 * 12081 * @name DataTable.defaults.renderer 12082 * 12083 */ 12084 "renderer": null, 12085 12086 12087 /** 12088 * Set the data property name that DataTables should use to get a row's id 12089 * to set as the `id` property in the node. 12090 * @type string 12091 * @default DT_RowId 12092 * 12093 * @name DataTable.defaults.rowId 12094 */ 12095 "rowId": "DT_RowId" 12096 }; 12097 12098 _fnHungarianMap( DataTable.defaults ); 12099 12100 12101 12102 /* 12103 * Developer note - See note in model.defaults.js about the use of Hungarian 12104 * notation and camel case. 12105 */ 12106 12107 /** 12108 * Column options that can be given to DataTables at initialisation time. 12109 * @namespace 12110 */ 12111 DataTable.defaults.column = { 12112 /** 12113 * Define which column(s) an order will occur on for this column. This 12114 * allows a column's ordering to take multiple columns into account when 12115 * doing a sort or use the data from a different column. For example first 12116 * name / last name columns make sense to do a multi-column sort over the 12117 * two columns. 12118 * @type array|int 12119 * @default null <i>Takes the value of the column index automatically</i> 12120 * 12121 * @name DataTable.defaults.column.orderData 12122 * @dtopt Columns 12123 * 12124 * @example 12125 * // Using `columnDefs` 12126 * $(document).ready( function() { 12127 * $('#example').dataTable( { 12128 * "columnDefs": [ 12129 * { "orderData": [ 0, 1 ], "targets": [ 0 ] }, 12130 * { "orderData": [ 1, 0 ], "targets": [ 1 ] }, 12131 * { "orderData": 2, "targets": [ 2 ] } 12132 * ] 12133 * } ); 12134 * } ); 12135 * 12136 * @example 12137 * // Using `columns` 12138 * $(document).ready( function() { 12139 * $('#example').dataTable( { 12140 * "columns": [ 12141 * { "orderData": [ 0, 1 ] }, 12142 * { "orderData": [ 1, 0 ] }, 12143 * { "orderData": 2 }, 12144 * null, 12145 * null 12146 * ] 12147 * } ); 12148 * } ); 12149 */ 12150 "aDataSort": null, 12151 "iDataSort": -1, 12152 12153 12154 /** 12155 * You can control the default ordering direction, and even alter the 12156 * behaviour of the sort handler (i.e. only allow ascending ordering etc) 12157 * using this parameter. 12158 * @type array 12159 * @default [ 'asc', 'desc' ] 12160 * 12161 * @name DataTable.defaults.column.orderSequence 12162 * @dtopt Columns 12163 * 12164 * @example 12165 * // Using `columnDefs` 12166 * $(document).ready( function() { 12167 * $('#example').dataTable( { 12168 * "columnDefs": [ 12169 * { "orderSequence": [ "asc" ], "targets": [ 1 ] }, 12170 * { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] }, 12171 * { "orderSequence": [ "desc" ], "targets": [ 3 ] } 12172 * ] 12173 * } ); 12174 * } ); 12175 * 12176 * @example 12177 * // Using `columns` 12178 * $(document).ready( function() { 12179 * $('#example').dataTable( { 12180 * "columns": [ 12181 * null, 12182 * { "orderSequence": [ "asc" ] }, 12183 * { "orderSequence": [ "desc", "asc", "asc" ] }, 12184 * { "orderSequence": [ "desc" ] }, 12185 * null 12186 * ] 12187 * } ); 12188 * } ); 12189 */ 12190 "asSorting": [ 'asc', 'desc' ], 12191 12192 12193 /** 12194 * Enable or disable filtering on the data in this column. 12195 * @type boolean 12196 * @default true 12197 * 12198 * @name DataTable.defaults.column.searchable 12199 * @dtopt Columns 12200 * 12201 * @example 12202 * // Using `columnDefs` 12203 * $(document).ready( function() { 12204 * $('#example').dataTable( { 12205 * "columnDefs": [ 12206 * { "searchable": false, "targets": [ 0 ] } 12207 * ] } ); 12208 * } ); 12209 * 12210 * @example 12211 * // Using `columns` 12212 * $(document).ready( function() { 12213 * $('#example').dataTable( { 12214 * "columns": [ 12215 * { "searchable": false }, 12216 * null, 12217 * null, 12218 * null, 12219 * null 12220 * ] } ); 12221 * } ); 12222 */ 12223 "bSearchable": true, 12224 12225 12226 /** 12227 * Enable or disable ordering on this column. 12228 * @type boolean 12229 * @default true 12230 * 12231 * @name DataTable.defaults.column.orderable 12232 * @dtopt Columns 12233 * 12234 * @example 12235 * // Using `columnDefs` 12236 * $(document).ready( function() { 12237 * $('#example').dataTable( { 12238 * "columnDefs": [ 12239 * { "orderable": false, "targets": [ 0 ] } 12240 * ] } ); 12241 * } ); 12242 * 12243 * @example 12244 * // Using `columns` 12245 * $(document).ready( function() { 12246 * $('#example').dataTable( { 12247 * "columns": [ 12248 * { "orderable": false }, 12249 * null, 12250 * null, 12251 * null, 12252 * null 12253 * ] } ); 12254 * } ); 12255 */ 12256 "bSortable": true, 12257 12258 12259 /** 12260 * Enable or disable the display of this column. 12261 * @type boolean 12262 * @default true 12263 * 12264 * @name DataTable.defaults.column.visible 12265 * @dtopt Columns 12266 * 12267 * @example 12268 * // Using `columnDefs` 12269 * $(document).ready( function() { 12270 * $('#example').dataTable( { 12271 * "columnDefs": [ 12272 * { "visible": false, "targets": [ 0 ] } 12273 * ] } ); 12274 * } ); 12275 * 12276 * @example 12277 * // Using `columns` 12278 * $(document).ready( function() { 12279 * $('#example').dataTable( { 12280 * "columns": [ 12281 * { "visible": false }, 12282 * null, 12283 * null, 12284 * null, 12285 * null 12286 * ] } ); 12287 * } ); 12288 */ 12289 "bVisible": true, 12290 12291 12292 /** 12293 * Developer definable function that is called whenever a cell is created (Ajax source, 12294 * etc) or processed for input (DOM source). This can be used as a compliment to mRender 12295 * allowing you to modify the DOM element (add background colour for example) when the 12296 * element is available. 12297 * @type function 12298 * @param {element} td The TD node that has been created 12299 * @param {*} cellData The Data for the cell 12300 * @param {array|object} rowData The data for the whole row 12301 * @param {int} row The row index for the aoData data store 12302 * @param {int} col The column index for aoColumns 12303 * 12304 * @name DataTable.defaults.column.createdCell 12305 * @dtopt Columns 12306 * 12307 * @example 12308 * $(document).ready( function() { 12309 * $('#example').dataTable( { 12310 * "columnDefs": [ { 12311 * "targets": [3], 12312 * "createdCell": function (td, cellData, rowData, row, col) { 12313 * if ( cellData == "1.7" ) { 12314 * $(td).css('color', 'blue') 12315 * } 12316 * } 12317 * } ] 12318 * }); 12319 * } ); 12320 */ 12321 "fnCreatedCell": null, 12322 12323 12324 /** 12325 * This parameter has been replaced by `data` in DataTables to ensure naming 12326 * consistency. `dataProp` can still be used, as there is backwards 12327 * compatibility in DataTables for this option, but it is strongly 12328 * recommended that you use `data` in preference to `dataProp`. 12329 * @name DataTable.defaults.column.dataProp 12330 */ 12331 12332 12333 /** 12334 * This property can be used to read data from any data source property, 12335 * including deeply nested objects / properties. `data` can be given in a 12336 * number of different ways which effect its behaviour: 12337 * 12338 * * `integer` - treated as an array index for the data source. This is the 12339 * default that DataTables uses (incrementally increased for each column). 12340 * * `string` - read an object property from the data source. There are 12341 * three 'special' options that can be used in the string to alter how 12342 * DataTables reads the data from the source object: 12343 * * `.` - Dotted Javascript notation. Just as you use a `.` in 12344 * Javascript to read from nested objects, so to can the options 12345 * specified in `data`. For example: `browser.version` or 12346 * `browser.name`. If your object parameter name contains a period, use 12347 * `\\` to escape it - i.e. `first\\.name`. 12348 * * `[]` - Array notation. DataTables can automatically combine data 12349 * from and array source, joining the data with the characters provided 12350 * between the two brackets. For example: `name[, ]` would provide a 12351 * comma-space separated list from the source array. If no characters 12352 * are provided between the brackets, the original array source is 12353 * returned. 12354 * * `()` - Function notation. Adding `()` to the end of a parameter will 12355 * execute a function of the name given. For example: `browser()` for a 12356 * simple function on the data source, `browser.version()` for a 12357 * function in a nested property or even `browser().version` to get an 12358 * object property if the function called returns an object. Note that 12359 * function notation is recommended for use in `render` rather than 12360 * `data` as it is much simpler to use as a renderer. 12361 * * `null` - use the original data source for the row rather than plucking 12362 * data directly from it. This action has effects on two other 12363 * initialisation options: 12364 * * `defaultContent` - When null is given as the `data` option and 12365 * `defaultContent` is specified for the column, the value defined by 12366 * `defaultContent` will be used for the cell. 12367 * * `render` - When null is used for the `data` option and the `render` 12368 * option is specified for the column, the whole data source for the 12369 * row is used for the renderer. 12370 * * `function` - the function given will be executed whenever DataTables 12371 * needs to set or get the data for a cell in the column. The function 12372 * takes three parameters: 12373 * * Parameters: 12374 * * `{array|object}` The data source for the row 12375 * * `{string}` The type call data requested - this will be 'set' when 12376 * setting data or 'filter', 'display', 'type', 'sort' or undefined 12377 * when gathering data. Note that when `undefined` is given for the 12378 * type DataTables expects to get the raw data for the object back< 12379 * * `{*}` Data to set when the second parameter is 'set'. 12380 * * Return: 12381 * * The return value from the function is not required when 'set' is 12382 * the type of call, but otherwise the return is what will be used 12383 * for the data requested. 12384 * 12385 * Note that `data` is a getter and setter option. If you just require 12386 * formatting of data for output, you will likely want to use `render` which 12387 * is simply a getter and thus simpler to use. 12388 * 12389 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The 12390 * name change reflects the flexibility of this property and is consistent 12391 * with the naming of mRender. If 'mDataProp' is given, then it will still 12392 * be used by DataTables, as it automatically maps the old name to the new 12393 * if required. 12394 * 12395 * @type string|int|function|null 12396 * @default null <i>Use automatically calculated column index</i> 12397 * 12398 * @name DataTable.defaults.column.data 12399 * @dtopt Columns 12400 * 12401 * @example 12402 * // Read table data from objects 12403 * // JSON structure for each row: 12404 * // { 12405 * // "engine": {value}, 12406 * // "browser": {value}, 12407 * // "platform": {value}, 12408 * // "version": {value}, 12409 * // "grade": {value} 12410 * // } 12411 * $(document).ready( function() { 12412 * $('#example').dataTable( { 12413 * "ajaxSource": "sources/objects.txt", 12414 * "columns": [ 12415 * { "data": "engine" }, 12416 * { "data": "browser" }, 12417 * { "data": "platform" }, 12418 * { "data": "version" }, 12419 * { "data": "grade" } 12420 * ] 12421 * } ); 12422 * } ); 12423 * 12424 * @example 12425 * // Read information from deeply nested objects 12426 * // JSON structure for each row: 12427 * // { 12428 * // "engine": {value}, 12429 * // "browser": {value}, 12430 * // "platform": { 12431 * // "inner": {value} 12432 * // }, 12433 * // "details": [ 12434 * // {value}, {value} 12435 * // ] 12436 * // } 12437 * $(document).ready( function() { 12438 * $('#example').dataTable( { 12439 * "ajaxSource": "sources/deep.txt", 12440 * "columns": [ 12441 * { "data": "engine" }, 12442 * { "data": "browser" }, 12443 * { "data": "platform.inner" }, 12444 * { "data": "details.0" }, 12445 * { "data": "details.1" } 12446 * ] 12447 * } ); 12448 * } ); 12449 * 12450 * @example 12451 * // Using `data` as a function to provide different information for 12452 * // sorting, filtering and display. In this case, currency (price) 12453 * $(document).ready( function() { 12454 * $('#example').dataTable( { 12455 * "columnDefs": [ { 12456 * "targets": [ 0 ], 12457 * "data": function ( source, type, val ) { 12458 * if (type === 'set') { 12459 * source.price = val; 12460 * // Store the computed dislay and filter values for efficiency 12461 * source.price_display = val=="" ? "" : "$"+numberFormat(val); 12462 * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val; 12463 * return; 12464 * } 12465 * else if (type === 'display') { 12466 * return source.price_display; 12467 * } 12468 * else if (type === 'filter') { 12469 * return source.price_filter; 12470 * } 12471 * // 'sort', 'type' and undefined all just use the integer 12472 * return source.price; 12473 * } 12474 * } ] 12475 * } ); 12476 * } ); 12477 * 12478 * @example 12479 * // Using default content 12480 * $(document).ready( function() { 12481 * $('#example').dataTable( { 12482 * "columnDefs": [ { 12483 * "targets": [ 0 ], 12484 * "data": null, 12485 * "defaultContent": "Click to edit" 12486 * } ] 12487 * } ); 12488 * } ); 12489 * 12490 * @example 12491 * // Using array notation - outputting a list from an array 12492 * $(document).ready( function() { 12493 * $('#example').dataTable( { 12494 * "columnDefs": [ { 12495 * "targets": [ 0 ], 12496 * "data": "name[, ]" 12497 * } ] 12498 * } ); 12499 * } ); 12500 * 12501 */ 12502 "mData": null, 12503 12504 12505 /** 12506 * This property is the rendering partner to `data` and it is suggested that 12507 * when you want to manipulate data for display (including filtering, 12508 * sorting etc) without altering the underlying data for the table, use this 12509 * property. `render` can be considered to be the the read only companion to 12510 * `data` which is read / write (then as such more complex). Like `data` 12511 * this option can be given in a number of different ways to effect its 12512 * behaviour: 12513 * 12514 * * `integer` - treated as an array index for the data source. This is the 12515 * default that DataTables uses (incrementally increased for each column). 12516 * * `string` - read an object property from the data source. There are 12517 * three 'special' options that can be used in the string to alter how 12518 * DataTables reads the data from the source object: 12519 * * `.` - Dotted Javascript notation. Just as you use a `.` in 12520 * Javascript to read from nested objects, so to can the options 12521 * specified in `data`. For example: `browser.version` or 12522 * `browser.name`. If your object parameter name contains a period, use 12523 * `\\` to escape it - i.e. `first\\.name`. 12524 * * `[]` - Array notation. DataTables can automatically combine data 12525 * from and array source, joining the data with the characters provided 12526 * between the two brackets. For example: `name[, ]` would provide a 12527 * comma-space separated list from the source array. If no characters 12528 * are provided between the brackets, the original array source is 12529 * returned. 12530 * * `()` - Function notation. Adding `()` to the end of a parameter will 12531 * execute a function of the name given. For example: `browser()` for a 12532 * simple function on the data source, `browser.version()` for a 12533 * function in a nested property or even `browser().version` to get an 12534 * object property if the function called returns an object. 12535 * * `object` - use different data for the different data types requested by 12536 * DataTables ('filter', 'display', 'type' or 'sort'). The property names 12537 * of the object is the data type the property refers to and the value can 12538 * defined using an integer, string or function using the same rules as 12539 * `render` normally does. Note that an `_` option _must_ be specified. 12540 * This is the default value to use if you haven't specified a value for 12541 * the data type requested by DataTables. 12542 * * `function` - the function given will be executed whenever DataTables 12543 * needs to set or get the data for a cell in the column. The function 12544 * takes three parameters: 12545 * * Parameters: 12546 * * {array|object} The data source for the row (based on `data`) 12547 * * {string} The type call data requested - this will be 'filter', 12548 * 'display', 'type' or 'sort'. 12549 * * {array|object} The full data source for the row (not based on 12550 * `data`) 12551 * * Return: 12552 * * The return value from the function is what will be used for the 12553 * data requested. 12554 * 12555 * @type string|int|function|object|null 12556 * @default null Use the data source value. 12557 * 12558 * @name DataTable.defaults.column.render 12559 * @dtopt Columns 12560 * 12561 * @example 12562 * // Create a comma separated list from an array of objects 12563 * $(document).ready( function() { 12564 * $('#example').dataTable( { 12565 * "ajaxSource": "sources/deep.txt", 12566 * "columns": [ 12567 * { "data": "engine" }, 12568 * { "data": "browser" }, 12569 * { 12570 * "data": "platform", 12571 * "render": "[, ].name" 12572 * } 12573 * ] 12574 * } ); 12575 * } ); 12576 * 12577 * @example 12578 * // Execute a function to obtain data 12579 * $(document).ready( function() { 12580 * $('#example').dataTable( { 12581 * "columnDefs": [ { 12582 * "targets": [ 0 ], 12583 * "data": null, // Use the full data source object for the renderer's source 12584 * "render": "browserName()" 12585 * } ] 12586 * } ); 12587 * } ); 12588 * 12589 * @example 12590 * // As an object, extracting different data for the different types 12591 * // This would be used with a data source such as: 12592 * // { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" } 12593 * // Here the `phone` integer is used for sorting and type detection, while `phone_filter` 12594 * // (which has both forms) is used for filtering for if a user inputs either format, while 12595 * // the formatted phone number is the one that is shown in the table. 12596 * $(document).ready( function() { 12597 * $('#example').dataTable( { 12598 * "columnDefs": [ { 12599 * "targets": [ 0 ], 12600 * "data": null, // Use the full data source object for the renderer's source 12601 * "render": { 12602 * "_": "phone", 12603 * "filter": "phone_filter", 12604 * "display": "phone_display" 12605 * } 12606 * } ] 12607 * } ); 12608 * } ); 12609 * 12610 * @example 12611 * // Use as a function to create a link from the data source 12612 * $(document).ready( function() { 12613 * $('#example').dataTable( { 12614 * "columnDefs": [ { 12615 * "targets": [ 0 ], 12616 * "data": "download_link", 12617 * "render": function ( data, type, full ) { 12618 * return '<a href="'+data+'">Download</a>'; 12619 * } 12620 * } ] 12621 * } ); 12622 * } ); 12623 */ 12624 "mRender": null, 12625 12626 12627 /** 12628 * Change the cell type created for the column - either TD cells or TH cells. This 12629 * can be useful as TH cells have semantic meaning in the table body, allowing them 12630 * to act as a header for a row (you may wish to add scope='row' to the TH elements). 12631 * @type string 12632 * @default td 12633 * 12634 * @name DataTable.defaults.column.cellType 12635 * @dtopt Columns 12636 * 12637 * @example 12638 * // Make the first column use TH cells 12639 * $(document).ready( function() { 12640 * $('#example').dataTable( { 12641 * "columnDefs": [ { 12642 * "targets": [ 0 ], 12643 * "cellType": "th" 12644 * } ] 12645 * } ); 12646 * } ); 12647 */ 12648 "sCellType": "td", 12649 12650 12651 /** 12652 * Class to give to each cell in this column. 12653 * @type string 12654 * @default <i>Empty string</i> 12655 * 12656 * @name DataTable.defaults.column.class 12657 * @dtopt Columns 12658 * 12659 * @example 12660 * // Using `columnDefs` 12661 * $(document).ready( function() { 12662 * $('#example').dataTable( { 12663 * "columnDefs": [ 12664 * { "class": "my_class", "targets": [ 0 ] } 12665 * ] 12666 * } ); 12667 * } ); 12668 * 12669 * @example 12670 * // Using `columns` 12671 * $(document).ready( function() { 12672 * $('#example').dataTable( { 12673 * "columns": [ 12674 * { "class": "my_class" }, 12675 * null, 12676 * null, 12677 * null, 12678 * null 12679 * ] 12680 * } ); 12681 * } ); 12682 */ 12683 "sClass": "", 12684 12685 /** 12686 * When DataTables calculates the column widths to assign to each column, 12687 * it finds the longest string in each column and then constructs a 12688 * temporary table and reads the widths from that. The problem with this 12689 * is that "mmm" is much wider then "iiii", but the latter is a longer 12690 * string - thus the calculation can go wrong (doing it properly and putting 12691 * it into an DOM object and measuring that is horribly(!) slow). Thus as 12692 * a "work around" we provide this option. It will append its value to the 12693 * text that is found to be the longest string for the column - i.e. padding. 12694 * Generally you shouldn't need this! 12695 * @type string 12696 * @default <i>Empty string<i> 12697 * 12698 * @name DataTable.defaults.column.contentPadding 12699 * @dtopt Columns 12700 * 12701 * @example 12702 * // Using `columns` 12703 * $(document).ready( function() { 12704 * $('#example').dataTable( { 12705 * "columns": [ 12706 * null, 12707 * null, 12708 * null, 12709 * { 12710 * "contentPadding": "mmm" 12711 * } 12712 * ] 12713 * } ); 12714 * } ); 12715 */ 12716 "sContentPadding": "", 12717 12718 12719 /** 12720 * Allows a default value to be given for a column's data, and will be used 12721 * whenever a null data source is encountered (this can be because `data` 12722 * is set to null, or because the data source itself is null). 12723 * @type string 12724 * @default null 12725 * 12726 * @name DataTable.defaults.column.defaultContent 12727 * @dtopt Columns 12728 * 12729 * @example 12730 * // Using `columnDefs` 12731 * $(document).ready( function() { 12732 * $('#example').dataTable( { 12733 * "columnDefs": [ 12734 * { 12735 * "data": null, 12736 * "defaultContent": "Edit", 12737 * "targets": [ -1 ] 12738 * } 12739 * ] 12740 * } ); 12741 * } ); 12742 * 12743 * @example 12744 * // Using `columns` 12745 * $(document).ready( function() { 12746 * $('#example').dataTable( { 12747 * "columns": [ 12748 * null, 12749 * null, 12750 * null, 12751 * { 12752 * "data": null, 12753 * "defaultContent": "Edit" 12754 * } 12755 * ] 12756 * } ); 12757 * } ); 12758 */ 12759 "sDefaultContent": null, 12760 12761 12762 /** 12763 * This parameter is only used in DataTables' server-side processing. It can 12764 * be exceptionally useful to know what columns are being displayed on the 12765 * client side, and to map these to database fields. When defined, the names 12766 * also allow DataTables to reorder information from the server if it comes 12767 * back in an unexpected order (i.e. if you switch your columns around on the 12768 * client-side, your server-side code does not also need updating). 12769 * @type string 12770 * @default <i>Empty string</i> 12771 * 12772 * @name DataTable.defaults.column.name 12773 * @dtopt Columns 12774 * 12775 * @example 12776 * // Using `columnDefs` 12777 * $(document).ready( function() { 12778 * $('#example').dataTable( { 12779 * "columnDefs": [ 12780 * { "name": "engine", "targets": [ 0 ] }, 12781 * { "name": "browser", "targets": [ 1 ] }, 12782 * { "name": "platform", "targets": [ 2 ] }, 12783 * { "name": "version", "targets": [ 3 ] }, 12784 * { "name": "grade", "targets": [ 4 ] } 12785 * ] 12786 * } ); 12787 * } ); 12788 * 12789 * @example 12790 * // Using `columns` 12791 * $(document).ready( function() { 12792 * $('#example').dataTable( { 12793 * "columns": [ 12794 * { "name": "engine" }, 12795 * { "name": "browser" }, 12796 * { "name": "platform" }, 12797 * { "name": "version" }, 12798 * { "name": "grade" } 12799 * ] 12800 * } ); 12801 * } ); 12802 */ 12803 "sName": "", 12804 12805 12806 /** 12807 * Defines a data source type for the ordering which can be used to read 12808 * real-time information from the table (updating the internally cached 12809 * version) prior to ordering. This allows ordering to occur on user 12810 * editable elements such as form inputs. 12811 * @type string 12812 * @default std 12813 * 12814 * @name DataTable.defaults.column.orderDataType 12815 * @dtopt Columns 12816 * 12817 * @example 12818 * // Using `columnDefs` 12819 * $(document).ready( function() { 12820 * $('#example').dataTable( { 12821 * "columnDefs": [ 12822 * { "orderDataType": "dom-text", "targets": [ 2, 3 ] }, 12823 * { "type": "numeric", "targets": [ 3 ] }, 12824 * { "orderDataType": "dom-select", "targets": [ 4 ] }, 12825 * { "orderDataType": "dom-checkbox", "targets": [ 5 ] } 12826 * ] 12827 * } ); 12828 * } ); 12829 * 12830 * @example 12831 * // Using `columns` 12832 * $(document).ready( function() { 12833 * $('#example').dataTable( { 12834 * "columns": [ 12835 * null, 12836 * null, 12837 * { "orderDataType": "dom-text" }, 12838 * { "orderDataType": "dom-text", "type": "numeric" }, 12839 * { "orderDataType": "dom-select" }, 12840 * { "orderDataType": "dom-checkbox" } 12841 * ] 12842 * } ); 12843 * } ); 12844 */ 12845 "sSortDataType": "std", 12846 12847 12848 /** 12849 * The title of this column. 12850 * @type string 12851 * @default null <i>Derived from the 'TH' value for this column in the 12852 * original HTML table.</i> 12853 * 12854 * @name DataTable.defaults.column.title 12855 * @dtopt Columns 12856 * 12857 * @example 12858 * // Using `columnDefs` 12859 * $(document).ready( function() { 12860 * $('#example').dataTable( { 12861 * "columnDefs": [ 12862 * { "title": "My column title", "targets": [ 0 ] } 12863 * ] 12864 * } ); 12865 * } ); 12866 * 12867 * @example 12868 * // Using `columns` 12869 * $(document).ready( function() { 12870 * $('#example').dataTable( { 12871 * "columns": [ 12872 * { "title": "My column title" }, 12873 * null, 12874 * null, 12875 * null, 12876 * null 12877 * ] 12878 * } ); 12879 * } ); 12880 */ 12881 "sTitle": null, 12882 12883 12884 /** 12885 * The type allows you to specify how the data for this column will be 12886 * ordered. Four types (string, numeric, date and html (which will strip 12887 * HTML tags before ordering)) are currently available. Note that only date 12888 * formats understood by Javascript's Date() object will be accepted as type 12889 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string', 12890 * 'numeric', 'date' or 'html' (by default). Further types can be adding 12891 * through plug-ins. 12892 * @type string 12893 * @default null <i>Auto-detected from raw data</i> 12894 * 12895 * @name DataTable.defaults.column.type 12896 * @dtopt Columns 12897 * 12898 * @example 12899 * // Using `columnDefs` 12900 * $(document).ready( function() { 12901 * $('#example').dataTable( { 12902 * "columnDefs": [ 12903 * { "type": "html", "targets": [ 0 ] } 12904 * ] 12905 * } ); 12906 * } ); 12907 * 12908 * @example 12909 * // Using `columns` 12910 * $(document).ready( function() { 12911 * $('#example').dataTable( { 12912 * "columns": [ 12913 * { "type": "html" }, 12914 * null, 12915 * null, 12916 * null, 12917 * null 12918 * ] 12919 * } ); 12920 * } ); 12921 */ 12922 "sType": null, 12923 12924 12925 /** 12926 * Defining the width of the column, this parameter may take any CSS value 12927 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not 12928 * been given a specific width through this interface ensuring that the table 12929 * remains readable. 12930 * @type string 12931 * @default null <i>Automatic</i> 12932 * 12933 * @name DataTable.defaults.column.width 12934 * @dtopt Columns 12935 * 12936 * @example 12937 * // Using `columnDefs` 12938 * $(document).ready( function() { 12939 * $('#example').dataTable( { 12940 * "columnDefs": [ 12941 * { "width": "20%", "targets": [ 0 ] } 12942 * ] 12943 * } ); 12944 * } ); 12945 * 12946 * @example 12947 * // Using `columns` 12948 * $(document).ready( function() { 12949 * $('#example').dataTable( { 12950 * "columns": [ 12951 * { "width": "20%" }, 12952 * null, 12953 * null, 12954 * null, 12955 * null 12956 * ] 12957 * } ); 12958 * } ); 12959 */ 12960 "sWidth": null 12961 }; 12962 12963 _fnHungarianMap( DataTable.defaults.column ); 12964 12965 12966 12967 /** 12968 * DataTables settings object - this holds all the information needed for a 12969 * given table, including configuration, data and current application of the 12970 * table options. DataTables does not have a single instance for each DataTable 12971 * with the settings attached to that instance, but rather instances of the 12972 * DataTable "class" are created on-the-fly as needed (typically by a 12973 * $().dataTable() call) and the settings object is then applied to that 12974 * instance. 12975 * 12976 * Note that this object is related to {@link DataTable.defaults} but this 12977 * one is the internal data store for DataTables's cache of columns. It should 12978 * NOT be manipulated outside of DataTables. Any configuration should be done 12979 * through the initialisation options. 12980 * @namespace 12981 * @todo Really should attach the settings object to individual instances so we 12982 * don't need to create new instances on each $().dataTable() call (if the 12983 * table already exists). It would also save passing oSettings around and 12984 * into every single function. However, this is a very significant 12985 * architecture change for DataTables and will almost certainly break 12986 * backwards compatibility with older installations. This is something that 12987 * will be done in 2.0. 12988 */ 12989 DataTable.models.oSettings = { 12990 /** 12991 * Primary features of DataTables and their enablement state. 12992 * @namespace 12993 */ 12994 "oFeatures": { 12995 12996 /** 12997 * Flag to say if DataTables should automatically try to calculate the 12998 * optimum table and columns widths (true) or not (false). 12999 * Note that this parameter will be set by the initialisation routine. To 13000 * set a default use {@link DataTable.defaults}. 13001 * @type boolean 13002 */ 13003 "bAutoWidth": null, 13004 13005 /** 13006 * Delay the creation of TR and TD elements until they are actually 13007 * needed by a driven page draw. This can give a significant speed 13008 * increase for Ajax source and Javascript source data, but makes no 13009 * difference at all f
13009ro
vendor: 14,836 bytes, lines 13009-13586
13009 DOM and server-side processing tables. 13010 * Note that this parameter will be set by the initialisation routine. To 13011 * set a default use {@link DataTable.defaults}. 13012 * @type boolean 13013 */ 13014 "bDeferRender": null, 13015 13016 /** 13017 * Enable filtering on the table or not. Note that if this is disabled 13018 * then there is no filtering at all on the table, including fnFilter. 13019 * To just remove the filtering input use sDom and remove the 'f' option. 13020 * Note that this parameter will be set by the initialisation routine. To 13021 * set a default use {@link DataTable.defaults}. 13022 * @type boolean 13023 */ 13024 "bFilter": null, 13025 13026 /** 13027 * Table information element (the 'Showing x of y records' div) enable 13028 * flag. 13029 * Note that this parameter will be set by the initialisation routine. To 13030 * set a default use {@link DataTable.defaults}. 13031 * @type boolean 13032 */ 13033 "bInfo": null, 13034 13035 /** 13036 * Present a user control allowing the end user to change the page size 13037 * when pagination is enabled. 13038 * Note that this parameter will be set by the initialisation routine. To 13039 * set a default use {@link DataTable.defaults}. 13040 * @type boolean 13041 */ 13042 "bLengthChange": null, 13043 13044 /** 13045 * Pagination enabled or not. Note that if this is disabled then length 13046 * changing must also be disabled. 13047 * Note that this parameter will be set by the initialisation routine. To 13048 * set a default use {@link DataTable.defaults}. 13049 * @type boolean 13050 */ 13051 "bPaginate": null, 13052 13053 /** 13054 * Processing indicator enable flag whenever DataTables is enacting a 13055 * user request - typically an Ajax request for server-side processing. 13056 * Note that this parameter will be set by the initialisation routine. To 13057 * set a default use {@link DataTable.defaults}. 13058 * @type boolean 13059 */ 13060 "bProcessing": null, 13061 13062 /** 13063 * Server-side processing enabled flag - when enabled DataTables will 13064 * get all data from the server for every draw - there is no filtering, 13065 * sorting or paging done on the client-side. 13066 * Note that this parameter will be set by the initialisation routine. To 13067 * set a default use {@link DataTable.defaults}. 13068 * @type boolean 13069 */ 13070 "bServerSide": null, 13071 13072 /** 13073 * Sorting enablement flag. 13074 * Note that this parameter will be set by the initialisation routine. To 13075 * set a default use {@link DataTable.defaults}. 13076 * @type boolean 13077 */ 13078 "bSort": null, 13079 13080 /** 13081 * Multi-column sorting 13082 * Note that this parameter will be set by the initialisation routine. To 13083 * set a default use {@link DataTable.defaults}. 13084 * @type boolean 13085 */ 13086 "bSortMulti": null, 13087 13088 /** 13089 * Apply a class to the columns which are being sorted to provide a 13090 * visual highlight or not. This can slow things down when enabled since 13091 * there is a lot of DOM interaction. 13092 * Note that this parameter will be set by the initialisation routine. To 13093 * set a default use {@link DataTable.defaults}. 13094 * @type boolean 13095 */ 13096 "bSortClasses": null, 13097 13098 /** 13099 * State saving enablement flag. 13100 * Note that this parameter will be set by the initialisation routine. To 13101 * set a default use {@link DataTable.defaults}. 13102 * @type boolean 13103 */ 13104 "bStateSave": null 13105 }, 13106 13107 13108 /** 13109 * Scrolling settings for a table. 13110 * @namespace 13111 */ 13112 "oScroll": { 13113 /** 13114 * When the table is shorter in height than sScrollY, collapse the 13115 * table container down to the height of the table (when true). 13116 * Note that this parameter will be set by the initialisation routine. To 13117 * set a default use {@link DataTable.defaults}. 13118 * @type boolean 13119 */ 13120 "bCollapse": null, 13121 13122 /** 13123 * Width of the scrollbar for the web-browser's platform. Calculated 13124 * during table initialisation. 13125 * @type int 13126 * @default 0 13127 */ 13128 "iBarWidth": 0, 13129 13130 /** 13131 * Viewport width for horizontal scrolling. Horizontal scrolling is 13132 * disabled if an empty string. 13133 * Note that this parameter will be set by the initialisation routine. To 13134 * set a default use {@link DataTable.defaults}. 13135 * @type string 13136 */ 13137 "sX": null, 13138 13139 /** 13140 * Width to expand the table to when using x-scrolling. Typically you 13141 * should not need to use this. 13142 * Note that this parameter will be set by the initialisation routine. To 13143 * set a default use {@link DataTable.defaults}. 13144 * @type string 13145 * @deprecated 13146 */ 13147 "sXInner": null, 13148 13149 /** 13150 * Viewport height for vertical scrolling. Vertical scrolling is disabled 13151 * if an empty string. 13152 * Note that this parameter will be set by the initialisation routine. To 13153 * set a default use {@link DataTable.defaults}. 13154 * @type string 13155 */ 13156 "sY": null 13157 }, 13158 13159 /** 13160 * Language information for the table. 13161 * @namespace 13162 * @extends DataTable.defaults.oLanguage 13163 */ 13164 "oLanguage": { 13165 /** 13166 * Information callback function. See 13167 * {@link DataTable.defaults.fnInfoCallback} 13168 * @type function 13169 * @default null 13170 */ 13171 "fnInfoCallback": null 13172 }, 13173 13174 /** 13175 * Browser support parameters 13176 * @namespace 13177 */ 13178 "oBrowser": { 13179 /** 13180 * Indicate if the browser incorrectly calculates width:100% inside a 13181 * scrolling element (IE6/7) 13182 * @type boolean 13183 * @default false 13184 */ 13185 "bScrollOversize": false, 13186 13187 /** 13188 * Determine if the vertical scrollbar is on the right or left of the 13189 * scrolling container - needed for rtl language layout, although not 13190 * all browsers move the scrollbar (Safari). 13191 * @type boolean 13192 * @default false 13193 */ 13194 "bScrollbarLeft": false, 13195 13196 /** 13197 * Flag for if `getBoundingClientRect` is fully supported or not 13198 * @type boolean 13199 * @default false 13200 */ 13201 "bBounding": false, 13202 13203 /** 13204 * Browser scrollbar width 13205 * @type integer 13206 * @default 0 13207 */ 13208 "barWidth": 0 13209 }, 13210 13211 13212 "ajax": null, 13213 13214 13215 /** 13216 * Array referencing the nodes which are used for the features. The 13217 * parameters of this object match what is allowed by sDom - i.e. 13218 * <ul> 13219 * <li>'l' - Length changing</li> 13220 * <li>'f' - Filtering input</li> 13221 * <li>'t' - The table!</li> 13222 * <li>'i' - Information</li> 13223 * <li>'p' - Pagination</li> 13224 * <li>'r' - pRocessing</li> 13225 * </ul> 13226 * @type array 13227 * @default [] 13228 */ 13229 "aanFeatures": [], 13230 13231 /** 13232 * Store data information - see {@link DataTable.models.oRow} for detailed 13233 * information. 13234 * @type array 13235 * @default [] 13236 */ 13237 "aoData": [], 13238 13239 /** 13240 * Array of indexes which are in the current display (after filtering etc) 13241 * @type array 13242 * @default [] 13243 */ 13244 "aiDisplay": [], 13245 13246 /** 13247 * Array of indexes for display - no filtering 13248 * @type array 13249 * @default [] 13250 */ 13251 "aiDisplayMaster": [], 13252 13253 /** 13254 * Map of row ids to data indexes 13255 * @type object 13256 * @default {} 13257 */ 13258 "aIds": {}, 13259 13260 /** 13261 * Store information about each column that is in use 13262 * @type array 13263 * @default [] 13264 */ 13265 "aoColumns": [], 13266 13267 /** 13268 * Store information about the table's header 13269 * @type array 13270 * @default [] 13271 */ 13272 "aoHeader": [], 13273 13274 /** 13275 * Store information about the table's footer 13276 * @type array 13277 * @default [] 13278 */ 13279 "aoFooter": [], 13280 13281 /** 13282 * Store the applied global search information in case we want to force a 13283 * research or compare the old search to a new one. 13284 * Note that this parameter will be set by the initialisation routine. To 13285 * set a default use {@link DataTable.defaults}. 13286 * @namespace 13287 * @extends DataTable.models.oSearch 13288 */ 13289 "oPreviousSearch": {}, 13290 13291 /** 13292 * Store the applied search for each column - see 13293 * {@link DataTable.models.oSearch} for the format that is used for the 13294 * filtering information for each column. 13295 * @type array 13296 * @default [] 13297 */ 13298 "aoPreSearchCols": [], 13299 13300 /** 13301 * Sorting that is applied to the table. Note that the inner arrays are 13302 * used in the following manner: 13303 * <ul> 13304 * <li>Index 0 - column number</li> 13305 * <li>Index 1 - current sorting direction</li> 13306 * </ul> 13307 * Note that this parameter will be set by the initialisation routine. To 13308 * set a default use {@link DataTable.defaults}. 13309 * @type array 13310 * @todo These inner arrays should really be objects 13311 */ 13312 "aaSorting": null, 13313 13314 /** 13315 * Sorting that is always applied to the table (i.e. prefixed in front of 13316 * aaSorting). 13317 * Note that this parameter will be set by the initialisation routine. To 13318 * set a default use {@link DataTable.defaults}. 13319 * @type array 13320 * @default [] 13321 */ 13322 "aaSortingFixed": [], 13323 13324 /** 13325 * Classes to use for the striping of a table. 13326 * Note that this parameter will be set by the initialisation routine. To 13327 * set a default use {@link DataTable.defaults}. 13328 * @type array 13329 * @default [] 13330 */ 13331 "asStripeClasses": null, 13332 13333 /** 13334 * If restoring a table - we should restore its striping classes as well 13335 * @type array 13336 * @default [] 13337 */ 13338 "asDestroyStripes": [], 13339 13340 /** 13341 * If restoring a table - we should restore its width 13342 * @type int 13343 * @default 0 13344 */ 13345 "sDestroyWidth": 0, 13346 13347 /** 13348 * Callback functions array for every time a row is inserted (i.e. on a draw). 13349 * @type array 13350 * @default [] 13351 */ 13352 "aoRowCallback": [], 13353 13354 /** 13355 * Callback functions for the header on each draw. 13356 * @type array 13357 * @default [] 13358 */ 13359 "aoHeaderCallback": [], 13360 13361 /** 13362 * Callback function for the footer on each draw. 13363 * @type array 13364 * @default [] 13365 */ 13366 "aoFooterCallback": [], 13367 13368 /** 13369 * Array of callback functions for draw callback functions 13370 * @type array 13371 * @default [] 13372 */ 13373 "aoDrawCallback": [], 13374 13375 /** 13376 * Array of callback functions for row created function 13377 * @type array 13378 * @default [] 13379 */ 13380 "aoRowCreatedCallback": [], 13381 13382 /** 13383 * Callback functions for just before the table is redrawn. A return of 13384 * false will be used to cancel the draw. 13385 * @type array 13386 * @default [] 13387 */ 13388 "aoPreDrawCallback": [], 13389 13390 /** 13391 * Callback functions for when the table has been initialised. 13392 * @type array 13393 * @default [] 13394 */ 13395 "aoInitComplete": [], 13396 13397 13398 /** 13399 * Callbacks for modifying the settings to be stored for state saving, prior to 13400 * saving state. 13401 * @type array 13402 * @default [] 13403 */ 13404 "aoStateSaveParams": [], 13405 13406 /** 13407 * Callbacks for modifying the settings that have been stored for state saving 13408 * prior to using the stored values to restore the state. 13409 * @type array 13410 * @default [] 13411 */ 13412 "aoStateLoadParams": [], 13413 13414 /** 13415 * Callbacks for operating on the settings object once the saved state has been 13416 * loaded 13417 * @type array 13418 * @default [] 13419 */ 13420 "aoStateLoaded": [], 13421 13422 /** 13423 * Cache the table ID for quick access 13424 * @type string 13425 * @default <i>Empty string</i> 13426 */ 13427 "sTableId": "", 13428 13429 /** 13430 * The TABLE node for the main table 13431 * @type node 13432 * @default null 13433 */ 13434 "nTable": null, 13435 13436 /** 13437 * Permanent ref to the thead element 13438 * @type node 13439 * @default null 13440 */ 13441 "nTHead": null, 13442 13443 /** 13444 * Permanent ref to the tfoot element - if it exists 13445 * @type node 13446 * @default null 13447 */ 13448 "nTFoot": null, 13449 13450 /** 13451 * Permanent ref to the tbody element 13452 * @type node 13453 * @default null 13454 */ 13455 "nTBody": null, 13456 13457 /** 13458 * Cache the wrapper node (contains all DataTables controlled elements) 13459 * @type node 13460 * @default null 13461 */ 13462 "nTableWrapper": null, 13463 13464 /** 13465 * Indicate if when using server-side processing the loading of data 13466 * should be deferred until the second draw. 13467 * Note that this parameter will be set by the initialisation routine. To 13468 * set a default use {@link DataTable.defaults}. 13469 * @type boolean 13470 * @default false 13471 */ 13472 "bDeferLoading": false, 13473 13474 /** 13475 * Indicate if all required information has been read in 13476 * @type boolean 13477 * @default false 13478 */ 13479 "bInitialised": false, 13480 13481 /** 13482 * Information about open rows. Each object in the array has the parameters 13483 * 'nTr' and 'nParent' 13484 * @type array 13485 * @default [] 13486 */ 13487 "aoOpenRows": [], 13488 13489 /** 13490 * Dictate the positioning of DataTables' control elements - see 13491 * {@link DataTable.model.oInit.sDom}. 13492 * Note that this parameter will be set by the initialisation routine. To 13493 * set a default use {@link DataTable.defaults}. 13494 * @type string 13495 * @default null 13496 */ 13497 "sDom": null, 13498 13499 /** 13500 * Search delay (in mS) 13501 * @type integer 13502 * @default null 13503 */ 13504 "searchDelay": null, 13505 13506 /** 13507 * Which type of pagination should be used. 13508 * Note that this parameter will be set by the initialisation routine. To 13509 * set a default use {@link DataTable.defaults}. 13510 * @type string 13511 * @default two_button 13512 */ 13513 "sPaginationType": "two_button", 13514 13515 /** 13516 * The state duration (for `stateSave`) in seconds. 13517 * Note that this parameter will be set by the initialisation routine. To 13518 * set a default use {@link DataTable.defaults}. 13519 * @type int 13520 * @default 0 13521 */ 13522 "iStateDuration": 0, 13523 13524 /** 13525 * Array of callback functions for state saving. Each array element is an 13526 * object with the following parameters: 13527 * <ul> 13528 * <li>function:fn - function to call. Takes two parameters, oSettings 13529 * and the JSON string to save that has been thus far created. Returns 13530 * a JSON string to be inserted into a json object 13531 * (i.e. '"param": [ 0, 1, 2]')</li> 13532 * <li>string:sName - name of callback</li> 13533 * </ul> 13534 * @type array 13535 * @default [] 13536 */ 13537 "aoStateSave": [], 13538 13539 /** 13540 * Array of callback functions for state loading. Each array element is an 13541 * object with the following parameters: 13542 * <ul> 13543 * <li>function:fn - function to call. Takes two parameters, oSettings 13544 * and the object stored. May return false to cancel state loading</li> 13545 * <li>string:sName - name of callback</li> 13546 * </ul> 13547 * @type array 13548 * @default [] 13549 */ 13550 "aoStateLoad": [], 13551 13552 /** 13553 * State that was saved. Useful for back reference 13554 * @type object 13555 * @default null 13556 */ 13557 "oSavedState": null, 13558 13559 /** 13560 * State that was loaded. Useful for back reference 13561 * @type object 13562 * @default null 13563 */ 13564 "oLoadedState": null, 13565 13566 /** 13567 * Source url for AJAX data for the table. 13568 * Note that this parameter will be set by the initialisation routine. To 13569 * set a default use {@link DataTable.defaults}. 13570 * @type string 13571 * @default null 13572 */ 13573 "sAjaxSource": null, 13574 13575 /** 13576 * Property from a given object from which to read the table data from. This 13577 * can be an empty string (when not server-side processing), in which case 13578 * it is assumed an an array is given directly. 13579 * Note that this parameter will be set by the initialisation routine. To 13580 * set a default use {@link DataTable.defaults}. 13581 * @type string 13582 */ 13583 "sAjaxDataProp": null, 13584 13585 /** 13586 *
13586Note if draw should be blocked while getting data 13587 * @type boolean 13588 * @default true 13589 */ 13590 "bAjaxDataGet": true, 13591 13592 /** 13593 * The last jQuery XHR object that was used for server-side data gathering. 13594 * This can be used for working with the XHR information in one of the 13595 * callbacks 13596 * @type object 13597 * @default null 13598 */ 13599 "jqXHR": null, 13600 13601 /** 13602 * JSON returned from the server in the last Ajax request 13603 * @type object 13604 * @default undefined 13605 */ 13606 "json": undefined, 13607 13608 /** 13609 * Data submitted as part of the last Ajax request 13610 * @type object 13611 * @default undefined 13612 */ 13613 "oAjaxData": undefined, 13614 13615 /** 13616 * Function to get the server-side data. 13617 * Note that this parameter will be set by the initialisation routine. To 13618 * set a default use {@link DataTable.defaults}. 13619 * @type function 13620 */ 13621 "fnServerData": null, 13622 13623 /** 13624 * Functions which are called prior to sending an Ajax request so extra 13625 * parameters can easily be sent to the server 13626 * @type array 13627 * @default [] 13628 */ 13629 "aoServerParams": [], 13630 13631 /** 13632 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if 13633 * required). 13634 * Note that this parameter will be set by the initialisation routine. To 13635 * set a default use {@link DataTable.defaults}. 13636 * @type string 13637 */ 13638 "sServerMethod": null, 13639 13640 /** 13641 * Format numbers for display. 13642 * Note that this parameter will be set by the initialisation routine. To 13643 * set a default use {@link DataTable.defaults}. 13644 * @type function 13645 */ 13646 "fnFormatNumber": null, 13647 13648 /** 13649 * List of options that can be used for the user selectable length menu. 13650 * Note that this parameter will be set by the initialisation routine. To 13651 * set a default use {@link DataTable.defaults}. 13652 * @type array 13653 * @default [] 13654 */ 13655 "aLengthMenu": null, 13656 13657 /** 13658 * Counter for the draws that the table does. Also used as a tracker for 13659 * server-side processing 13660 * @type int 13661 * @default 0 13662 */ 13663 "iDraw": 0, 13664 13665 /** 13666 * Indicate if a redraw is being done - useful for Ajax 13667 * @type boolean 13668 * @default false 13669 */ 13670 "bDrawing": false, 13671 13672 /** 13673 * Draw index (iDraw) of the last error when parsing the returned data 13674 * @type int 13675 * @default -1 13676 */ 13677 "iDrawError": -1, 13678 13679 /** 13680 * Paging display length 13681 * @type int 13682 * @default 10 13683 */ 13684 "_iDisplayLength": 10, 13685 13686 /** 13687 * Paging start point - aiDisplay index 13688 * @type int 13689 * @default 0 13690 */ 13691 "_iDisplayStart": 0, 13692 13693 /** 13694 * Server-side processing - number of records in the result set 13695 * (i.e. before filtering), Use fnRecordsTotal rather than 13696 * this property to get the value of the number of records, regardless of 13697 * the server-side processing setting. 13698 * @type int 13699 * @default 0 13700 * @private 13701 */ 13702 "_iRecordsTotal": 0, 13703 13704 /** 13705 * Server-side processing - number of records in the current display set 13706 * (i.e. after filtering). Use fnRecordsDisplay rather than 13707 * this property to get the value of the number of records, regardless of 13708 * the server-side processing setting. 13709 * @type boolean 13710 * @default 0 13711 * @private 13712 */ 13713 "_iRecordsDisplay": 0, 13714 13715 /** 13716 * The classes to use for the table 13717 * @type object 13718 * @default {} 13719 */
vendor: 3,548 bytes, lines 13720-13875
13720 "oClasses": {}, 13721 13722 /** 13723 * Flag attached to the settings object so you can check in the draw 13724 * callback if filtering has been done in the draw. Deprecated in favour of 13725 * events. 13726 * @type boolean 13727 * @default false 13728 * @deprecated 13729 */ 13730 "bFiltered": false, 13731 13732 /** 13733 * Flag attached to the settings object so you can check in the draw 13734 * callback if sorting has been done in the draw. Deprecated in favour of 13735 * events. 13736 * @type boolean 13737 * @default false 13738 * @deprecated 13739 */ 13740 "bSorted": false, 13741 13742 /** 13743 * Indicate that if multiple rows are in the header and there is more than 13744 * one unique cell per column, if the top one (true) or bottom one (false) 13745 * should be used for sorting / title by DataTables. 13746 * Note that this parameter will be set by the initialisation routine. To 13747 * set a default use {@link DataTable.defaults}. 13748 * @type boolean 13749 */ 13750 "bSortCellsTop": null, 13751 13752 /** 13753 * Initialisation object that is used for the table 13754 * @type object 13755 * @default null 13756 */ 13757 "oInit": null, 13758 13759 /** 13760 * Destroy callback functions - for plug-ins to attach themselves to the 13761 * destroy so they can clean up markup and events. 13762 * @type array 13763 * @default [] 13764 */ 13765 "aoDestroyCallback": [], 13766 13767 13768 /** 13769 * Get the number of records in the current record set, before filtering 13770 * @type function 13771 */ 13772 "fnRecordsTotal": function () 13773 { 13774 return _fnDataSource( this ) == 'ssp' ? 13775 this._iRecordsTotal * 1 : 13776 this.aiDisplayMaster.length; 13777 }, 13778 13779 /** 13780 * Get the number of records in the current record set, after filtering 13781 * @type function 13782 */ 13783 "fnRecordsDisplay": function () 13784 { 13785 return _fnDataSource( this ) == 'ssp' ? 13786 this._iRecordsDisplay * 1 : 13787 this.aiDisplay.length; 13788 }, 13789 13790 /** 13791 * Get the display end point - aiDisplay index 13792 * @type function 13793 */ 13794 "fnDisplayEnd": function () 13795 { 13796 var 13797 len = this._iDisplayLength, 13798 start = this._iDisplayStart, 13799 calc = start + len, 13800 records = this.aiDisplay.length, 13801 features = this.oFeatures, 13802 paginate = features.bPaginate; 13803 13804 if ( features.bServerSide ) { 13805 return paginate === false || len === -1 ? 13806 start + records : 13807 Math.min( start+len, this._iRecordsDisplay ); 13808 } 13809 else { 13810 return ! paginate || calc>records || len===-1 ? 13811 records : 13812 calc; 13813 } 13814 }, 13815 13816 /** 13817 * The DataTables object for this table 13818 * @type object 13819 * @default null 13820 */ 13821 "oInstance": null, 13822 13823 /** 13824 * Unique identifier for each instance of the DataTables object. If there 13825 * is an ID on the table node, then it takes that value, otherwise an 13826 * incrementing internal counter is used. 13827 * @type string 13828 * @default null 13829 */ 13830 "sInstance": null, 13831 13832 /** 13833 * tabindex attribute value that is added to DataTables control elements, allowing 13834 * keyboard navigation of the table and its controls. 13835 */ 13836 "iTabIndex": 0, 13837 13838 /** 13839 * DIV container for the footer scrolling table if scrolling 13840 */ 13841 "nScrollHead": null, 13842 13843 /** 13844 * DIV container for the footer scrolling table if scrolling 13845 */ 13846 "nScrollFoot": null, 13847 13848 /** 13849 * Last applied sort 13850 * @type array 13851 * @default [] 13852 */ 13853 "aLastSort": [], 13854 13855 /** 13856 * Stored plug-in instances 13857 * @type object 13858 * @default {} 13859 */ 13860 "oPlugins": {}, 13861 13862 /** 13863 * Function used to get a row's id from the row's data 13864 * @type function 13865 * @default null 13866 */ 13867 "rowIdFn": null, 13868 13869 /** 13870 * Data location where to store a row's id 13871 * @type string 13872 * @default null 13873 */ 13874 "rowId": null 13875 };
vendor: 16,410 bytes, lines 13876-14374
13876 13877 /** 13878 * Extension object for DataTables that is used to provide all extension 13879 * options. 13880 * 13881 * Note that the `DataTable.ext` object is available through 13882 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is 13883 * also aliased to `jQuery.fn.dataTableExt` for historic reasons. 13884 * @namespace 13885 * @extends DataTable.models.ext 13886 */ 13887 13888 13889 /** 13890 * DataTables extensions 13891 * 13892 * This namespace acts as a collection area for plug-ins that can be used to 13893 * extend DataTables capabilities. Indeed many of the build in methods 13894 * use this method to provide their own capabilities (sorting methods for 13895 * example). 13896 * 13897 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy 13898 * reasons 13899 * 13900 * @namespace 13901 */ 13902 DataTable.ext = _ext = { 13903 /** 13904 * Buttons. For use with the Buttons extension for DataTables. This is 13905 * defined here so other extensions can define buttons regardless of load 13906 * order. It is _not_ used by DataTables core. 13907 * 13908 * @type object 13909 * @default {} 13910 */ 13911 buttons: {}, 13912 13913 13914 /** 13915 * Element class names 13916 * 13917 * @type object 13918 * @default {} 13919 */ 13920 classes: {}, 13921 13922 13923 /** 13924 * DataTables build type (expanded by the download builder) 13925 * 13926 * @type string 13927 */ 13928 builder: "-source-", 13929 13930 13931 /** 13932 * Error reporting. 13933 * 13934 * How should DataTables report an error. Can take the value 'alert', 13935 * 'throw', 'none' or a function. 13936 * 13937 * @type string|function 13938 * @default alert 13939 */ 13940 errMode: "alert", 13941 13942 13943 /** 13944 * Feature plug-ins. 13945 * 13946 * This is an array of objects which describe the feature plug-ins that are 13947 * available to DataTables. These feature plug-ins are then available for 13948 * use through the `dom` initialisation option. 13949 * 13950 * Each feature plug-in is described by an object which must have the 13951 * following properties: 13952 * 13953 * * `fnInit` - function that is used to initialise the plug-in, 13954 * * `cFeature` - a character so the feature can be enabled by the `dom` 13955 * instillation option. This is case sensitive. 13956 * 13957 * The `fnInit` function has the following input parameters: 13958 * 13959 * 1. `{object}` DataTables settings object: see 13960 * {@link DataTable.models.oSettings} 13961 * 13962 * And the following return is expected: 13963 * 13964 * * {node|null} The element which contains your feature. Note that the 13965 * return may also be void if your plug-in does not require to inject any 13966 * DOM elements into DataTables control (`dom`) - for example this might 13967 * be useful when developing a plug-in which allows table control via 13968 * keyboard entry 13969 * 13970 * @type array 13971 * 13972 * @example 13973 * $.fn.dataTable.ext.features.push( { 13974 * "fnInit": function( oSettings ) { 13975 * return new TableTools( { "oDTSettings": oSettings } ); 13976 * }, 13977 * "cFeature": "T" 13978 * } ); 13979 */ 13980 feature: [], 13981 13982 13983 /** 13984 * Row searching. 13985 * 13986 * This method of searching is complimentary to the default type based 13987 * searching, and a lot more comprehensive as it allows you complete control 13988 * over the searching logic. Each element in this array is a function 13989 * (parameters described below) that is called for every row in the table, 13990 * and your logic decides if it should be included in the searching data set 13991 * or not. 13992 * 13993 * Searching functions have the following input parameters: 13994 * 13995 * 1. `{object}` DataTables settings object: see 13996 * {@link DataTable.models.oSettings} 13997 * 2. `{array|object}` Data for the row to be processed (same as the 13998 * original format that was passed in as the data source, or an array 13999 * from a DOM data source 14000 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which 14001 * can be useful to retrieve the `TR` element if you need DOM interaction. 14002 * 14003 * And the following return is expected: 14004 * 14005 * * {boolean} Include the row in the searched result set (true) or not 14006 * (false) 14007 * 14008 * Note that as with the main search ability in DataTables, technically this 14009 * is "filtering", since it is subtractive. However, for consistency in 14010 * naming we call it searching here. 14011 * 14012 * @type array 14013 * @default [] 14014 * 14015 * @example 14016 * // The following example shows custom search being applied to the 14017 * // fourth column (i.e. the data[3] index) based on two input values 14018 * // from the end-user, matching the data in a certain range. 14019 * $.fn.dataTable.ext.search.push( 14020 * function( settings, data, dataIndex ) { 14021 * var min = document.getElementById('min').value * 1; 14022 * var max = document.getElementById('max').value * 1; 14023 * var version = data[3] == "-" ? 0 : data[3]*1; 14024 * 14025 * if ( min == "" && max == "" ) { 14026 * return true; 14027 * } 14028 * else if ( min == "" && version < max ) { 14029 * return true; 14030 * } 14031 * else if ( min < version && "" == max ) { 14032 * return true; 14033 * } 14034 * else if ( min < version && version < max ) { 14035 * return true; 14036 * } 14037 * return false; 14038 * } 14039 * ); 14040 */ 14041 search: [], 14042 14043 14044 /** 14045 * Selector extensions 14046 * 14047 * The `selector` option can be used to extend the options available for the 14048 * selector modifier options (`selector-modifier` object data type) that 14049 * each of the three built in selector types offer (row, column and cell + 14050 * their plural counterparts). For example the Select extension uses this 14051 * mechanism to provide an option to select only rows, columns and cells 14052 * that have been marked as selected by the end user (`{selected: true}`), 14053 * which can be used in conjunction with the existing built in selector 14054 * options. 14055 * 14056 * Each property is an array to which functions can be pushed. The functions 14057 * take three attributes: 14058 * 14059 * * Settings object for the host table 14060 * * Options object (`selector-modifier` object type) 14061 * * Array of selected item indexes 14062 * 14063 * The return is an array of the resulting item indexes after the custom 14064 * selector has been applied. 14065 * 14066 * @type object 14067 */ 14068 selector: { 14069 cell: [], 14070 column: [], 14071 row: [] 14072 }, 14073 14074 14075 /** 14076 * Internal functions, exposed for used in plug-ins. 14077 * 14078 * Please note that you should not need to use the internal methods for 14079 * anything other than a plug-in (and even then, try to avoid if possible). 14080 * The internal function may change between releases. 14081 * 14082 * @type object 14083 * @default {} 14084 */ 14085 internal: {}, 14086 14087 14088 /** 14089 * Legacy configuration options. Enable and disable legacy options that 14090 * are available in DataTables. 14091 * 14092 * @type object 14093 */ 14094 legacy: { 14095 /** 14096 * Enable / disable DataTables 1.9 compatible server-side processing 14097 * requests 14098 * 14099 * @type boolean 14100 * @default null 14101 */ 14102 ajax: null 14103 }, 14104 14105 14106 /** 14107 * Pagination plug-in methods. 14108 * 14109 * Each entry in this object is a function and defines which buttons should 14110 * be shown by the pagination rendering method that is used for the table: 14111 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the 14112 * buttons are displayed in the document, while the functions here tell it 14113 * what buttons to display. This is done by returning an array of button 14114 * descriptions (what each button will do). 14115 * 14116 * Pagination types (the four built in options and any additional plug-in 14117 * options defined here) can be used through the `paginationType` 14118 * initialisation parameter. 14119 * 14120 * The functions defined take two parameters: 14121 * 14122 * 1. `{int} page` The current page index 14123 * 2. `{int} pages` The number of pages in the table 14124 * 14125 * Each function is expected to return an array where each element of the 14126 * array can be one of: 14127 * 14128 * * `first` - Jump to first page when activated 14129 * * `last` - Jump to last page when activated 14130 * * `previous` - Show previous page when activated 14131 * * `next` - Show next page when activated 14132 * * `{int}` - Show page of the index given 14133 * * `{array}` - A nested array containing the above elements to add a 14134 * containing 'DIV' element (might be useful for styling). 14135 * 14136 * Note that DataTables v1.9- used this object slightly differently whereby 14137 * an object with two functions would be defined for each plug-in. That 14138 * ability is still supported by DataTables 1.10+ to provide backwards 14139 * compatibility, but this option of use is now decremented and no longer 14140 * documented in DataTables 1.10+. 14141 * 14142 * @type object 14143 * @default {} 14144 * 14145 * @example 14146 * // Show previous, next and current page buttons only 14147 * $.fn.dataTableExt.oPagination.current = function ( page, pages ) { 14148 * return [ 'previous', page, 'next' ]; 14149 * }; 14150 */ 14151 pager: {}, 14152 14153 14154 renderer: { 14155 pageButton: {}, 14156 header: {} 14157 }, 14158 14159 14160 /** 14161 * Ordering plug-ins - custom data source 14162 * 14163 * The extension options for ordering of data available here is complimentary 14164 * to the default type based ordering that DataTables typically uses. It 14165 * allows much greater control over the the data that is being used to 14166 * order a column, but is necessarily therefore more complex. 14167 * 14168 * This type of ordering is useful if you want to do ordering based on data 14169 * live from the DOM (for example the contents of an 'input' element) rather 14170 * than just the static string that DataTables knows of. 14171 * 14172 * The way these plug-ins work is that you create an array of the values you 14173 * wish to be ordering for the column in question and then return that 14174 * array. The data in the array much be in the index order of the rows in 14175 * the table (not the currently ordering order!). Which order data gathering 14176 * function is run here depends on the `dt-init columns.orderDataType` 14177 * parameter that is used for the column (if any). 14178 * 14179 * The functions defined take two parameters: 14180 * 14181 * 1. `{object}` DataTables settings object: see 14182 * {@link DataTable.models.oSettings} 14183 * 2. `{int}` Target column index 14184 * 14185 * Each function is expected to return an array: 14186 * 14187 * * `{array}` Data for the column to be ordering upon 14188 * 14189 * @type array 14190 * 14191 * @example 14192 * // Ordering using `input` node values 14193 * $.fn.dataTable.ext.order['dom-text'] = function ( settings, col ) 14194 * { 14195 * return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) { 14196 * return $('input', td).val(); 14197 * } ); 14198 * } 14199 */ 14200 order: {}, 14201 14202 14203 /** 14204 * Type based plug-ins. 14205 * 14206 * Each column in DataTables has a type assigned to it, either by automatic 14207 * detection or by direct assignment using the `type` option for the column. 14208 * The type of a column will effect how it is ordering and search (plug-ins 14209 * can also make use of the column type if required). 14210 * 14211 * @namespace 14212 */ 14213 type: { 14214 /** 14215 * Type detection functions. 14216 * 14217 * The functions defined in this object are used to automatically detect 14218 * a column's type, making initialisation of DataTables super easy, even 14219 * when complex data is in the table. 14220 * 14221 * The functions defined take two parameters: 14222 * 14223 * 1. `{*}` Data from the column cell to be analysed 14224 * 2. `{settings}` DataTables settings object. This can be used to 14225 * perform context specific type detection - for example detection 14226 * based on language settings such as using a comma for a decimal 14227 * place. Generally speaking the options from the settings will not 14228 * be required 14229 * 14230 * Each function is expected to return: 14231 * 14232 * * `{string|null}` Data type detected, or null if unknown (and thus 14233 * pass it on to the other type detection functions. 14234 * 14235 * @type array 14236 * 14237 * @example 14238 * // Currency type detection plug-in: 14239 * $.fn.dataTable.ext.type.detect.push( 14240 * function ( data, settings ) { 14241 * // Check the numeric part 14242 * if ( ! data.substring(1).match(/[0-9]/) ) { 14243 * return null; 14244 * } 14245 * 14246 * // Check prefixed by currency 14247 * if ( data.charAt(0) == '$' || data.charAt(0) == '£' ) { 14248 * return 'currency'; 14249 * } 14250 * return null; 14251 * } 14252 * ); 14253 */ 14254 detect: [], 14255 14256 14257 /** 14258 * Type based search formatting. 14259 * 14260 * The type based searching functions can be used to pre-format the 14261 * data to be search on. For example, it can be used to strip HTML 14262 * tags or to de-format telephone numbers for numeric only searching. 14263 * 14264 * Note that is a search is not defined for a column of a given type, 14265 * no search formatting will be performed. 14266 * 14267 * Pre-processing of searching data plug-ins - When you assign the sType 14268 * for a column (or have it automatically detected for you by DataTables 14269 * or a type detection plug-in), you will typically be using this for 14270 * custom sorting, but it can also be used to provide custom searching 14271 * by allowing you to pre-processing the data and returning the data in 14272 * the format that should be searched upon. This is done by adding 14273 * functions this object with a parameter name which matches the sType 14274 * for that target column. This is the corollary of <i>afnSortData</i> 14275 * for searching data. 14276 * 14277 * The functions defined take a single parameter: 14278 * 14279 * 1. `{*}` Data from the column cell to be prepared for searching 14280 * 14281 * Each function is expected to return: 14282 * 14283 * * `{string|null}` Formatted string that will be used for the searching. 14284 * 14285 * @type object 14286 * @default {} 14287 * 14288 * @example 14289 * $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) { 14290 * return d.replace(/\n/g," ").replace( /<.*?>/g, "" ); 14291 * } 14292 */ 14293 search: {}, 14294 14295 14296 /** 14297 * Type based ordering. 14298 * 14299 * The column type tells DataTables what ordering to apply to the table 14300 * when a column is sorted upon. The order for each type that is defined, 14301 * is defined by the functions available in this object. 14302 * 14303 * Each ordering option can be described by three properties added to 14304 * this object: 14305 * 14306 * * `{type}-pre` - Pre-formatting function 14307 * * `{type}-asc` - Ascending order function 14308 * * `{type}-desc` - Descending order function 14309 * 14310 * All three can be used together, only `{type}-pre` or only 14311 * `{type}-asc` and `{type}-desc` together. It is generally recommended 14312 * that only `{type}-pre` is used, as this provides the optimal 14313 * implementation in terms of speed, although the others are provided 14314 * for compatibility with existing Javascript sort functions. 14315 * 14316 * `{type}-pre`: Functions defined take a single parameter: 14317 * 14318 * 1. `{*}` Data from the column cell to be prepared for ordering 14319 * 14320 * And return: 14321 * 14322 * * `{*}` Data to be sorted upon 14323 * 14324 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort 14325 * functions, taking two parameters: 14326 * 14327 * 1. `{*}` Data to compare to the second parameter 14328 * 2. `{*}` Data to compare to the first parameter 14329 * 14330 * And returning: 14331 * 14332 * * `{*}` Ordering match: <0 if first parameter should be sorted lower 14333 * than the second parameter, ===0 if the two parameters are equal and 14334 * >0 if the first parameter should be sorted height than the second 14335 * parameter. 14336 * 14337 * @type object 14338 * @default {} 14339 * 14340 * @example 14341 * // Numeric ordering of formatted numbers with a pre-formatter 14342 * $.extend( $.fn.dataTable.ext.type.order, { 14343 * "string-pre": function(x) { 14344 * a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" ); 14345 * return parseFloat( a ); 14346 * } 14347 * } ); 14348 * 14349 * @example 14350 * // Case-sensitive string ordering, with no pre-formatting method 14351 * $.extend( $.fn.dataTable.ext.order, { 14352 * "string-case-asc": function(x,y) { 14353 * return ((x < y) ? -1 : ((x > y) ? 1 : 0)); 14354 * }, 14355 * "string-case-desc": function(x,y) { 14356 * return ((x < y) ? 1 : ((x > y) ? -1 : 0)); 14357 * } 14358 * } ); 14359 */ 14360 order: {} 14361 }, 14362 14363 /** 14364 * Unique DataTables instance counter 14365 * 14366 * @type int 14367 * @private 14368 */ 14369 _unique: 0, 14370 14371 14372 // 14373 // Depreciated 14374 // The following properties are retained for backwards compatib
vendor: 25,973 bytes, lines 14374-15289
14374lity only. 14375 // The should not be used in new projects and will be removed in a future 14376 // version 14377 // 14378 14379 /** 14380 * Version check function. 14381 * @type function 14382 * @depreciated Since 1.10 14383 */ 14384 fnVersionCheck: DataTable.fnVersionCheck, 14385 14386 14387 /** 14388 * Index for what 'this' index API functions should use 14389 * @type int 14390 * @deprecated Since v1.10 14391 */ 14392 iApiIndex: 0, 14393 14394 14395 /** 14396 * jQuery UI class container 14397 * @type object 14398 * @deprecated Since v1.10 14399 */ 14400 oJUIClasses: {}, 14401 14402 14403 /** 14404 * Software version 14405 * @type string 14406 * @deprecated Since v1.10 14407 */ 14408 sVersion: DataTable.version 14409 }; 14410 14411 14412 // 14413 // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts 14414 // 14415 $.extend( _ext, { 14416 afnFiltering: _ext.search, 14417 aTypes: _ext.type.detect, 14418 ofnSearch: _ext.type.search, 14419 oSort: _ext.type.order, 14420 afnSortData: _ext.order, 14421 aoFeatures: _ext.feature, 14422 oApi: _ext.internal, 14423 oStdClasses: _ext.classes, 14424 oPagination: _ext.pager 14425 } ); 14426 14427 14428 $.extend( DataTable.ext.classes, { 14429 "sTable": "dataTable", 14430 "sNoFooter": "no-footer", 14431 14432 /* Paging buttons */ 14433 "sPageButton": "paginate_button", 14434 "sPageButtonActive": "current", 14435 "sPageButtonDisabled": "disabled", 14436 14437 /* Striping classes */ 14438 "sStripeOdd": "odd", 14439 "sStripeEven": "even", 14440 14441 /* Empty row */ 14442 "sRowEmpty": "dataTables_empty", 14443 14444 /* Features */ 14445 "sWrapper": "dataTables_wrapper", 14446 "sFilter": "dataTables_filter", 14447 "sInfo": "dataTables_info", 14448 "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */ 14449 "sLength": "dataTables_length", 14450 "sProcessing": "dataTables_processing", 14451 14452 /* Sorting */ 14453 "sSortAsc": "sorting_asc", 14454 "sSortDesc": "sorting_desc", 14455 "sSortable": "sorting", /* Sortable in both directions */ 14456 "sSortableAsc": "sorting_asc_disabled", 14457 "sSortableDesc": "sorting_desc_disabled", 14458 "sSortableNone": "sorting_disabled", 14459 "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */ 14460 14461 /* Filtering */ 14462 "sFilterInput": "", 14463 14464 /* Page length */ 14465 "sLengthSelect": "", 14466 14467 /* Scrolling */ 14468 "sScrollWrapper": "dataTables_scroll", 14469 "sScrollHead": "dataTables_scrollHead", 14470 "sScrollHeadInner": "dataTables_scrollHeadInner", 14471 "sScrollBody": "dataTables_scrollBody", 14472 "sScrollFoot": "dataTables_scrollFoot", 14473 "sScrollFootInner": "dataTables_scrollFootInner", 14474 14475 /* Misc */ 14476 "sHeaderTH": "", 14477 "sFooterTH": "", 14478 14479 // Deprecated 14480 "sSortJUIAsc": "", 14481 "sSortJUIDesc": "", 14482 "sSortJUI": "", 14483 "sSortJUIAscAllowed": "", 14484 "sSortJUIDescAllowed": "", 14485 "sSortJUIWrapper": "", 14486 "sSortIcon": "", 14487 "sJUIHeader": "", 14488 "sJUIFooter": "" 14489 } ); 14490 14491 14492 var extPagination = DataTable.ext.pager; 14493 14494 function _numbers ( page, pages ) { 14495 var 14496 numbers = [], 14497 buttons = extPagination.numbers_length, 14498 half = Math.floor( buttons / 2 ), 14499 i = 1; 14500 14501 if ( pages <= buttons ) { 14502 numbers = _range( 0, pages ); 14503 } 14504 else if ( page <= half ) { 14505 numbers = _range( 0, buttons-2 ); 14506 numbers.push( 'ellipsis' ); 14507 numbers.push( pages-1 ); 14508 } 14509 else if ( page >= pages - 1 - half ) { 14510 numbers = _range( pages-(buttons-2), pages ); 14511 numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6 14512 numbers.splice( 0, 0, 0 ); 14513 } 14514 else { 14515 numbers = _range( page-half+2, page+half-1 ); 14516 numbers.push( 'ellipsis' ); 14517 numbers.push( pages-1 ); 14518 numbers.splice( 0, 0, 'ellipsis' ); 14519 numbers.splice( 0, 0, 0 ); 14520 } 14521 14522 numbers.DT_el = 'span'; 14523 return numbers; 14524 } 14525 14526 14527 $.extend( extPagination, { 14528 simple: function ( page, pages ) { 14529 return [ 'previous', 'next' ]; 14530 }, 14531 14532 full: function ( page, pages ) { 14533 return [ 'first', 'previous', 'next', 'last' ]; 14534 }, 14535 14536 numbers: function ( page, pages ) { 14537 return [ _numbers(page, pages) ]; 14538 }, 14539 14540 simple_numbers: function ( page, pages ) { 14541 return [ 'previous', _numbers(page, pages), 'next' ]; 14542 }, 14543 14544 full_numbers: function ( page, pages ) { 14545 return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ]; 14546 }, 14547 14548 first_last_numbers: function (page, pages) { 14549 return ['first', _numbers(page, pages), 'last']; 14550 }, 14551 14552 // For testing and plug-ins to use 14553 _numbers: _numbers, 14554 14555 // Number of number buttons (including ellipsis) to show. _Must be odd!_ 14556 numbers_length: 7 14557 } ); 14558 14559 14560 $.extend( true, DataTable.ext.renderer, { 14561 pageButton: { 14562 _: function ( settings, host, idx, buttons, page, pages ) { 14563 var classes = settings.oClasses; 14564 var lang = settings.oLanguage.oPaginate; 14565 var aria = settings.oLanguage.oAria.paginate || {}; 14566 var btnDisplay, btnClass, counter=0; 14567 14568 var attach = function( container, buttons ) { 14569 var i, ien, node, button, tabIndex; 14570 var disabledClass = classes.sPageButtonDisabled; 14571 var clickHandler = function ( e ) { 14572 _fnPageChange( settings, e.data.action, true ); 14573 }; 14574 14575 for ( i=0, ien=buttons.length ; i<ien ; i++ ) { 14576 button = buttons[i]; 14577 14578 if ( $.isArray( button ) ) { 14579 var inner = $( '<'+(button.DT_el || 'div')+'/>' ) 14580 .appendTo( container ); 14581 attach( inner, button ); 14582 } 14583 else { 14584 btnDisplay = null; 14585 btnClass = button; 14586 tabIndex = settings.iTabIndex; 14587 14588 switch ( button ) { 14589 case 'ellipsis': 14590 container.append('<span class="ellipsis">…</span>'); 14591 break; 14592 14593 case 'first': 14594 btnDisplay = lang.sFirst; 14595 14596 if ( page === 0 ) { 14597 tabIndex = -1; 14598 btnClass += ' ' + disabledClass; 14599 } 14600 break; 14601 14602 case 'previous': 14603 btnDisplay = lang.sPrevious; 14604 14605 if ( page === 0 ) { 14606 tabIndex = -1; 14607 btnClass += ' ' + disabledClass; 14608 } 14609 break; 14610 14611 case 'next': 14612 btnDisplay = lang.sNext; 14613 14614 if ( pages === 0 || page === pages-1 ) { 14615 tabIndex = -1; 14616 btnClass += ' ' + disabledClass; 14617 } 14618 break; 14619 14620 case 'last': 14621 btnDisplay = lang.sLast; 14622 14623 if ( page === pages-1 ) { 14624 tabIndex = -1; 14625 btnClass += ' ' + disabledClass; 14626 } 14627 break; 14628 14629 default: 14630 btnDisplay = button + 1; 14631 btnClass = page === button ? 14632 classes.sPageButtonActive : ''; 14633 break; 14634 } 14635 14636 if ( btnDisplay !== null ) { 14637 node = $('<a>', { 14638 'class': classes.sPageButton+' '+btnClass, 14639 'aria-controls': settings.sTableId, 14640 'aria-label': aria[ button ], 14641 'data-dt-idx': counter, 14642 'tabindex': tabIndex, 14643 'id': idx === 0 && typeof button === 'string' ? 14644 settings.sTableId +'_'+ button : 14645 null 14646 } ) 14647 .html( btnDisplay ) 14648 .appendTo( container ); 14649 14650 _fnBindAction( 14651 node, {action: button}, clickHandler 14652 ); 14653 14654 counter++; 14655 } 14656 } 14657 } 14658 }; 14659 14660 // IE9 throws an 'unknown error' if document.activeElement is used 14661 // inside an iframe or frame. Try / catch the error. Not good for 14662 // accessibility, but neither are frames. 14663 var activeEl; 14664 14665 try { 14666 // Because this approach is destroying and recreating the paging 14667 // elements, focus is lost on the select button which is bad for 14668 // accessibility. So we want to restore focus once the draw has 14669 // completed 14670 activeEl = $(host).find(document.activeElement).data('dt-idx'); 14671 } 14672 catch (e) {} 14673 14674 attach( $(host).empty(), buttons ); 14675 14676 if ( activeEl !== undefined ) { 14677 $(host).find( '[data-dt-idx='+activeEl+']' ).trigger('focus'); 14678 } 14679 } 14680 } 14681 } ); 14682 14683 14684 14685 // Built in type detection. See model.ext.aTypes for information about 14686 // what is required from this methods. 14687 $.extend( DataTable.ext.type.detect, [ 14688 // Plain numbers - first since V8 detects some plain numbers as dates 14689 // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...). 14690 function ( d, settings ) 14691 { 14692 var decimal = settings.oLanguage.sDecimal; 14693 return _isNumber( d, decimal ) ? 'num'+decimal : null; 14694 }, 14695 14696 // Dates (only those recognised by the browser's Date.parse) 14697 function ( d, settings ) 14698 { 14699 // V8 tries _very_ hard to make a string passed into `Date.parse()` 14700 // valid, so we need to use a regex to restrict date formats. Use a 14701 // plug-in for anything other than ISO8601 style strings 14702 if ( d && !(d instanceof Date) && ! _re_date.test(d) ) { 14703 return null; 14704 } 14705 var parsed = Date.parse(d); 14706 return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null; 14707 }, 14708 14709 // Formatted numbers 14710 function ( d, settings ) 14711 { 14712 var decimal = settings.oLanguage.sDecimal; 14713 return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null; 14714 }, 14715 14716 // HTML numeric 14717 function ( d, settings ) 14718 { 14719 var decimal = settings.oLanguage.sDecimal; 14720 return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null; 14721 }, 14722 14723 // HTML numeric, formatted 14724 function ( d, settings ) 14725 { 14726 var decimal = settings.oLanguage.sDecimal; 14727 return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null; 14728 }, 14729 14730 // HTML (this is strict checking - there must be html) 14731 function ( d, settings ) 14732 { 14733 return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ? 14734 'html' : null; 14735 } 14736 ] ); 14737 14738 14739 14740 // Filter formatting functions. See model.ext.ofnSearch for information about 14741 // what is required from these methods. 14742 // 14743 // Note that additional search methods are added for the html numbers and 14744 // html formatted numbers by `_addNumericSort()` when we know what the decimal 14745 // place is 14746 14747 14748 $.extend( DataTable.ext.type.search, { 14749 html: function ( data ) { 14750 return _empty(data) ? 14751 data : 14752 typeof data === 'string' ? 14753 data 14754 .replace( _re_new_lines, " " ) 14755 .replace( _re_html, "" ) : 14756 ''; 14757 }, 14758 14759 string: function ( data ) { 14760 return _empty(data) ? 14761 data : 14762 typeof data === 'string' ? 14763 data.replace( _re_new_lines, " " ) : 14764 data; 14765 } 14766 } ); 14767 14768 14769 14770 var __numericReplace = function ( d, decimalPlace, re1, re2 ) { 14771 if ( d !== 0 && (!d || d === '-') ) { 14772 return -Infinity; 14773 } 14774 14775 // If a decimal place other than `.` is used, it needs to be given to the 14776 // function so we can detect it and replace with a `.` which is the only 14777 // decimal place Javascript recognises - it is not locale aware. 14778 if ( decimalPlace ) { 14779 d = _numToDecimal( d, decimalPlace ); 14780 } 14781 14782 if ( d.replace ) { 14783 if ( re1 ) { 14784 d = d.replace( re1, '' ); 14785 } 14786 14787 if ( re2 ) { 14788 d = d.replace( re2, '' ); 14789 } 14790 } 14791 14792 return d * 1; 14793 }; 14794 14795 14796 // Add the numeric 'deformatting' functions for sorting and search. This is done 14797 // in a function to provide an easy ability for the language options to add 14798 // additional methods if a non-period decimal place is used. 14799 function _addNumericSort ( decimalPlace ) { 14800 $.each( 14801 { 14802 // Plain numbers 14803 "num": function ( d ) { 14804 return __numericReplace( d, decimalPlace ); 14805 }, 14806 14807 // Formatted numbers 14808 "num-fmt": function ( d ) { 14809 return __numericReplace( d, decimalPlace, _re_formatted_numeric ); 14810 }, 14811 14812 // HTML numeric 14813 "html-num": function ( d ) { 14814 return __numericReplace( d, decimalPlace, _re_html ); 14815 }, 14816 14817 // HTML numeric, formatted 14818 "html-num-fmt": function ( d ) { 14819 return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric ); 14820 } 14821 }, 14822 function ( key, fn ) { 14823 // Add the ordering method 14824 _ext.type.order[ key+decimalPlace+'-pre' ] = fn; 14825 14826 // For HTML types add a search formatter that will strip the HTML 14827 if ( key.match(/^html\-/) ) { 14828 _ext.type.search[ key+decimalPlace ] = _ext.type.search.html; 14829 } 14830 } 14831 ); 14832 } 14833 14834 14835 // Default sort methods 14836 $.extend( _ext.type.order, { 14837 // Dates 14838 "date-pre": function ( d ) { 14839 var ts = Date.parse( d ); 14840 return isNaN(ts) ? -Infinity : ts; 14841 }, 14842 14843 // html 14844 "html-pre": function ( a ) { 14845 return _empty(a) ? 14846 '' : 14847 a.replace ? 14848 a.replace( /<.*?>/g, "" ).toLowerCase() : 14849 a+''; 14850 }, 14851 14852 // string 14853 "string-pre": function ( a ) { 14854 // This is a little complex, but faster than always calling toString, 14855 // http://jsperf.com/tostring-v-check 14856 return _empty(a) ? 14857 '' : 14858 typeof a === 'string' ? 14859 a.toLowerCase() : 14860 ! a.toString ? 14861 '' : 14862 a.toString(); 14863 }, 14864 14865 // string-asc and -desc are retained only for compatibility with the old 14866 // sort methods 14867 "string-asc": function ( x, y ) { 14868 return ((x < y) ? -1 : ((x > y) ? 1 : 0)); 14869 }, 14870 14871 "string-desc": function ( x, y ) { 14872 return ((x < y) ? 1 : ((x > y) ? -1 : 0)); 14873 } 14874 } ); 14875 14876 14877 // Numeric sorting types - order doesn't matter here 14878 _addNumericSort( '' ); 14879 14880 14881 $.extend( true, DataTable.ext.renderer, { 14882 header: { 14883 _: function ( settings, cell, column, classes ) { 14884 // No additional mark-up required 14885 // Attach a sort listener to update on sort - note that using the 14886 // `DT` namespace will allow the event to be removed automatically 14887 // on destroy, while the `dt` namespaced event is the one we are 14888 // listening for 14889 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) { 14890 if ( settings !== ctx ) { // need to check this this is the host 14891 return; // table, not a nested one 14892 } 14893 14894 var colIdx = column.idx; 14895 14896 cell 14897 .removeClass( 14898 column.sSortingClass +' '+ 14899 classes.sSortAsc +' '+ 14900 classes.sSortDesc 14901 ) 14902 .addClass( columns[ colIdx ] == 'asc' ? 14903 classes.sSortAsc : columns[ colIdx ] == 'desc' ? 14904 classes.sSortDesc : 14905 column.sSortingClass 14906 ); 14907 } ); 14908 }, 14909 14910 jqueryui: function ( settings, cell, column, classes ) { 14911 $('<div/>') 14912 .addClass( classes.sSortJUIWrapper ) 14913 .append( cell.contents() ) 14914 .append( $('<span/>') 14915 .addClass( classes.sSortIcon+' '+column.sSortingClassJUI ) 14916 ) 14917 .appendTo( cell ); 14918 14919 // Attach a sort listener to update on sort 14920 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) { 14921 if ( settings !== ctx ) { 14922 return; 14923 } 14924 14925 var colIdx = column.idx; 14926 14927 cell 14928 .removeClass( classes.sSortAsc +" "+classes.sSortDesc ) 14929 .addClass( columns[ colIdx ] == 'asc' ? 14930 classes.sSortAsc : columns[ colIdx ] == 'desc' ? 14931 classes.sSortDesc : 14932 column.sSortingClass 14933 ); 14934 14935 cell 14936 .find( 'span.'+classes.sSortIcon ) 14937 .removeClass( 14938 classes.sSortJUIAsc +" "+ 14939 classes.sSortJUIDesc +" "+ 14940 classes.sSortJUI +" "+ 14941 classes.sSortJUIAscAllowed +" "+ 14942 classes.sSortJUIDescAllowed 14943 ) 14944 .addClass( columns[ colIdx ] == 'asc' ? 14945 classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ? 14946 classes.sSortJUIDesc : 14947 column.sSortingClassJUI 14948 ); 14949 } ); 14950 } 14951 } 14952 } ); 14953 14954 /* 14955 * Public helper functions. These aren't used internally by DataTables, or 14956 * called by any of the options passed into DataTables, but they can be used 14957 * externally by developers working with DataTables. They are helper functions 14958 * to make working with DataTables a little bit easier. 14959 */ 14960 14961 var __htmlEscapeEntities = function ( d ) { 14962 return typeof d === 'string' ? 14963 d 14964 .replace(/&/g, '&') 14965 .replace(/</g, '<') 14966 .replace(/>/g, '>') 14967 .replace(/"/g, '"') : 14968 d; 14969 }; 14970 14971 /** 14972 * Helpers for `columns.render`. 14973 * 14974 * The options defined here can be used with the `columns.render` initialisation 14975 * option to provide a display renderer. The following functions are defined: 14976 * 14977 * * `number` - Will format numeric data (defined by `columns.data`) for 14978 * display, retaining the original unformatted data for sorting and filtering. 14979 * It takes 5 parameters: 14980 * * `string` - Thousands grouping separator 14981 * * `string` - Decimal point indicator 14982 * * `integer` - Number of decimal points to show 14983 * * `string` (optional) - Prefix. 14984 * * `string` (optional) - Postfix (/suffix). 14985 * * `text` - Escape HTML to help prevent XSS attacks. It has no optional 14986 * parameters. 14987 * 14988 * @example 14989 * // Column definition using the number renderer 14990 * { 14991 * data: "salary", 14992 * render: $.fn.dataTable.render.number( '\'', '.', 0, '$' ) 14993 * } 14994 * 14995 * @namespace 14996 */ 14997 DataTable.render = { 14998 number: function ( thousands, decimal, precision, prefix, postfix ) { 14999 return { 15000 display: function ( d ) { 15001 if ( typeof d !== 'number' && typeof d !== 'string' ) { 15002 return d; 15003 } 15004 15005 var negative = d < 0 ? '-' : ''; 15006 var flo = parseFloat( d ); 15007 15008 // If NaN then there isn't much formatting that we can do - just 15009 // return immediately, escaping any HTML (this was supposed to 15010 // be a number after all) 15011 if ( isNaN( flo ) ) { 15012 return __htmlEscapeEntities( d ); 15013 } 15014 15015 flo = flo.toFixed( precision ); 15016 d = Math.abs( flo ); 15017 15018 var intPart = parseInt( d, 10 ); 15019 var floatPart = precision ? 15020 decimal+(d - intPart).toFixed( precision ).substring( 2 ): 15021 ''; 15022 15023 return negative + (prefix||'') + 15024 intPart.toString().replace( 15025 /\B(?=(\d{3})+(?!\d))/g, thousands 15026 ) + 15027 floatPart + 15028 (postfix||''); 15029 } 15030 }; 15031 }, 15032 15033 text: function () { 15034 return { 15035 display: __htmlEscapeEntities, 15036 filter: __htmlEscapeEntities 15037 }; 15038 } 15039 }; 15040 15041 15042 /* 15043 * This is really a good bit rubbish this method of exposing the internal methods 15044 * publicly... - To be fixed in 2.0 using methods on the prototype 15045 */ 15046 15047 15048 /** 15049 * Create a wrapper function for exporting an internal functions to an external API. 15050 * @param {string} fn API function name 15051 * @returns {function} wrapped function 15052 * @memberof DataTable#internal 15053 */ 15054 function _fnExternApiFunc (fn) 15055 { 15056 return function() { 15057 var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat( 15058 Array.prototype.slice.call(arguments) 15059 ); 15060 return DataTable.ext.internal[fn].apply( this, args ); 15061 }; 15062 } 15063 15064 15065 /** 15066 * Reference to internal functions for use by plug-in developers. Note that 15067 * these methods are references to internal functions and are considered to be 15068 * private. If you use these methods, be aware that they are liable to change 15069 * between versions. 15070 * @namespace 15071 */ 15072 $.extend( DataTable.ext.internal, { 15073 _fnExternApiFunc: _fnExternApiFunc, 15074 _fnBuildAjax: _fnBuildAjax, 15075 _fnAjaxUpdate: _fnAjaxUpdate, 15076 _fnAjaxParameters: _fnAjaxParameters, 15077 _fnAjaxUpdateDraw: _fnAjaxUpdateDraw, 15078 _fnAjaxDataSrc: _fnAjaxDataSrc, 15079 _fnAddColumn: _fnAddColumn, 15080 _fnColumnOptions: _fnColumnOptions, 15081 _fnAdjustColumnSizing: _fnAdjustColumnSizing, 15082 _fnVisibleToColumnIndex: _fnVisibleToColumnIndex, 15083 _fnColumnIndexToVisible: _fnColumnIndexToVisible, 15084 _fnVisbleColumns: _fnVisbleColumns, 15085 _fnGetColumns: _fnGetColumns, 15086 _fnColumnTypes: _fnColumnTypes, 15087 _fnApplyColumnDefs: _fnApplyColumnDefs, 15088 _fnHungarianMap: _fnHungarianMap, 15089 _fnCamelToHungarian: _fnCamelToHungarian, 15090 _fnLanguageCompat: _fnLanguageCompat, 15091 _fnBrowserDetect: _fnBrowserDetect, 15092 _fnAddData: _fnAddData, 15093 _fnAddTr: _fnAddTr, 15094 _fnNodeToDataIndex: _fnNodeToDataIndex, 15095 _fnNodeToColumnIndex: _fnNodeToColumnIndex, 15096 _fnGetCellData: _fnGetCellData, 15097 _fnSetCellData: _fnSetCellData, 15098 _fnSplitObjNotation: _fnSplitObjNotation, 15099 _fnGetObjectDataFn: _fnGetObjectDataFn, 15100 _fnSetObjectDataFn: _fnSetObjectDataFn, 15101 _fnGetDataMaster: _fnGetDataMaster, 15102 _fnClearTable: _fnClearTable, 15103 _fnDeleteIndex: _fnDeleteIndex, 15104 _fnInvalidate: _fnInvalidate, 15105 _fnGetRowElements: _fnGetRowElements, 15106 _fnCreateTr: _fnCreateTr, 15107 _fnBuildHead: _fnBuildHead, 15108 _fnDrawHead: _fnDrawHead, 15109 _fnDraw: _fnDraw, 15110 _fnReDraw: _fnReDraw, 15111 _fnAddOptionsHtml: _fnAddOptionsHtml, 15112 _fnDetectHeader: _fnDetectHeader, 15113 _fnGetUniqueThs: _fnGetUniqueThs, 15114 _fnFeatureHtmlFilter: _fnFeatureHtmlFilter, 15115 _fnFilterComplete: _fnFilterComplete, 15116 _fnFilterCustom: _fnFilterCustom, 15117 _fnFilterColumn: _fnFilterColumn, 15118 _fnFilter: _fnFilter, 15119 _fnFilterCreateSearch: _fnFilterCreateSearch, 15120 _fnEscapeRegex: _fnEscapeRegex, 15121 _fnFilterData: _fnFilterData, 15122 _fnFeatureHtmlInfo: _fnFeatureHtmlInfo, 15123 _fnUpdateInfo: _fnUpdateInfo, 15124 _fnInfoMacros: _fnInfoMacros, 15125 _fnInitialise: _fnInitialise, 15126 _fnInitComplete: _fnInitComplete, 15127 _fnLengthChange: _fnLengthChange, 15128 _fnFeatureHtmlLength: _fnFeatureHtmlLength, 15129 _fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate, 15130 _fnPageChange: _fnPageChange, 15131 _fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing, 15132 _fnProcessingDisplay: _fnProcessingDisplay, 15133 _fnFeatureHtmlTable: _fnFeatureHtmlTable, 15134 _fnScrollDraw: _fnScrollDraw, 15135 _fnApplyToChildren: _fnApplyToChildren, 15136 _fnCalculateColumnWidths: _fnCalculateColumnWidths, 15137 _fnThrottle: _fnThrottle, 15138 _fnConvertToWidth: _fnConvertToWidth, 15139 _fnGetWidestNode: _fnGetWidestNode, 15140 _fnGetMaxLenString: _fnGetMaxLenString, 15141 _fnStringToCss: _fnStringToCss, 15142 _fnSortFlatten: _fnSortFlatten, 15143 _fnSort: _fnSort, 15144 _fnSortAria: _fnSortAria, 15145 _fnSortListener: _fnSortListener, 15146 _fnSortAttachListener: _fnSortAttachListener, 15147 _fnSortingClasses: _fnSortingClasses, 15148 _fnSortData: _fnSortData, 15149 _fnSaveState: _fnSaveState, 15150 _fnLoadState: _fnLoadState, 15151 _fnSettingsFromNode: _fnSettingsFromNode, 15152 _fnLog: _fnLog, 15153 _fnMap: _fnMap, 15154 _fnBindAction: _fnBindAction, 15155 _fnCallbackReg: _fnCallbackReg, 15156 _fnCallbackFire: _fnCallbackFire, 15157 _fnLengthOverflow: _fnLengthOverflow, 15158 _fnRenderer: _fnRenderer, 15159 _fnDataSource: _fnDataSource, 15160 _fnRowAttributes: _fnRowAttributes, 15161 _fnExtend: _fnExtend, 15162 _fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant 15163 // in 1.10, so this dead-end function is 15164 // added to prevent errors 15165 } ); 15166 15167 15168 // jQuery access 15169 $.fn.dataTable = DataTable; 15170 15171 // Provide access to the host jQuery object (circular reference) 15172 DataTable.$ = $; 15173 15174 // Legacy aliases 15175 $.fn.dataTableSettings = DataTable.settings; 15176 $.fn.dataTableExt = DataTable.ext; 15177 15178 // With a capital `D` we return a DataTables API instance rather than a 15179 // jQuery object 15180 $.fn.DataTable = function ( opts ) { 15181 return $(this).dataTable( opts ).api(); 15182 }; 15183 15184 // All properties that are available to $.fn.dataTable should also be 15185 // available on $.fn.DataTable 15186 $.each( DataTable, function ( prop, val ) { 15187 $.fn.DataTable[ prop ] = val; 15188 } ); 15189 15190 15191 // Information about events fired by DataTables - for documentation. 15192 /** 15193 * Draw event, fired whenever the table is redrawn on the page, at the same 15194 * point as fnDrawCallback. This may be useful for binding events or 15195 * performing calculations when the table is altered at all. 15196 * @name DataTable#draw.dt 15197 * @event 15198 * @param {event} e jQuery event object 15199 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15200 */ 15201 15202 /** 15203 * Search event, fired when the searching applied to the table (using the 15204 * built-in global search, or column filters) is altered. 15205 * @name DataTable#search.dt 15206 * @event 15207 * @param {event} e jQuery event object 15208 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15209 */ 15210 15211 /** 15212 * Page change event, fired when the paging of the table is altered. 15213 * @name DataTable#page.dt 15214 * @event 15215 * @param {event} e jQuery event object 15216 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15217 */ 15218 15219 /** 15220 * Order event, fired when the ordering applied to the table is altered. 15221 * @name DataTable#order.dt 15222 * @event 15223 * @param {event} e jQuery event object 15224 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15225 */ 15226 15227 /** 15228 * DataTables initialisation complete event, fired when the table is fully 15229 * drawn, including Ajax data loaded, if Ajax data is required. 15230 * @name DataTable#init.dt 15231 * @event 15232 * @param {event} e jQuery event object 15233 * @param {object} oSettings DataTables settings object 15234 * @param {object} json The JSON object request from the server - only 15235 * present if client-side Ajax sourced data is used</li></ol> 15236 */ 15237 15238 /** 15239 * State save event, fired when the table has changed state a new state save 15240 * is required. This event allows modification of the state saving object 15241 * prior to actually doing the save, including addition or other state 15242 * properties (for plug-ins) or modification of a DataTables core property. 15243 * @name DataTable#stateSaveParams.dt 15244 * @event 15245 * @param {event} e jQuery event object 15246 * @param {object} oSettings DataTables settings object 15247 * @param {object} json The state information to be saved 15248 */ 15249 15250 /** 15251 * State load event, fired when the table is loading state from the stored 15252 * data, but prior to the settings object being modified by the saved state 15253 * - allowing modification of the saved state is required or loading of 15254 * state for a plug-in. 15255 * @name DataTable#stateLoadParams.dt 15256 * @event 15257 * @param {event} e jQuery event object 15258 * @param {object} oSettings DataTables settings object 15259 * @param {object} json The saved state information 15260 */ 15261 15262 /** 15263 * State loaded event, fired when state has been loaded from stored data and 15264 * the settings object has been modified by the loaded data. 15265 * @name DataTable#stateLoaded.dt 15266 * @event 15267 * @param {event} e jQuery event object 15268 * @param {object} oSettings DataTables settings object 15269 * @param {object} json The saved state information 15270 */ 15271 15272 /** 15273 * Processing event, fired when DataTables is doing some kind of processing 15274 * (be it, order, search or anything else). It can be used to indicate to 15275 * the end user that there is something happening, or that something has 15276 * finished. 15277 * @name DataTable#processing.dt 15278 * @event 15279 * @param {event} e jQuery event object 15280 * @param {object} oSettings DataTables settings object 15281 * @param {boolean} bShow Flag for if DataTables is doing processing or not 15282 */ 15283 15284 /** 15285 * Ajax (XHR) event, fired whenever an Ajax request is completed from a 15286 * request to made to the server for new data. This event is called before 15287 * DataTables processed the returned data, so it can also be used to pre- 15288 * process the data returned from the server, if needed. 15289 *
15290 * Note that this trigger is called in `fnServerData`, if you override 15291 * `fnServerData` and which to use this event, you need to trigger it in you 15292 * success function. 15293 * @name DataTable#xhr.dt 15294 * @event 15295 * @param {event} e jQuery event object 15296 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15297 * @param {object} json JSON returned from the server 15298 * 15299 * @example 15300 * // Use a custom property returned from the server in another DOM element 15301 * $('#table').dataTable().on('xhr.dt', function (e, settings, json) { 15302 * $('#status').html( json.status ); 15303 * } ); 15304 * 15305 * @example 15306 * // Pre-process the data returned from the server 15307 * $('#table').dataTable().on('xhr.dt', function (e, settings, json) { 15308 * for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) { 15309 * json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two; 15310 * } 15311 * // Note no return - manipulate the data directly in the JSON object. 15312 * } ); 15313 */ 15314 15315 /** 15316 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy 15317 * or passing the bDestroy:true parameter in the initialisation object. This 15318 * can be used to remove bound events, added DOM nodes, etc. 15319 * @name DataTable#destroy.dt 15320 * @event 15321 * @param {event} e jQuery event object 15322 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15323 */ 15324 15325 /** 15326 * Page length change event, fired when number of records to show on each 15327 * page (the length) is changed. 15328 * @name DataTable#length.dt 15329 * @event 15330 * @param {event} e jQuery event object 15331 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15332 * @param {integer} len New length 15333 */ 15334 15335 /** 15336 * Column sizing has changed. 15337 * @name DataTable#column-sizing.dt 15338 * @event 15339 * @param {event} e jQuery event object 15340 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15341 */ 15342 15343 /** 15344 * Column visibility has changed. 15345 * @name DataTable#column-visibility.dt 15346 * @event 15347 * @param {event} e jQuery event object 15348 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15349 * @param {int} column Column index 15350 * @param {bool} vis `false` if column now hidden, or `true` if visible 15351 */ 15352 15353 return $.fn.dataTable; 15354}));
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.