1/*! DataTables 1.10.19 2 * ©2008-2018 SpryMedia Ltd - datatables.net/license 3 */ 4 5/** 6 * @summary DataTables 7 * @description Paginate, search and order HTML tables 8 * @version 1.10.19 9 * @file jquery.dataTables.js 10 * @author SpryMedia Ltd 11 * @contact www.datatables.net 12 * @copyright Copyright 2008-2018 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,803 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() ) ); 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]/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 ); 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: 10,997 bytes, lines 3010-3432
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; 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 3103 nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType ); 3104 nTd._DT_CellIndex = { 3105 row: iRow, 3106 column: i 3107 }; 3108 3109 cells.push( nTd ); 3110 3111 // Need to create the HTML if new, or if a rendering function is defined 3112 if ( (!nTrIn || oCol.mRender || oCol.mData !== i) && 3113 (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display') 3114 ) { 3115 nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' ); 3116 } 3117 3118 /* Add user defined class */ 3119 if ( oCol.sClass ) 3120 { 3121 nTd.className += ' '+oCol.sClass; 3122 } 3123 3124 // Visibility - add or remove as required 3125 if ( oCol.bVisible && ! nTrIn ) 3126 { 3127 nTr.appendChild( nTd ); 3128 } 3129 else if ( ! oCol.bVisible && nTrIn ) 3130 { 3131 nTd.parentNode.removeChild( nTd ); 3132 } 3133 3134 if ( oCol.fnCreatedCell ) 3135 { 3136 oCol.fnCreatedCell.call( oSettings.oInstance, 3137 nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i 3138 ); 3139 } 3140 } 3141 3142 _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow, cells] ); 3143 } 3144 3145 // Remove once webkit bug 131819 and Chromium bug 365619 have been resolved 3146 // and deployed 3147 row.nTr.setAttribute( 'role', 'row' ); 3148 } 3149 3150 3151 /** 3152 * Add attributes to a row based on the special `DT_*` parameters in a data 3153 * source object. 3154 * @param {object} settings DataTables settings object 3155 * @param {object} DataTables row object for the row to be modified 3156 * @memberof DataTable#oApi 3157 */ 3158 function _fnRowAttributes( settings, row ) 3159 { 3160 var tr = row.nTr; 3161 var data = row._aData; 3162 3163 if ( tr ) { 3164 var id = settings.rowIdFn( data ); 3165 3166 if ( id ) { 3167 tr.id = id; 3168 } 3169 3170 if ( data.DT_RowClass ) { 3171 // Remove any classes added by DT_RowClass before 3172 var a = data.DT_RowClass.split(' '); 3173 row.__rowc = row.__rowc ? 3174 _unique( row.__rowc.concat( a ) ) : 3175 a; 3176 3177 $(tr) 3178 .removeClass( row.__rowc.join(' ') ) 3179 .addClass( data.DT_RowClass ); 3180 } 3181 3182 if ( data.DT_RowAttr ) { 3183 $(tr).attr( data.DT_RowAttr ); 3184 } 3185 3186 if ( data.DT_RowData ) { 3187 $(tr).data( data.DT_RowData ); 3188 } 3189 } 3190 } 3191 3192 3193 /** 3194 * Create the HTML header for the table 3195 * @param {object} oSettings dataTables settings object 3196 * @memberof DataTable#oApi 3197 */ 3198 function _fnBuildHead( oSettings ) 3199 { 3200 var i, ien, cell, row, column; 3201 var thead = oSettings.nTHead; 3202 var tfoot = oSettings.nTFoot; 3203 var createHeader = $('th, td', thead).length === 0; 3204 var classes = oSettings.oClasses; 3205 var columns = oSettings.aoColumns; 3206 3207 if ( createHeader ) { 3208 row = $('<tr/>').appendTo( thead ); 3209 } 3210 3211 for ( i=0, ien=columns.length ; i<ien ; i++ ) { 3212 column = columns[i]; 3213 cell = $( column.nTh ).addClass( column.sClass ); 3214 3215 if ( createHeader ) { 3216 cell.appendTo( row ); 3217 } 3218 3219 // 1.11 move into sorting 3220 if ( oSettings.oFeatures.bSort ) { 3221 cell.addClass( column.sSortingClass ); 3222 3223 if ( column.bSortable !== false ) { 3224 cell 3225 .attr( 'tabindex', oSettings.iTabIndex ) 3226 .attr( 'aria-controls', oSettings.sTableId ); 3227 3228 _fnSortAttachListener( oSettings, column.nTh, i ); 3229 } 3230 } 3231 3232 if ( column.sTitle != cell[0].innerHTML ) { 3233 cell.html( column.sTitle ); 3234 } 3235 3236 _fnRenderer( oSettings, 'header' )( 3237 oSettings, cell, column, classes 3238 ); 3239 } 3240 3241 if ( createHeader ) { 3242 _fnDetectHeader( oSettings.aoHeader, thead ); 3243 } 3244 3245 /* ARIA role for the rows */ 3246 $(thead).find('>tr').attr('role', 'row'); 3247 3248 /* Deal with the footer - add classes if required */ 3249 $(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH ); 3250 $(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH ); 3251 3252 // Cache the footer cells. Note that we only take the cells from the first 3253 // row in the footer. If there is more than one row the user wants to 3254 // interact with, they need to use the table().foot() method. Note also this 3255 // allows cells to be used for multiple columns using colspan 3256 if ( tfoot !== null ) { 3257 var cells = oSettings.aoFooter[0]; 3258 3259 for ( i=0, ien=cells.length ; i<ien ; i++ ) { 3260 column = columns[i]; 3261 column.nTf = cells[i].cell; 3262 3263 if ( column.sClass ) { 3264 $(column.nTf).addClass( column.sClass ); 3265 } 3266 } 3267 } 3268 } 3269 3270 3271 /** 3272 * Draw the header (or footer) element based on the column visibility states. The 3273 * methodology here is to use the layout array from _fnDetectHeader, modified for 3274 * the instantaneous column visibility, to construct the new layout. The grid is 3275 * traversed over cell at a time in a rows x columns grid fashion, although each 3276 * cell insert can cover multiple elements in the grid - which is tracks using the 3277 * aApplied array. Cell inserts in the grid will only occur where there isn't 3278 * already a cell in that position. 3279 * @param {object} oSettings dataTables settings object 3280 * @param array {objects} aoSource Layout array from _fnDetectHeader 3281 * @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc, 3282 * @memberof DataTable#oApi 3283 */ 3284 function _fnDrawHead( oSettings, aoSource, bIncludeHidden ) 3285 { 3286 var i, iLen, j, jLen, k, kLen, n, nLocalTr; 3287 var aoLocal = []; 3288 var aApplied = []; 3289 var iColumns = oSettings.aoColumns.length; 3290 var iRowspan, iColspan; 3291 3292 if ( ! aoSource ) 3293 { 3294 return; 3295 } 3296 3297 if ( bIncludeHidden === undefined ) 3298 { 3299 bIncludeHidden = false; 3300 } 3301 3302 /* Make a copy of the master layout array, but without the visible columns in it */ 3303 for ( i=0, iLen=aoSource.length ; i<iLen ; i++ ) 3304 { 3305 aoLocal[i] = aoSource[i].slice(); 3306 aoLocal[i].nTr = aoSource[i].nTr; 3307 3308 /* Remove any columns which are currently hidden */ 3309 for ( j=iColumns-1 ; j>=0 ; j-- ) 3310 { 3311 if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden ) 3312 { 3313 aoLocal[i].splice( j, 1 ); 3314 } 3315 } 3316 3317 /* Prep the applied array - it needs an element for each row */ 3318 aApplied.push( [] ); 3319 } 3320 3321 for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ ) 3322 { 3323 nLocalTr = aoLocal[i].nTr; 3324 3325 /* All cells are going to be replaced, so empty out the row */ 3326 if ( nLocalTr ) 3327 { 3328 while( (n = nLocalTr.firstChild) ) 3329 { 3330 nLocalTr.removeChild( n ); 3331 } 3332 } 3333 3334 for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ ) 3335 { 3336 iRowspan = 1; 3337 iColspan = 1; 3338 3339 /* Check to see if there is already a cell (row/colspan) covering our target 3340 * insert point. If there is, then there is nothing to do. 3341 */ 3342 if ( aApplied[i][j] === undefined ) 3343 { 3344 nLocalTr.appendChild( aoLocal[i][j].cell ); 3345 aApplied[i][j] = 1; 3346 3347 /* Expand the cell to cover as many rows as needed */ 3348 while ( aoLocal[i+iRowspan] !== undefined && 3349 aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell ) 3350 { 3351 aApplied[i+iRowspan][j] = 1; 3352 iRowspan++; 3353 } 3354 3355 /* Expand the cell to cover as many columns as needed */ 3356 while ( aoLocal[i][j+iColspan] !== undefined && 3357 aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell ) 3358 { 3359 /* Must update the applied array over the rows for the columns */ 3360 for ( k=0 ; k<iRowspan ; k++ ) 3361 { 3362 aApplied[i+k][j+iColspan] = 1; 3363 } 3364 iColspan++; 3365 } 3366 3367 /* Do the actual expansion in the DOM */ 3368 $(aoLocal[i][j].cell) 3369 .attr('rowspan', iRowspan) 3370 .attr('colspan', iColspan); 3371 } 3372 } 3373 } 3374 } 3375 3376 3377 /** 3378 * Insert the required TR nodes into the table for display 3379 * @param {object} oSettings dataTables settings object 3380 * @memberof DataTable#oApi 3381 */ 3382 function _fnDraw( oSettings ) 3383 { 3384 /* Provide a pre-callback function which can be used to cancel the draw is false is returned */ 3385 var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] ); 3386 if ( $.inArray( false, aPreDraw ) !== -1 ) 3387 { 3388 _fnProcessingDisplay( oSettings, false ); 3389 return; 3390 } 3391 3392 var i, iLen, n; 3393 var anRows = []; 3394 var iRowCount = 0; 3395 var asStripeClasses = oSettings.asStripeClasses; 3396 var iStripes = asStripeClasses.length; 3397 var iOpenRows = oSettings.aoOpenRows.length; 3398 var oLang = oSettings.oLanguage; 3399 var iInitDisplayStart = oSettings.iInitDisplayStart; 3400 var bServerSide = _fnDataSource( oSettings ) == 'ssp'; 3401 var aiDisplay = oSettings.aiDisplay; 3402 3403 oSettings.bDrawing = true; 3404 3405 /* Check and see if we have an initial draw position from state saving */ 3406 if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 ) 3407 { 3408 oSettings._iDisplayStart = bServerSide ? 3409 iInitDisplayStart : 3410 iInitDisplayStart >= oSettings.fnRecordsDisplay() ? 3411 0 : 3412 iInitDisplayStart; 3413 3414 oSettings.iInitDisplayStart = -1; 3415 } 3416 3417 var iDisplayStart = oSettings._iDisplayStart; 3418 var iDisplayEnd = oSettings.fnDisplayEnd(); 3419 3420 /* Server-side processing draw intercept */ 3421 if ( oSettings.bDeferLoading ) 3422 { 3423 oSettings.bDeferLoading = false; 3424 oSettings.iDraw++; 3425 _fnProcessingDisplay( oSettings, false ); 3426 } 3427 else if ( !bServerSide ) 3428 { 3429 oSettings.iDraw++; 3430 } 3431 else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) ) 3432 {
vendor: 10,503 bytes, lines 3432-3821
3432 3433 return; 3434 } 3435 3436 if ( aiDisplay.length !== 0 ) 3437 { 3438 var iStart = bServerSide ? 0 : iDisplayStart; 3439 var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd; 3440 3441 for ( var j=iStart ; j<iEnd ; j++ ) 3442 { 3443 var iDataIndex = aiDisplay[j]; 3444 var aoData = oSettings.aoData[ iDataIndex ]; 3445 if ( aoData.nTr === null ) 3446 { 3447 _fnCreateTr( oSettings, iDataIndex ); 3448 } 3449 3450 var nRow = aoData.nTr; 3451 3452 /* Remove the old striping classes and then add the new one */ 3453 if ( iStripes !== 0 ) 3454 { 3455 var sStripe = asStripeClasses[ iRowCount % iStripes ]; 3456 if ( aoData._sRowStripe != sStripe ) 3457 { 3458 $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe ); 3459 aoData._sRowStripe = sStripe; 3460 } 3461 } 3462 3463 // Row callback functions - might want to manipulate the row 3464 // iRowCount and j are not currently documented. Are they at all 3465 // useful? 3466 _fnCallbackFire( oSettings, 'aoRowCallback', null, 3467 [nRow, aoData._aData, iRowCount, j, iDataIndex] ); 3468 3469 anRows.push( nRow ); 3470 iRowCount++; 3471 } 3472 } 3473 else 3474 { 3475 /* Table is empty - create a row with an empty message in it */ 3476 var sZero = oLang.sZeroRecords; 3477 if ( oSettings.iDraw == 1 && _fnDataSource( oSettings ) == 'ajax' ) 3478 { 3479 sZero = oLang.sLoadingRecords; 3480 } 3481 else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 ) 3482 { 3483 sZero = oLang.sEmptyTable; 3484 } 3485 3486 anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } ) 3487 .append( $('<td />', { 3488 'valign': 'top', 3489 'colSpan': _fnVisbleColumns( oSettings ), 3490 'class': oSettings.oClasses.sRowEmpty 3491 } ).html( sZero ) )[0]; 3492 } 3493 3494 /* Header and footer callbacks */ 3495 _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0], 3496 _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] ); 3497 3498 _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0], 3499 _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] ); 3500 3501 var body = $(oSettings.nTBody); 3502 3503 body.children().detach(); 3504 body.append( $(anRows) ); 3505 3506 /* Call all required callback functions for the end of a draw */ 3507 _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] ); 3508 3509 /* Draw is complete, sorting and filtering must be as well */ 3510 oSettings.bSorted = false; 3511 oSettings.bFiltered = false; 3512 oSettings.bDrawing = false; 3513 } 3514 3515 3516 /** 3517 * Redraw the table - taking account of the various features which are enabled 3518 * @param {object} oSettings dataTables settings object 3519 * @param {boolean} [holdPosition] Keep the current paging position. By default 3520 * the paging is reset to the first page 3521 * @memberof DataTable#oApi 3522 */ 3523 function _fnReDraw( settings, holdPosition ) 3524 { 3525 var 3526 features = settings.oFeatures, 3527 sort = features.bSort, 3528 filter = features.bFilter; 3529 3530 if ( sort ) { 3531 _fnSort( settings ); 3532 } 3533 3534 if ( filter ) { 3535 _fnFilterComplete( settings, settings.oPreviousSearch ); 3536 } 3537 else { 3538 // No filtering, so we want to just use the display master 3539 settings.aiDisplay = settings.aiDisplayMaster.slice(); 3540 } 3541 3542 if ( holdPosition !== true ) { 3543 settings._iDisplayStart = 0; 3544 } 3545 3546 // Let any modules know about the draw hold position state (used by 3547 // scrolling internally) 3548 settings._drawHold = holdPosition; 3549 3550 _fnDraw( settings ); 3551 3552 settings._drawHold = false; 3553 } 3554 3555 3556 /** 3557 * Add the options to the page HTML for the table 3558 * @param {object} oSettings dataTables settings object 3559 * @memberof DataTable#oApi 3560 */ 3561 function _fnAddOptionsHtml ( oSettings ) 3562 { 3563 var classes = oSettings.oClasses; 3564 var table = $(oSettings.nTable); 3565 var holding = $('<div/>').insertBefore( table ); // Holding element for speed 3566 var features = oSettings.oFeatures; 3567 3568 // All DataTables are wrapped in a div 3569 var insert = $('<div/>', { 3570 id: oSettings.sTableId+'_wrapper', 3571 'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter) 3572 } ); 3573 3574 oSettings.nHolding = holding[0]; 3575 oSettings.nTableWrapper = insert[0]; 3576 oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling; 3577 3578 /* Loop over the user set positioning and place the elements as needed */ 3579 var aDom = oSettings.sDom.split(''); 3580 var featureNode, cOption, nNewNode, cNext, sAttr, j; 3581 for ( var i=0 ; i<aDom.length ; i++ ) 3582 { 3583 featureNode = null; 3584 cOption = aDom[i]; 3585 3586 if ( cOption == '<' ) 3587 { 3588 /* New container div */ 3589 nNewNode = $('<div/>')[0]; 3590 3591 /* Check to see if we should append an id and/or a class name to the container */ 3592 cNext = aDom[i+1]; 3593 if ( cNext == "'" || cNext == '"' ) 3594 { 3595 sAttr = ""; 3596 j = 2; 3597 while ( aDom[i+j] != cNext ) 3598 { 3599 sAttr += aDom[i+j]; 3600 j++; 3601 } 3602 3603 /* Replace jQuery UI constants @todo depreciated */ 3604 if ( sAttr == "H" ) 3605 { 3606 sAttr = classes.sJUIHeader; 3607 } 3608 else if ( sAttr == "F" ) 3609 { 3610 sAttr = classes.sJUIFooter; 3611 } 3612 3613 /* The attribute can be in the format of "#id.class", "#id" or "class" This logic 3614 * breaks the string into parts and applies them as needed 3615 */ 3616 if ( sAttr.indexOf('.') != -1 ) 3617 { 3618 var aSplit = sAttr.split('.'); 3619 nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1); 3620 nNewNode.className = aSplit[1]; 3621 } 3622 else if ( sAttr.charAt(0) == "#" ) 3623 { 3624 nNewNode.id = sAttr.substr(1, sAttr.length-1); 3625 } 3626 else 3627 { 3628 nNewNode.className = sAttr; 3629 } 3630 3631 i += j; /* Move along the position array */ 3632 } 3633 3634 insert.append( nNewNode ); 3635 insert = $(nNewNode); 3636 } 3637 else if ( cOption == '>' ) 3638 { 3639 /* End container div */ 3640 insert = insert.parent(); 3641 } 3642 // @todo Move options into their own plugins? 3643 else if ( cOption == 'l' && features.bPaginate && features.bLengthChange ) 3644 { 3645 /* Length */ 3646 featureNode = _fnFeatureHtmlLength( oSettings ); 3647 } 3648 else if ( cOption == 'f' && features.bFilter ) 3649 { 3650 /* Filter */ 3651 featureNode = _fnFeatureHtmlFilter( oSettings ); 3652 } 3653 else if ( cOption == 'r' && features.bProcessing ) 3654 { 3655 /* pRocessing */ 3656 featureNode = _fnFeatureHtmlProcessing( oSettings ); 3657 } 3658 else if ( cOption == 't' ) 3659 { 3660 /* Table */ 3661 featureNode = _fnFeatureHtmlTable( oSettings ); 3662 } 3663 else if ( cOption == 'i' && features.bInfo ) 3664 { 3665 /* Info */ 3666 featureNode = _fnFeatureHtmlInfo( oSettings ); 3667 } 3668 else if ( cOption == 'p' && features.bPaginate ) 3669 { 3670 /* Pagination */ 3671 featureNode = _fnFeatureHtmlPaginate( oSettings ); 3672 } 3673 else if ( DataTable.ext.feature.length !== 0 ) 3674 { 3675 /* Plug-in features */ 3676 var aoFeatures = DataTable.ext.feature; 3677 for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ ) 3678 { 3679 if ( cOption == aoFeatures[k].cFeature ) 3680 { 3681 featureNode = aoFeatures[k].fnInit( oSettings ); 3682 break; 3683 } 3684 } 3685 } 3686 3687 /* Add to the 2D features array */ 3688 if ( featureNode ) 3689 { 3690 var aanFeatures = oSettings.aanFeatures; 3691 3692 if ( ! aanFeatures[cOption] ) 3693 { 3694 aanFeatures[cOption] = []; 3695 } 3696 3697 aanFeatures[cOption].push( featureNode ); 3698 insert.append( featureNode ); 3699 } 3700 } 3701 3702 /* Built our DOM structure - replace the holding div with what we want */ 3703 holding.replaceWith( insert ); 3704 oSettings.nHolding = null; 3705 } 3706 3707 3708 /** 3709 * Use the DOM source to create up an array of header cells. The idea here is to 3710 * create a layout grid (array) of rows x columns, which contains a reference 3711 * to the cell that that point in the grid (regardless of col/rowspan), such that 3712 * any column / row could be removed and the new grid constructed 3713 * @param array {object} aLayout Array to store the calculated layout in 3714 * @param {node} nThead The header/footer element for the table 3715 * @memberof DataTable#oApi 3716 */ 3717 function _fnDetectHeader ( aLayout, nThead ) 3718 { 3719 var nTrs = $(nThead).children('tr'); 3720 var nTr, nCell; 3721 var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan; 3722 var bUnique; 3723 var fnShiftCol = function ( a, i, j ) { 3724 var k = a[i]; 3725 while ( k[j] ) { 3726 j++; 3727 } 3728 return j; 3729 }; 3730 3731 aLayout.splice( 0, aLayout.length ); 3732 3733 /* We know how many rows there are in the layout - so prep it */ 3734 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ ) 3735 { 3736 aLayout.push( [] ); 3737 } 3738 3739 /* Calculate a layout array */ 3740 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ ) 3741 { 3742 nTr = nTrs[i]; 3743 iColumn = 0; 3744 3745 /* For every cell in the row... */ 3746 nCell = nTr.firstChild; 3747 while ( nCell ) { 3748 if ( nCell.nodeName.toUpperCase() == "TD" || 3749 nCell.nodeName.toUpperCase() == "TH" ) 3750 { 3751 /* Get the col and rowspan attributes from the DOM and sanitise them */ 3752 iColspan = nCell.getAttribute('colspan') * 1; 3753 iRowspan = nCell.getAttribute('rowspan') * 1; 3754 iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan; 3755 iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan; 3756 3757 /* There might be colspan cells already in this row, so shift our target 3758 * accordingly 3759 */ 3760 iColShifted = fnShiftCol( aLayout, i, iColumn ); 3761 3762 /* Cache calculation for unique columns */ 3763 bUnique = iColspan === 1 ? true : false; 3764 3765 /* If there is col / rowspan, copy the information into the layout grid */ 3766 for ( l=0 ; l<iColspan ; l++ ) 3767 { 3768 for ( k=0 ; k<iRowspan ; k++ ) 3769 { 3770 aLayout[i+k][iColShifted+l] = { 3771 "cell": nCell, 3772 "unique": bUnique 3773 }; 3774 aLayout[i+k].nTr = nTr; 3775 } 3776 } 3777 } 3778 nCell = nCell.nextSibling; 3779 } 3780 } 3781 } 3782 3783 3784 /** 3785 * Get an array of unique th elements, one for each column 3786 * @param {object} oSettings dataTables settings object 3787 * @param {node} nHeader automatically detect the layout from this node - optional 3788 * @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional 3789 * @returns array {node} aReturn list of unique th's 3790 * @memberof DataTable#oApi 3791 */ 3792 function _fnGetUniqueThs ( oSettings, nHeader, aLayout ) 3793 { 3794 var aReturn = []; 3795 if ( !aLayout ) 3796 { 3797 aLayout = oSettings.aoHeader; 3798 if ( nHeader ) 3799 { 3800 aLayout = []; 3801 _fnDetectHeader( aLayout, nHeader ); 3802 } 3803 } 3804 3805 for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ ) 3806 { 3807 for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ ) 3808 { 3809 if ( aLayout[i][j].unique && 3810 (!aReturn[j] || !oSettings.bSortCellsTop) ) 3811 { 3812 aReturn[j] = aLayout[i][j].cell; 3813 } 3814 } 3815 } 3816 3817 return aReturn; 3818 } 3819 3820 /** 3821 *
vendor: 47,598 bytes, lines 3821-5460
3821Create an Ajax call based on the table's settings, taking into account that 3822 * parameters can have multiple forms, and backwards compatibility. 3823 * 3824 * @param {object} oSettings dataTables settings object 3825 * @param {array} data Data to send to the server, required by 3826 * DataTables - may be augmented by developer callbacks 3827 * @param {function} fn Callback function to run when data is obtained 3828 */ 3829 function _fnBuildAjax( oSettings, data, fn ) 3830 { 3831 // Compatibility with 1.9-, allow fnServerData and event to manipulate 3832 _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] ); 3833 3834 // Convert to object based for 1.10+ if using the old array scheme which can 3835 // come from server-side processing or serverParams 3836 if ( data && $.isArray(data) ) { 3837 var tmp = {}; 3838 var rbracket = /(.*?)\[\]$/; 3839 3840 $.each( data, function (key, val) { 3841 var match = val.name.match(rbracket); 3842 3843 if ( match ) { 3844 // Support for arrays 3845 var name = match[0]; 3846 3847 if ( ! tmp[ name ] ) { 3848 tmp[ name ] = []; 3849 } 3850 tmp[ name ].push( val.value ); 3851 } 3852 else { 3853 tmp[val.name] = val.value; 3854 } 3855 } ); 3856 data = tmp; 3857 } 3858 3859 var ajaxData; 3860 var ajax = oSettings.ajax; 3861 var instance = oSettings.oInstance; 3862 var callback = function ( json ) { 3863 _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] ); 3864 fn( json ); 3865 }; 3866 3867 if ( $.isPlainObject( ajax ) && ajax.data ) 3868 { 3869 ajaxData = ajax.data; 3870 3871 var newData = typeof ajaxData === 'function' ? 3872 ajaxData( data, oSettings ) : // fn can manipulate data or return 3873 ajaxData; // an object object or array to merge 3874 3875 // If the function returned something, use that alone 3876 data = typeof ajaxData === 'function' && newData ? 3877 newData : 3878 $.extend( true, data, newData ); 3879 3880 // Remove the data property as we've resolved it already and don't want 3881 // jQuery to do it again (it is restored at the end of the function) 3882 delete ajax.data; 3883 } 3884 3885 var baseAjax = { 3886 "data": data, 3887 "success": function (json) { 3888 var error = json.error || json.sError; 3889 if ( error ) { 3890 _fnLog( oSettings, 0, error ); 3891 } 3892 3893 oSettings.json = json; 3894 callback( json ); 3895 }, 3896 "dataType": "json", 3897 "cache": false, 3898 "type": oSettings.sServerMethod, 3899 "error": function (xhr, error, thrown) { 3900 var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] ); 3901 3902 if ( $.inArray( true, ret ) === -1 ) { 3903 if ( error == "parsererror" ) { 3904 _fnLog( oSettings, 0, 'Invalid JSON response', 1 ); 3905 } 3906 else if ( xhr.readyState === 4 ) { 3907 _fnLog( oSettings, 0, 'Ajax error', 7 ); 3908 } 3909 } 3910 3911 _fnProcessingDisplay( oSettings, false ); 3912 } 3913 }; 3914 3915 // Store the data submitted for the API 3916 oSettings.oAjaxData = data; 3917 3918 // Allow plug-ins and external processes to modify the data 3919 _fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] ); 3920 3921 if ( oSettings.fnServerData ) 3922 { 3923 // DataTables 1.9- compatibility 3924 oSettings.fnServerData.call( instance, 3925 oSettings.sAjaxSource, 3926 $.map( data, function (val, key) { // Need to convert back to 1.9 trad format 3927 return { name: key, value: val }; 3928 } ), 3929 callback, 3930 oSettings 3931 ); 3932 } 3933 else if ( oSettings.sAjaxSource || typeof ajax === 'string' ) 3934 { 3935 // DataTables 1.9- compatibility 3936 oSettings.jqXHR = $.ajax( $.extend( baseAjax, { 3937 url: ajax || oSettings.sAjaxSource 3938 } ) ); 3939 } 3940 else if ( typeof ajax === 'function' ) 3941 { 3942 // Is a function - let the caller define what needs to be done 3943 oSettings.jqXHR = ajax.call( instance, data, callback, oSettings ); 3944 } 3945 else 3946 { 3947 // Object to extend the base settings 3948 oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) ); 3949 3950 // Restore for next time around 3951 ajax.data = ajaxData; 3952 } 3953 } 3954 3955 3956 /** 3957 * Update the table using an Ajax call 3958 * @param {object} settings dataTables settings object 3959 * @returns {boolean} Block the table drawing or not 3960 * @memberof DataTable#oApi 3961 */ 3962 function _fnAjaxUpdate( settings ) 3963 { 3964 if ( settings.bAjaxDataGet ) { 3965 settings.iDraw++; 3966 _fnProcessingDisplay( settings, true ); 3967 3968 _fnBuildAjax( 3969 settings, 3970 _fnAjaxParameters( settings ), 3971 function(json) { 3972 _fnAjaxUpdateDraw( settings, json ); 3973 } 3974 ); 3975 3976 return false; 3977 } 3978 return true; 3979 } 3980 3981 3982 /** 3983 * Build up the parameters in an object needed for a server-side processing 3984 * request. Note that this is basically done twice, is different ways - a modern 3985 * method which is used by default in DataTables 1.10 which uses objects and 3986 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if 3987 * the sAjaxSource option is used in the initialisation, or the legacyAjax 3988 * option is set. 3989 * @param {object} oSettings dataTables settings object 3990 * @returns {bool} block the table drawing or not 3991 * @memberof DataTable#oApi 3992 */ 3993 function _fnAjaxParameters( settings ) 3994 { 3995 var 3996 columns = settings.aoColumns, 3997 columnCount = columns.length, 3998 features = settings.oFeatures, 3999 preSearch = settings.oPreviousSearch, 4000 preColSearch = settings.aoPreSearchCols, 4001 i, data = [], dataProp, column, columnSearch, 4002 sort = _fnSortFlatten( settings ), 4003 displayStart = settings._iDisplayStart, 4004 displayLength = features.bPaginate !== false ? 4005 settings._iDisplayLength : 4006 -1; 4007 4008 var param = function ( name, value ) { 4009 data.push( { 'name': name, 'value': value } ); 4010 }; 4011 4012 // DataTables 1.9- compatible method 4013 param( 'sEcho', settings.iDraw ); 4014 param( 'iColumns', columnCount ); 4015 param( 'sColumns', _pluck( columns, 'sName' ).join(',') ); 4016 param( 'iDisplayStart', displayStart ); 4017 param( 'iDisplayLength', displayLength ); 4018 4019 // DataTables 1.10+ method 4020 var d = { 4021 draw: settings.iDraw, 4022 columns: [], 4023 order: [], 4024 start: displayStart, 4025 length: displayLength, 4026 search: { 4027 value: preSearch.sSearch, 4028 regex: preSearch.bRegex 4029 } 4030 }; 4031 4032 for ( i=0 ; i<columnCount ; i++ ) { 4033 column = columns[i]; 4034 columnSearch = preColSearch[i]; 4035 dataProp = typeof column.mData=="function" ? 'function' : column.mData ; 4036 4037 d.columns.push( { 4038 data: dataProp, 4039 name: column.sName, 4040 searchable: column.bSearchable, 4041 orderable: column.bSortable, 4042 search: { 4043 value: columnSearch.sSearch, 4044 regex: columnSearch.bRegex 4045 } 4046 } ); 4047 4048 param( "mDataProp_"+i, dataProp ); 4049 4050 if ( features.bFilter ) { 4051 param( 'sSearch_'+i, columnSearch.sSearch ); 4052 param( 'bRegex_'+i, columnSearch.bRegex ); 4053 param( 'bSearchable_'+i, column.bSearchable ); 4054 } 4055 4056 if ( features.bSort ) { 4057 param( 'bSortable_'+i, column.bSortable ); 4058 } 4059 } 4060 4061 if ( features.bFilter ) { 4062 param( 'sSearch', preSearch.sSearch ); 4063 param( 'bRegex', preSearch.bRegex ); 4064 } 4065 4066 if ( features.bSort ) { 4067 $.each( sort, function ( i, val ) { 4068 d.order.push( { column: val.col, dir: val.dir } ); 4069 4070 param( 'iSortCol_'+i, val.col ); 4071 param( 'sSortDir_'+i, val.dir ); 4072 } ); 4073 4074 param( 'iSortingCols', sort.length ); 4075 } 4076 4077 // If the legacy.ajax parameter is null, then we automatically decide which 4078 // form to use, based on sAjaxSource 4079 var legacy = DataTable.ext.legacy.ajax; 4080 if ( legacy === null ) { 4081 return settings.sAjaxSource ? data : d; 4082 } 4083 4084 // Otherwise, if legacy has been specified then we use that to decide on the 4085 // form 4086 return legacy ? data : d; 4087 } 4088 4089 4090 /** 4091 * Data the data from the server (nuking the old) and redraw the table 4092 * @param {object} oSettings dataTables settings object 4093 * @param {object} json json data return from the server. 4094 * @param {string} json.sEcho Tracking flag for DataTables to match requests 4095 * @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering 4096 * @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering 4097 * @param {array} json.aaData The data to display on this page 4098 * @param {string} [json.sColumns] Column ordering (sName, comma separated) 4099 * @memberof DataTable#oApi 4100 */ 4101 function _fnAjaxUpdateDraw ( settings, json ) 4102 { 4103 // v1.10 uses camelCase variables, while 1.9 uses Hungarian notation. 4104 // Support both 4105 var compat = function ( old, modern ) { 4106 return json[old] !== undefined ? json[old] : json[modern]; 4107 }; 4108 4109 var data = _fnAjaxDataSrc( settings, json ); 4110 var draw = compat( 'sEcho', 'draw' ); 4111 var recordsTotal = compat( 'iTotalRecords', 'recordsTotal' ); 4112 var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' ); 4113 4114 if ( draw ) { 4115 // Protect against out of sequence returns 4116 if ( draw*1 < settings.iDraw ) { 4117 return; 4118 } 4119 settings.iDraw = draw * 1; 4120 } 4121 4122 _fnClearTable( settings ); 4123 settings._iRecordsTotal = parseInt(recordsTotal, 10); 4124 settings._iRecordsDisplay = parseInt(recordsFiltered, 10); 4125 4126 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 4127 _fnAddData( settings, data[i] ); 4128 } 4129 settings.aiDisplay = settings.aiDisplayMaster.slice(); 4130 4131 settings.bAjaxDataGet = false; 4132 _fnDraw( settings ); 4133 4134 if ( ! settings._bInitComplete ) { 4135 _fnInitComplete( settings, json ); 4136 } 4137 4138 settings.bAjaxDataGet = true; 4139 _fnProcessingDisplay( settings, false ); 4140 } 4141 4142 4143 /** 4144 * Get the data from the JSON data source to use for drawing a table. Using 4145 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the 4146 * source object, or from a processing function. 4147 * @param {object} oSettings dataTables settings object 4148 * @param {object} json Data source object / array from the server 4149 * @return {array} Array of data to use 4150 */ 4151 function _fnAjaxDataSrc ( oSettings, json ) 4152 { 4153 var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ? 4154 oSettings.ajax.dataSrc : 4155 oSettings.sAjaxDataProp; // Compatibility with 1.9-. 4156 4157 // Compatibility with 1.9-. In order to read from aaData, check if the 4158 // default has been changed, if not, check for aaData 4159 if ( dataSrc === 'data' ) { 4160 return json.aaData || json[dataSrc]; 4161 } 4162 4163 return dataSrc !== "" ? 4164 _fnGetObjectDataFn( dataSrc )( json ) : 4165 json; 4166 } 4167 4168 /** 4169 * Generate the node required for filtering text 4170 * @returns {node} Filter control element 4171 * @param {object} oSettings dataTables settings object 4172 * @memberof DataTable#oApi 4173 */ 4174 function _fnFeatureHtmlFilter ( settings ) 4175 { 4176 var classes = settings.oClasses; 4177 var tableId = settings.sTableId; 4178 var language = settings.oLanguage; 4179 var previousSearch = settings.oPreviousSearch; 4180 var features = settings.aanFeatures; 4181 var input = '<input type="search" class="'+classes.sFilterInput+'"/>'; 4182 4183 var str = language.sSearch; 4184 str = str.match(/_INPUT_/) ? 4185 str.replace('_INPUT_', input) : 4186 str+input; 4187 4188 var filter = $('<div/>', { 4189 'id': ! features.f ? tableId+'_filter' : null, 4190 'class': classes.sFilter 4191 } ) 4192 .append( $('<label/>' ).append( str ) ); 4193 4194 var searchFn = function() { 4195 /* Update all other filter input elements for the new display */ 4196 var n = features.f; 4197 var val = !this.value ? "" : this.value; // mental IE8 fix :-( 4198 4199 /* Now do the filter */ 4200 if ( val != previousSearch.sSearch ) { 4201 _fnFilterComplete( settings, { 4202 "sSearch": val, 4203 "bRegex": previousSearch.bRegex, 4204 "bSmart": previousSearch.bSmart , 4205 "bCaseInsensitive": previousSearch.bCaseInsensitive 4206 } ); 4207 4208 // Need to redraw, without resorting 4209 settings._iDisplayStart = 0; 4210 _fnDraw( settings ); 4211 } 4212 }; 4213 4214 var searchDelay = settings.searchDelay !== null ? 4215 settings.searchDelay : 4216 _fnDataSource( settings ) === 'ssp' ? 4217 400 : 4218 0; 4219 4220 var jqFilter = $('input', filter) 4221 .val( previousSearch.sSearch ) 4222 .attr( 'placeholder', language.sSearchPlaceholder ) 4223 .on( 4224 'keyup.DT search.DT input.DT paste.DT cut.DT', 4225 searchDelay ? 4226 _fnThrottle( searchFn, searchDelay ) : 4227 searchFn 4228 ) 4229 .on( 'keypress.DT', function(e) { 4230 /* Prevent form submission */ 4231 if ( e.keyCode == 13 ) { 4232 return false; 4233 } 4234 } ) 4235 .attr('aria-controls', tableId); 4236 4237 // Update the input elements whenever the table is filtered 4238 $(settings.nTable).on( 'search.dt.DT', function ( ev, s ) { 4239 if ( settings === s ) { 4240 // IE9 throws an 'unknown error' if document.activeElement is used 4241 // inside an iframe or frame... 4242 try { 4243 if ( jqFilter[0] !== document.activeElement ) { 4244 jqFilter.val( previousSearch.sSearch ); 4245 } 4246 } 4247 catch ( e ) {} 4248 } 4249 } ); 4250 4251 return filter[0]; 4252 } 4253 4254 4255 /** 4256 * Filter the table using both the global filter and column based filtering 4257 * @param {object} oSettings dataTables settings object 4258 * @param {object} oSearch search information 4259 * @param {int} [iForce] force a research of the master array (1) or not (undefined or 0) 4260 * @memberof DataTable#oApi 4261 */ 4262 function _fnFilterComplete ( oSettings, oInput, iForce ) 4263 { 4264 var oPrevSearch = oSettings.oPreviousSearch; 4265 var aoPrevSearch = oSettings.aoPreSearchCols; 4266 var fnSaveFilter = function ( oFilter ) { 4267 /* Save the filtering values */ 4268 oPrevSearch.sSearch = oFilter.sSearch; 4269 oPrevSearch.bRegex = oFilter.bRegex; 4270 oPrevSearch.bSmart = oFilter.bSmart; 4271 oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive; 4272 }; 4273 var fnRegex = function ( o ) { 4274 // Backwards compatibility with the bEscapeRegex option 4275 return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex; 4276 }; 4277 4278 // Resolve any column types that are unknown due to addition or invalidation 4279 // @todo As per sort - can this be moved into an event handler? 4280 _fnColumnTypes( oSettings ); 4281 4282 /* In server-side processing all filtering is done by the server, so no point hanging around here */ 4283 if ( _fnDataSource( oSettings ) != 'ssp' ) 4284 { 4285 /* Global filter */ 4286 _fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive ); 4287 fnSaveFilter( oInput ); 4288 4289 /* Now do the individual column filter */ 4290 for ( var i=0 ; i<aoPrevSearch.length ; i++ ) 4291 { 4292 _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]), 4293 aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive ); 4294 } 4295 4296 /* Custom filtering */ 4297 _fnFilterCustom( oSettings ); 4298 } 4299 else 4300 { 4301 fnSaveFilter( oInput ); 4302 } 4303 4304 /* Tell the draw function we have been filtering */ 4305 oSettings.bFiltered = true; 4306 _fnCallbackFire( oSettings, null, 'search', [oSettings] ); 4307 } 4308 4309 4310 /** 4311 * Apply custom filtering functions 4312 * @param {object} oSettings dataTables settings object 4313 * @memberof DataTable#oApi 4314 */ 4315 function _fnFilterCustom( settings ) 4316 { 4317 var filters = DataTable.ext.search; 4318 var displayRows = settings.aiDisplay; 4319 var row, rowIdx; 4320 4321 for ( var i=0, ien=filters.length ; i<ien ; i++ ) { 4322 var rows = []; 4323 4324 // Loop over each row and see if it should be included 4325 for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) { 4326 rowIdx = displayRows[ j ]; 4327 row = settings.aoData[ rowIdx ]; 4328 4329 if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) { 4330 rows.push( rowIdx ); 4331 } 4332 } 4333 4334 // So the array reference doesn't break set the results into the 4335 // existing array 4336 displayRows.length = 0; 4337 $.merge( displayRows, rows ); 4338 } 4339 } 4340 4341 4342 /** 4343 * Filter the table on a per-column basis 4344 * @param {object} oSettings dataTables settings object 4345 * @param {string} sInput string to filter on 4346 * @param {int} iColumn column to filter 4347 * @param {bool} bRegex treat search string as a regular expression or not 4348 * @param {bool} bSmart use smart filtering or not 4349 * @param {bool} bCaseInsensitive Do case insenstive matching or not 4350 * @memberof DataTable#oApi 4351 */ 4352 function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive ) 4353 { 4354 if ( searchStr === '' ) { 4355 return; 4356 } 4357 4358 var data; 4359 var out = []; 4360 var display = settings.aiDisplay; 4361 var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive ); 4362 4363 for ( var i=0 ; i<display.length ; i++ ) { 4364 data = settings.aoData[ display[i] ]._aFilterData[ colIdx ]; 4365 4366 if ( rpSearch.test( data ) ) { 4367 out.push( display[i] ); 4368 } 4369 } 4370 4371 settings.aiDisplay = out; 4372 } 4373 4374 4375 /** 4376 * Filter the data table based on user input and draw the table 4377 * @param {object} settings dataTables settings object 4378 * @param {string} input string to filter on 4379 * @param {int} force optional - force a research of the master array (1) or not (undefined or 0) 4380 * @param {bool} regex treat as a regular expression or not 4381 * @param {bool} smart perform smart filtering or not 4382 * @param {bool} caseInsensitive Do case insenstive matching or not 4383 * @memberof DataTable#oApi 4384 */ 4385 function _fnFilter( settings, input, force, regex, smart, caseInsensitive ) 4386 { 4387 var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive ); 4388 var prevSearch = settings.oPreviousSearch.sSearch; 4389 var displayMaster = settings.aiDisplayMaster; 4390 var display, invalidated, i; 4391 var filtered = []; 4392 4393 // Need to take account of custom filtering functions - always filter 4394 if ( DataTable.ext.search.length !== 0 ) { 4395 force = true; 4396 } 4397 4398 // Check if any of the rows were invalidated 4399 invalidated = _fnFilterData( settings ); 4400 4401 // If the input is blank - we just want the full data set 4402 if ( input.length <= 0 ) { 4403 settings.aiDisplay = displayMaster.slice(); 4404 } 4405 else { 4406 // New search - start from the master array 4407 if ( invalidated || 4408 force || 4409 prevSearch.length > input.length || 4410 input.indexOf(prevSearch) !== 0 || 4411 settings.bSorted // On resort, the display master needs to be 4412 // re-filtered since indexes will have changed 4413 ) { 4414 settings.aiDisplay = displayMaster.slice(); 4415 } 4416 4417 // Search the display array 4418 display = settings.aiDisplay; 4419 4420 for ( i=0 ; i<display.length ; i++ ) { 4421 if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) { 4422 filtered.push( display[i] ); 4423 } 4424 } 4425 4426 settings.aiDisplay = filtered; 4427 } 4428 } 4429 4430 4431 /** 4432 * Build a regular expression object suitable for searching a table 4433 * @param {string} sSearch string to search for 4434 * @param {bool} bRegex treat as a regular expression or not 4435 * @param {bool} bSmart perform smart filtering or not 4436 * @param {bool} bCaseInsensitive Do case insensitive matching or not 4437 * @returns {RegExp} constructed object 4438 * @memberof DataTable#oApi 4439 */ 4440 function _fnFilterCreateSearch( search, regex, smart, caseInsensitive ) 4441 { 4442 search = regex ? 4443 search : 4444 _fnEscapeRegex( search ); 4445 4446 if ( smart ) { 4447 /* For smart filtering we want to allow the search to work regardless of 4448 * word order. We also want double quoted text to be preserved, so word 4449 * order is important - a la google. So this is what we want to 4450 * generate: 4451 * 4452 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$ 4453 */ 4454 var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) { 4455 if ( word.charAt(0) === '"' ) { 4456 var m = word.match( /^"(.*)"$/ ); 4457 word = m ? m[1] : word; 4458 } 4459 4460 return word.replace('"', ''); 4461 } ); 4462 4463 search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$'; 4464 } 4465 4466 return new RegExp( search, caseInsensitive ? 'i' : '' ); 4467 } 4468 4469 4470 /** 4471 * Escape a string such that it can be used in a regular expression 4472 * @param {string} sVal string to escape 4473 * @returns {string} escaped string 4474 * @memberof DataTable#oApi 4475 */ 4476 var _fnEscapeRegex = DataTable.util.escapeRegex; 4477 4478 var __filter_div = $('<div>')[0]; 4479 var __filter_div_textContent = __filter_div.textContent !== undefined; 4480 4481 // Update the filtering data for each row if needed (by invalidation or first run) 4482 function _fnFilterData ( settings ) 4483 { 4484 var columns = settings.aoColumns; 4485 var column; 4486 var i, j, ien, jen, filterData, cellData, row; 4487 var fomatters = DataTable.ext.type.search; 4488 var wasInvalidated = false; 4489 4490 for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 4491 row = settings.aoData[i]; 4492 4493 if ( ! row._aFilterData ) { 4494 filterData = []; 4495 4496 for ( j=0, jen=columns.length ; j<jen ; j++ ) { 4497 column = columns[j]; 4498 4499 if ( column.bSearchable ) { 4500 cellData = _fnGetCellData( settings, i, j, 'filter' ); 4501 4502 if ( fomatters[ column.sType ] ) { 4503 cellData = fomatters[ column.sType ]( cellData ); 4504 } 4505 4506 // Search in DataTables 1.10 is string based. In 1.11 this 4507 // should be altered to also allow strict type checking. 4508 if ( cellData === null ) { 4509 cellData = ''; 4510 } 4511 4512 if ( typeof cellData !== 'string' && cellData.toString ) { 4513 cellData = cellData.toString(); 4514 } 4515 } 4516 else { 4517 cellData = ''; 4518 } 4519 4520 // If it looks like there is an HTML entity in the string, 4521 // attempt to decode it so sorting works as expected. Note that 4522 // we could use a single line of jQuery to do this, but the DOM 4523 // method used here is much faster http://jsperf.com/html-decode 4524 if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) { 4525 __filter_div.innerHTML = cellData; 4526 cellData = __filter_div_textContent ? 4527 __filter_div.textContent : 4528 __filter_div.innerText; 4529 } 4530 4531 if ( cellData.replace ) { 4532 cellData = cellData.replace(/[\r\n]/g, ''); 4533 } 4534 4535 filterData.push( cellData ); 4536 } 4537 4538 row._aFilterData = filterData; 4539 row._sFilterRow = filterData.join(' '); 4540 wasInvalidated = true; 4541 } 4542 } 4543 4544 return wasInvalidated; 4545 } 4546 4547 4548 /** 4549 * Convert from the internal Hungarian notation to camelCase for external 4550 * interaction 4551 * @param {object} obj Object to convert 4552 * @returns {object} Inverted object 4553 * @memberof DataTable#oApi 4554 */ 4555 function _fnSearchToCamel ( obj ) 4556 { 4557 return { 4558 search: obj.sSearch, 4559 smart: obj.bSmart, 4560 regex: obj.bRegex, 4561 caseInsensitive: obj.bCaseInsensitive 4562 }; 4563 } 4564 4565 4566 4567 /** 4568 * Convert from camelCase notation to the internal Hungarian. We could use the 4569 * Hungarian convert function here, but this is cleaner 4570 * @param {object} obj Object to convert 4571 * @returns {object} Inverted object 4572 * @memberof DataTable#oApi 4573 */ 4574 function _fnSearchToHung ( obj ) 4575 { 4576 return { 4577 sSearch: obj.search, 4578 bSmart: obj.smart, 4579 bRegex: obj.regex, 4580 bCaseInsensitive: obj.caseInsensitive 4581 }; 4582 } 4583 4584 /** 4585 * Generate the node required for the info display 4586 * @param {object} oSettings dataTables settings object 4587 * @returns {node} Information element 4588 * @memberof DataTable#oApi 4589 */ 4590 function _fnFeatureHtmlInfo ( settings ) 4591 { 4592 var 4593 tid = settings.sTableId, 4594 nodes = settings.aanFeatures.i, 4595 n = $('<div/>', { 4596 'class': settings.oClasses.sInfo, 4597 'id': ! nodes ? tid+'_info' : null 4598 } ); 4599 4600 if ( ! nodes ) { 4601 // Update display on each draw 4602 settings.aoDrawCallback.push( { 4603 "fn": _fnUpdateInfo, 4604 "sName": "information" 4605 } ); 4606 4607 n 4608 .attr( 'role', 'status' ) 4609 .attr( 'aria-live', 'polite' ); 4610 4611 // Table is described by our info div 4612 $(settings.nTable).attr( 'aria-describedby', tid+'_info' ); 4613 } 4614 4615 return n[0]; 4616 } 4617 4618 4619 /** 4620 * Update the information elements in the display 4621 * @param {object} settings dataTables settings object 4622 * @memberof DataTable#oApi 4623 */ 4624 function _fnUpdateInfo ( settings ) 4625 { 4626 /* Show information about the table */ 4627 var nodes = settings.aanFeatures.i; 4628 if ( nodes.length === 0 ) { 4629 return; 4630 } 4631 4632 var 4633 lang = settings.oLanguage, 4634 start = settings._iDisplayStart+1, 4635 end = settings.fnDisplayEnd(), 4636 max = settings.fnRecordsTotal(), 4637 total = settings.fnRecordsDisplay(), 4638 out = total ? 4639 lang.sInfo : 4640 lang.sInfoEmpty; 4641 4642 if ( total !== max ) { 4643 /* Record set after filtering */ 4644 out += ' ' + lang.sInfoFiltered; 4645 } 4646 4647 // Convert the macros 4648 out += lang.sInfoPostFix; 4649 out = _fnInfoMacros( settings, out ); 4650 4651 var callback = lang.fnInfoCallback; 4652 if ( callback !== null ) { 4653 out = callback.call( settings.oInstance, 4654 settings, start, end, max, total, out 4655 ); 4656 } 4657 4658 $(nodes).html( out ); 4659 } 4660 4661 4662 function _fnInfoMacros ( settings, str ) 4663 { 4664 // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only 4665 // internally 4666 var 4667 formatter = settings.fnFormatNumber, 4668 start = settings._iDisplayStart+1, 4669 len = settings._iDisplayLength, 4670 vis = settings.fnRecordsDisplay(), 4671 all = len === -1; 4672 4673 return str. 4674 replace(/_START_/g, formatter.call( settings, start ) ). 4675 replace(/_END_/g, formatter.call( settings, settings.fnDisplayEnd() ) ). 4676 replace(/_MAX_/g, formatter.call( settings, settings.fnRecordsTotal() ) ). 4677 replace(/_TOTAL_/g, formatter.call( settings, vis ) ). 4678 replace(/_PAGE_/g, formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ). 4679 replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) ); 4680 } 4681 4682 4683 4684 /** 4685 * Draw the table for the first time, adding all required features 4686 * @param {object} settings dataTables settings object 4687 * @memberof DataTable#oApi 4688 */ 4689 function _fnInitialise ( settings ) 4690 { 4691 var i, iLen, iAjaxStart=settings.iInitDisplayStart; 4692 var columns = settings.aoColumns, column; 4693 var features = settings.oFeatures; 4694 var deferLoading = settings.bDeferLoading; // value modified by the draw 4695 4696 /* Ensure that the table data is fully initialised */ 4697 if ( ! settings.bInitialised ) { 4698 setTimeout( function(){ _fnInitialise( settings ); }, 200 ); 4699 return; 4700 } 4701 4702 /* Show the display HTML options */ 4703 _fnAddOptionsHtml( settings ); 4704 4705 /* Build and draw the header / footer for the table */ 4706 _fnBuildHead( settings ); 4707 _fnDrawHead( settings, settings.aoHeader ); 4708 _fnDrawHead( settings, settings.aoFooter ); 4709 4710 /* Okay to show that something is going on now */ 4711 _fnProcessingDisplay( settings, true ); 4712 4713 /* Calculate sizes for columns */ 4714 if ( features.bAutoWidth ) { 4715 _fnCalculateColumnWidths( settings ); 4716 } 4717 4718 for ( i=0, iLen=columns.length ; i<iLen ; i++ ) { 4719 column = columns[i]; 4720 4721 if ( column.sWidth ) { 4722 column.nTh.style.width = _fnStringToCss( column.sWidth ); 4723 } 4724 } 4725 4726 _fnCallbackFire( settings, null, 'preInit', [settings] ); 4727 4728 // If there is default sorting required - let's do it. The sort function 4729 // will do the drawing for us. Otherwise we draw the table regardless of the 4730 // Ajax source - this allows the table to look initialised for Ajax sourcing 4731 // data (show 'loading' message possibly) 4732 _fnReDraw( settings ); 4733 4734 // Server-side processing init complete is done by _fnAjaxUpdateDraw 4735 var dataSrc = _fnDataSource( settings ); 4736 if ( dataSrc != 'ssp' || deferLoading ) { 4737 // if there is an ajax source load the data 4738 if ( dataSrc == 'ajax' ) { 4739 _fnBuildAjax( settings, [], function(json) { 4740 var aData = _fnAjaxDataSrc( settings, json ); 4741 4742 // Got the data - add it to the table 4743 for ( i=0 ; i<aData.length ; i++ ) { 4744 _fnAddData( settings, aData[i] ); 4745 } 4746 4747 // Reset the init display for cookie saving. We've already done 4748 // a filter, and therefore cleared it before. So we need to make 4749 // it appear 'fresh' 4750 settings.iInitDisplayStart = iAjaxStart; 4751 4752 _fnReDraw( settings ); 4753 4754 _fnProcessingDisplay( settings, false ); 4755 _fnInitComplete( settings, json ); 4756 }, settings ); 4757 } 4758 else { 4759 _fnProcessingDisplay( settings, false ); 4760 _fnInitComplete( settings ); 4761 } 4762 } 4763 } 4764 4765 4766 /** 4767 * Draw the table for the first time, adding all required features 4768 * @param {object} oSettings dataTables settings object 4769 * @param {object} [json] JSON from the server that completed the table, if using Ajax source 4770 * with client-side processing (optional) 4771 * @memberof DataTable#oApi 4772 */ 4773 function _fnInitComplete ( settings, json ) 4774 { 4775 settings._bInitComplete = true; 4776 4777 // When data was added after the initialisation (data or Ajax) we need to 4778 // calculate the column sizing 4779 if ( json || settings.oInit.aaData ) { 4780 _fnAdjustColumnSizing( settings ); 4781 } 4782 4783 _fnCallbackFire( settings, null, 'plugin-init', [settings, json] ); 4784 _fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] ); 4785 } 4786 4787 4788 function _fnLengthChange ( settings, val ) 4789 { 4790 var len = parseInt( val, 10 ); 4791 settings._iDisplayLength = len; 4792 4793 _fnLengthOverflow( settings ); 4794 4795 // Fire length change event 4796 _fnCallbackFire( settings, null, 'length', [settings, len] ); 4797 } 4798 4799 4800 /** 4801 * Generate the node required for user display length changing 4802 * @param {object} settings dataTables settings object 4803 * @returns {node} Display length feature node 4804 * @memberof DataTable#oApi 4805 */ 4806 function _fnFeatureHtmlLength ( settings ) 4807 { 4808 var 4809 classes = settings.oClasses, 4810 tableId = settings.sTableId, 4811 menu = settings.aLengthMenu, 4812 d2 = $.isArray( menu[0] ), 4813 lengths = d2 ? menu[0] : menu, 4814 language = d2 ? menu[1] : menu; 4815 4816 var select = $('<select/>', { 4817 'name': tableId+'_length', 4818 'aria-controls': tableId, 4819 'class': classes.sLengthSelect 4820 } ); 4821 4822 for ( var i=0, ien=lengths.length ; i<ien ; i++ ) { 4823 select[0][ i ] = new Option( 4824 typeof language[i] === 'number' ? 4825 settings.fnFormatNumber( language[i] ) : 4826 language[i], 4827 lengths[i] 4828 ); 4829 } 4830 4831 var div = $('<div><label/></div>').addClass( classes.sLength ); 4832 if ( ! settings.aanFeatures.l ) { 4833 div[0].id = tableId+'_length'; 4834 } 4835 4836 div.children().append( 4837 settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML ) 4838 ); 4839 4840 // Can't use `select` variable as user might provide their own and the 4841 // reference is broken by the use of outerHTML 4842 $('select', div) 4843 .val( settings._iDisplayLength ) 4844 .on( 'change.DT', function(e) { 4845 _fnLengthChange( settings, $(this).val() ); 4846 _fnDraw( settings ); 4847 } ); 4848 4849 // Update node value whenever anything changes the table's length 4850 $(settings.nTable).on( 'length.dt.DT', function (e, s, len) { 4851 if ( settings === s ) { 4852 $('select', div).val( len ); 4853 } 4854 } ); 4855 4856 return div[0]; 4857 } 4858 4859 4860 4861 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 4862 * Note that most of the paging logic is done in 4863 * DataTable.ext.pager 4864 */ 4865 4866 /** 4867 * Generate the node required for default pagination 4868 * @param {object} oSettings dataTables settings object 4869 * @returns {node} Pagination feature node 4870 * @memberof DataTable#oApi 4871 */ 4872 function _fnFeatureHtmlPaginate ( settings ) 4873 { 4874 var 4875 type = settings.sPaginationType, 4876 plugin = DataTable.ext.pager[ type ], 4877 modern = typeof plugin === 'function', 4878 redraw = function( settings ) { 4879 _fnDraw( settings ); 4880 }, 4881 node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0], 4882 features = settings.aanFeatures; 4883 4884 if ( ! modern ) { 4885 plugin.fnInit( settings, node, redraw ); 4886 } 4887 4888 /* Add a draw callback for the pagination on first instance, to update the paging display */ 4889 if ( ! features.p ) 4890 { 4891 node.id = settings.sTableId+'_paginate'; 4892 4893 settings.aoDrawCallback.push( { 4894 "fn": function( settings ) { 4895 if ( modern ) { 4896 var 4897 start = settings._iDisplayStart, 4898 len = settings._iDisplayLength, 4899 visRecords = settings.fnRecordsDisplay(), 4900 all = len === -1, 4901 page = all ? 0 : Math.ceil( start / len ), 4902 pages = all ? 1 : Math.ceil( visRecords / len ), 4903 buttons = plugin(page, pages), 4904 i, ien; 4905 4906 for ( i=0, ien=features.p.length ; i<ien ; i++ ) { 4907 _fnRenderer( settings, 'pageButton' )( 4908 settings, features.p[i], i, buttons, page, pages 4909 ); 4910 } 4911 } 4912 else { 4913 plugin.fnUpdate( settings, redraw ); 4914 } 4915 }, 4916 "sName": "pagination" 4917 } ); 4918 } 4919 4920 return node; 4921 } 4922 4923 4924 /** 4925 * Alter the display settings to change the page 4926 * @param {object} settings DataTables settings object 4927 * @param {string|int} action Paging action to take: "first", "previous", 4928 * "next" or "last" or page number to jump to (integer) 4929 * @param [bool] redraw Automatically draw the update or not 4930 * @returns {bool} true page has changed, false - no change 4931 * @memberof DataTable#oApi 4932 */ 4933 function _fnPageChange ( settings, action, redraw ) 4934 { 4935 var 4936 start = settings._iDisplayStart, 4937 len = settings._iDisplayLength, 4938 records = settings.fnRecordsDisplay(); 4939 4940 if ( records === 0 || len === -1 ) 4941 { 4942 start = 0; 4943 } 4944 else if ( typeof action === "number" ) 4945 { 4946 start = action * len; 4947 4948 if ( start > records ) 4949 { 4950 start = 0; 4951 } 4952 } 4953 else if ( action == "first" ) 4954 { 4955 start = 0; 4956 } 4957 else if ( action == "previous" ) 4958 { 4959 start = len >= 0 ? 4960 start - len : 4961 0; 4962 4963 if ( start < 0 ) 4964 { 4965 start = 0; 4966 } 4967 } 4968 else if ( action == "next" ) 4969 { 4970 if ( start + len < records ) 4971 { 4972 start += len; 4973 } 4974 } 4975 else if ( action == "last" ) 4976 { 4977 start = Math.floor( (records-1) / len) * len; 4978 } 4979 else 4980 { 4981 _fnLog( settings, 0, "Unknown paging action: "+action, 5 ); 4982 } 4983 4984 var changed = settings._iDisplayStart !== start; 4985 settings._iDisplayStart = start; 4986 4987 if ( changed ) { 4988 _fnCallbackFire( settings, null, 'page', [settings] ); 4989 4990 if ( redraw ) { 4991 _fnDraw( settings ); 4992 } 4993 } 4994 4995 return changed; 4996 } 4997 4998 4999 5000 /** 5001 * Generate the node required for the processing node 5002 * @param {object} settings dataTables settings object 5003 * @returns {node} Processing element 5004 * @memberof DataTable#oApi 5005 */ 5006 function _fnFeatureHtmlProcessing ( settings ) 5007 { 5008 return $('<div/>', { 5009 'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null, 5010 'class': settings.oClasses.sProcessing 5011 } ) 5012 .html( settings.oLanguage.sProcessing ) 5013 .insertBefore( settings.nTable )[0]; 5014 } 5015 5016 5017 /** 5018 * Display or hide the processing indicator 5019 * @param {object} settings dataTables settings object 5020 * @param {bool} show Show the processing indicator (true) or not (false) 5021 * @memberof DataTable#oApi 5022 */ 5023 function _fnProcessingDisplay ( settings, show ) 5024 { 5025 if ( settings.oFeatures.bProcessing ) { 5026 $(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' ); 5027 } 5028 5029 _fnCallbackFire( settings, null, 'processing', [settings, show] ); 5030 } 5031 5032 /** 5033 * Add any control elements for the table - specifically scrolling 5034 * @param {object} settings dataTables settings object 5035 * @returns {node} Node to add to the DOM 5036 * @memberof DataTable#oApi 5037 */ 5038 function _fnFeatureHtmlTable ( settings ) 5039 { 5040 var table = $(settings.nTable); 5041 5042 // Add the ARIA grid role to the table 5043 table.attr( 'role', 'grid' ); 5044 5045 // Scrolling from here on in 5046 var scroll = settings.oScroll; 5047 5048 if ( scroll.sX === '' && scroll.sY === '' ) { 5049 return settings.nTable; 5050 } 5051 5052 var scrollX = scroll.sX; 5053 var scrollY = scroll.sY; 5054 var classes = settings.oClasses; 5055 var caption = table.children('caption'); 5056 var captionSide = caption.length ? caption[0]._captionSide : null; 5057 var headerClone = $( table[0].cloneNode(false) ); 5058 var footerClone = $( table[0].cloneNode(false) ); 5059 var footer = table.children('tfoot'); 5060 var _div = '<div/>'; 5061 var size = function ( s ) { 5062 return !s ? null : _fnStringToCss( s ); 5063 }; 5064 5065 if ( ! footer.length ) { 5066 footer = null; 5067 } 5068 5069 /* 5070 * The HTML structure that we want to generate in this function is: 5071 * div - scroller 5072 * div - scroll head 5073 * div - scroll head inner 5074 * table - scroll head table 5075 * thead - thead 5076 * div - scroll body 5077 * table - table (master table) 5078 * thead - thead clone for sizing 5079 * tbody - tbody 5080 * div - scroll foot 5081 * div - scroll foot inner 5082 * table - scroll foot table 5083 * tfoot - tfoot 5084 */ 5085 var scroller = $( _div, { 'class': classes.sScrollWrapper } ) 5086 .append( 5087 $(_div, { 'class': classes.sScrollHead } ) 5088 .css( { 5089 overflow: 'hidden', 5090 position: 'relative', 5091 border: 0, 5092 width: scrollX ? size(scrollX) : '100%' 5093 } ) 5094 .append( 5095 $(_div, { 'class': classes.sScrollHeadInner } ) 5096 .css( { 5097 'box-sizing': 'content-box', 5098 width: scroll.sXInner || '100%' 5099 } ) 5100 .append( 5101 headerClone 5102 .removeAttr('id') 5103 .css( 'margin-left', 0 ) 5104 .append( captionSide === 'top' ? caption : null ) 5105 .append( 5106 table.children('thead') 5107 ) 5108 ) 5109 ) 5110 ) 5111 .append( 5112 $(_div, { 'class': classes.sScrollBody } ) 5113 .css( { 5114 position: 'relative', 5115 overflow: 'auto', 5116 width: size( scrollX ) 5117 } ) 5118 .append( table ) 5119 ); 5120 5121 if ( footer ) { 5122 scroller.append( 5123 $(_div, { 'class': classes.sScrollFoot } ) 5124 .css( { 5125 overflow: 'hidden', 5126 border: 0, 5127 width: scrollX ? size(scrollX) : '100%' 5128 } ) 5129 .append( 5130 $(_div, { 'class': classes.sScrollFootInner } ) 5131 .append( 5132 footerClone 5133 .removeAttr('id') 5134 .css( 'margin-left', 0 ) 5135 .append( captionSide === 'bottom' ? caption : null ) 5136 .append( 5137 table.children('tfoot') 5138 ) 5139 ) 5140 ) 5141 ); 5142 } 5143 5144 var children = scroller.children(); 5145 var scrollHead = children[0]; 5146 var scrollBody = children[1]; 5147 var scrollFoot = footer ? children[2] : null; 5148 5149 // When the body is scrolled, then we also want to scroll the headers 5150 if ( scrollX ) { 5151 $(scrollBody).on( 'scroll.DT', function (e) { 5152 var scrollLeft = this.scrollLeft; 5153 5154 scrollHead.scrollLeft = scrollLeft; 5155 5156 if ( footer ) { 5157 scrollFoot.scrollLeft = scrollLeft; 5158 } 5159 } ); 5160 } 5161 5162 $(scrollBody).css( 5163 scrollY && scroll.bCollapse ? 'max-height' : 'height', 5164 scrollY 5165 ); 5166 5167 settings.nScrollHead = scrollHead; 5168 settings.nScrollBody = scrollBody; 5169 settings.nScrollFoot = scrollFoot; 5170 5171 // On redraw - align columns 5172 settings.aoDrawCallback.push( { 5173 "fn": _fnScrollDraw, 5174 "sName": "scrolling" 5175 } ); 5176 5177 return scroller[0]; 5178 } 5179 5180 5181 5182 /** 5183 * Update the header, footer and body tables for resizing - i.e. column 5184 * alignment. 5185 * 5186 * Welcome to the most horrible function DataTables. The process that this 5187 * function follows is basically: 5188 * 1. Re-create the table inside the scrolling div 5189 * 2. Take live measurements from the DOM 5190 * 3. Apply the measurements to align the columns 5191 * 4. Clean up 5192 * 5193 * @param {object} settings dataTables settings object 5194 * @memberof DataTable#oApi 5195 */ 5196 function _fnScrollDraw ( settings ) 5197 { 5198 // Given that this is such a monster function, a lot of variables are use 5199 // to try and keep the minimised size as small as possible 5200 var 5201 scroll = settings.oScroll, 5202 scrollX = scroll.sX, 5203 scrollXInner = scroll.sXInner, 5204 scrollY = scroll.sY, 5205 barWidth = scroll.iBarWidth, 5206 divHeader = $(settings.nScrollHead), 5207 divHeaderStyle = divHeader[0].style, 5208 divHeaderInner = divHeader.children('div'), 5209 divHeaderInnerStyle = divHeaderInner[0].style, 5210 divHeaderTable = divHeaderInner.children('table'), 5211 divBodyEl = settings.nScrollBody, 5212 divBody = $(divBodyEl), 5213 divBodyStyle = divBodyEl.style, 5214 divFooter = $(settings.nScrollFoot), 5215 divFooterInner = divFooter.children('div'), 5216 divFooterTable = divFooterInner.children('table'), 5217 header = $(settings.nTHead), 5218 table = $(settings.nTable), 5219 tableEl = table[0], 5220 tableStyle = tableEl.style, 5221 footer = settings.nTFoot ? $(settings.nTFoot) : null, 5222 browser = settings.oBrowser, 5223 ie67 = browser.bScrollOversize, 5224 dtHeaderCells = _pluck( settings.aoColumns, 'nTh' ), 5225 headerTrgEls, footerTrgEls, 5226 headerSrcEls, footerSrcEls, 5227 headerCopy, footerCopy, 5228 headerWidths=[], footerWidths=[], 5229 headerContent=[], footerContent=[], 5230 idx, correction, sanityWidth, 5231 zeroOut = function(nSizer) { 5232 var style = nSizer.style; 5233 style.paddingTop = "0"; 5234 style.paddingBottom = "0"; 5235 style.borderTopWidth = "0"; 5236 style.borderBottomWidth = "0"; 5237 style.height = 0; 5238 }; 5239 5240 // If the scrollbar visibility has changed from the last draw, we need to 5241 // adjust the column sizes as the table width will have changed to account 5242 // for the scrollbar 5243 var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight; 5244 5245 if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) { 5246 settings.scrollBarVis = scrollBarVis; 5247 _fnAdjustColumnSizing( settings ); 5248 return; // adjust column sizing will call this function again 5249 } 5250 else { 5251 settings.scrollBarVis = scrollBarVis; 5252 } 5253 5254 /* 5255 * 1. Re-create the table inside the scrolling div 5256 */ 5257 5258 // Remove the old minimised thead and tfoot elements in the inner table 5259 table.children('thead, tfoot').remove(); 5260 5261 if ( footer ) { 5262 footerCopy = footer.clone().prependTo( table ); 5263 footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized 5264 footerSrcEls = footerCopy.find('tr'); 5265 } 5266 5267 // Clone the current header and footer elements and then place it into the inner table 5268 headerCopy = header.clone().prependTo( table ); 5269 headerTrgEls = header.find('tr'); // original header is in its own table 5270 headerSrcEls = headerCopy.find('tr'); 5271 headerCopy.find('th, td').removeAttr('tabindex'); 5272 5273 5274 /* 5275 * 2. Take live measurements from the DOM - do not alter the DOM itself! 5276 */ 5277 5278 // Remove old sizing and apply the calculated column widths 5279 // Get the unique column headers in the newly created (cloned) header. We want to apply the 5280 // calculated sizes to this header 5281 if ( ! scrollX ) 5282 { 5283 divBodyStyle.width = '100%'; 5284 divHeader[0].style.width = '100%'; 5285 } 5286 5287 $.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) { 5288 idx = _fnVisibleToColumnIndex( settings, i ); 5289 el.style.width = settings.aoColumns[idx].sWidth; 5290 } ); 5291 5292 if ( footer ) { 5293 _fnApplyToChildren( function(n) { 5294 n.style.width = ""; 5295 }, footerSrcEls ); 5296 } 5297 5298 // Size the table as a whole 5299 sanityWidth = table.outerWidth(); 5300 if ( scrollX === "" ) { 5301 // No x scrolling 5302 tableStyle.width = "100%"; 5303 5304 // IE7 will make the width of the table when 100% include the scrollbar 5305 // - which is shouldn't. When there is a scrollbar we need to take this 5306 // into account. 5307 if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight || 5308 divBody.css('overflow-y') == "scroll") 5309 ) { 5310 tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth); 5311 } 5312 5313 // Recalculate the sanity width 5314 sanityWidth = table.outerWidth(); 5315 } 5316 else if ( scrollXInner !== "" ) { 5317 // legacy x scroll inner has been given - use it 5318 tableStyle.width = _fnStringToCss(scrollXInner); 5319 5320 // Recalculate the sanity width 5321 sanityWidth = table.outerWidth(); 5322 } 5323 5324 // Hidden header should have zero height, so remove padding and borders. Then 5325 // set the width based on the real headers 5326 5327 // Apply all styles in one pass 5328 _fnApplyToChildren( zeroOut, headerSrcEls ); 5329 5330 // Read all widths in next pass 5331 _fnApplyToChildren( function(nSizer) { 5332 headerContent.push( nSizer.innerHTML ); 5333 headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) ); 5334 }, headerSrcEls ); 5335 5336 // Apply all widths in final pass 5337 _fnApplyToChildren( function(nToSize, i) { 5338 // Only apply widths to the DataTables detected header cells - this 5339 // prevents complex headers from having contradictory sizes applied 5340 if ( $.inArray( nToSize, dtHeaderCells ) !== -1 ) { 5341 nToSize.style.width = headerWidths[i]; 5342 } 5343 }, headerTrgEls ); 5344 5345 $(headerSrcEls).height(0); 5346 5347 /* Same again with the footer if we have one */ 5348 if ( footer ) 5349 { 5350 _fnApplyToChildren( zeroOut, footerSrcEls ); 5351 5352 _fnApplyToChildren( function(nSizer) { 5353 footerContent.push( nSizer.innerHTML ); 5354 footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) ); 5355 }, footerSrcEls ); 5356 5357 _fnApplyToChildren( function(nToSize, i) { 5358 nToSize.style.width = footerWidths[i]; 5359 }, footerTrgEls ); 5360 5361 $(footerSrcEls).height(0); 5362 } 5363 5364 5365 /* 5366 * 3. Apply the measurements 5367 */ 5368 5369 // "Hide" the header and footer that we used for the sizing. We need to keep 5370 // the content of the cell so that the width applied to the header and body 5371 // both match, but we want to hide it completely. We want to also fix their 5372 // width to what they currently are 5373 _fnApplyToChildren( function(nSizer, i) { 5374 nSizer.innerHTML = '<div class="dataTables_sizing">'+headerContent[i]+'</div>'; 5375 nSizer.childNodes[0].style.height = "0"; 5376 nSizer.childNodes[0].style.overflow = "hidden"; 5377 nSizer.style.width = headerWidths[i]; 5378 }, headerSrcEls ); 5379 5380 if ( footer ) 5381 { 5382 _fnApplyToChildren( function(nSizer, i) { 5383 nSizer.innerHTML = '<div class="dataTables_sizing">'+footerContent[i]+'</div>'; 5384 nSizer.childNodes[0].style.height = "0"; 5385 nSizer.childNodes[0].style.overflow = "hidden"; 5386 nSizer.style.width = footerWidths[i]; 5387 }, footerSrcEls ); 5388 } 5389 5390 // Sanity check that the table is of a sensible width. If not then we are going to get 5391 // misalignment - try to prevent this by not allowing the table to shrink below its min width 5392 if ( table.outerWidth() < sanityWidth ) 5393 { 5394 // The min width depends upon if we have a vertical scrollbar visible or not */ 5395 correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight || 5396 divBody.css('overflow-y') == "scroll")) ? 5397 sanityWidth+barWidth : 5398 sanityWidth; 5399 5400 // IE6/7 are a law unto themselves... 5401 if ( ie67 && (divBodyEl.scrollHeight > 5402 divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll") 5403 ) { 5404 tableStyle.width = _fnStringToCss( correction-barWidth ); 5405 } 5406 5407 // And give the user a warning that we've stopped the table getting too small 5408 if ( scrollX === "" || scrollXInner !== "" ) { 5409 _fnLog( settings, 1, 'Possible column misalignment', 6 ); 5410 } 5411 } 5412 else 5413 { 5414 correction = '100%'; 5415 } 5416 5417 // Apply to the container elements 5418 divBodyStyle.width = _fnStringToCss( correction ); 5419 divHeaderStyle.width = _fnStringToCss( correction ); 5420 5421 if ( footer ) { 5422 settings.nScrollFoot.style.width = _fnStringToCss( correction ); 5423 } 5424 5425 5426 /* 5427 * 4. Clean up 5428 */ 5429 if ( ! scrollY ) { 5430 /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting 5431 * the scrollbar height from the visible display, rather than adding it on. We need to 5432 * set the height in order to sort this. Don't want to do it in any other browsers. 5433 */ 5434 if ( ie67 ) { 5435 divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth ); 5436 } 5437 } 5438 5439 /* Finally set the width's of the header and footer tables */ 5440 var iOuterWidth = table.outerWidth(); 5441 divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth ); 5442 divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth ); 5443 5444 // Figure out if there are scrollbar present - if so then we need a the header and footer to 5445 // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar) 5446 var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll"; 5447 var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' ); 5448 divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px"; 5449 5450 if ( footer ) { 5451 divFooterTable[0].style.width = _fnStringToCss( iOuterWidth ); 5452 divFooterInner[0].style.width = _fnStringToCss( iOuterWidth ); 5453 divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px"; 5454 } 5455 5456 // Correct DOM ordering for colgroup - comes before the thead 5457 table.children('colgroup').insertBefore( table.children('thead') ); 5458 5459 /* Adjust the position of the header in case we loose the y-scrollbar */ 5460 divBody.scroll(
vendor: 11,594 bytes, lines 5460-5858
5460); 5461 5462 // If sorting or filtering has occurred, jump the scrolling back to the top 5463 // only if we aren't holding the position 5464 if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) { 5465 divBodyEl.scrollTop = 0; 5466 } 5467 } 5468 5469 5470 5471 /** 5472 * Apply a given function to the display child nodes of an element array (typically 5473 * TD children of TR rows 5474 * @param {function} fn Method to apply to the objects 5475 * @param array {nodes} an1 List of elements to look through for display children 5476 * @param array {nodes} an2 Another list (identical structure to the first) - optional 5477 * @memberof DataTable#oApi 5478 */ 5479 function _fnApplyToChildren( fn, an1, an2 ) 5480 { 5481 var index=0, i=0, iLen=an1.length; 5482 var nNode1, nNode2; 5483 5484 while ( i < iLen ) { 5485 nNode1 = an1[i].firstChild; 5486 nNode2 = an2 ? an2[i].firstChild : null; 5487 5488 while ( nNode1 ) { 5489 if ( nNode1.nodeType === 1 ) { 5490 if ( an2 ) { 5491 fn( nNode1, nNode2, index ); 5492 } 5493 else { 5494 fn( nNode1, index ); 5495 } 5496 5497 index++; 5498 } 5499 5500 nNode1 = nNode1.nextSibling; 5501 nNode2 = an2 ? nNode2.nextSibling : null; 5502 } 5503 5504 i++; 5505 } 5506 } 5507 5508 5509 5510 var __re_html_remove = /<.*?>/g; 5511 5512 5513 /** 5514 * Calculate the width of columns for the table 5515 * @param {object} oSettings dataTables settings object 5516 * @memberof DataTable#oApi 5517 */ 5518 function _fnCalculateColumnWidths ( oSettings ) 5519 { 5520 var 5521 table = oSettings.nTable, 5522 columns = oSettings.aoColumns, 5523 scroll = oSettings.oScroll, 5524 scrollY = scroll.sY, 5525 scrollX = scroll.sX, 5526 scrollXInner = scroll.sXInner, 5527 columnCount = columns.length, 5528 visibleColumns = _fnGetColumns( oSettings, 'bVisible' ), 5529 headerCells = $('th', oSettings.nTHead), 5530 tableWidthAttr = table.getAttribute('width'), // from DOM element 5531 tableContainer = table.parentNode, 5532 userInputs = false, 5533 i, column, columnIdx, width, outerWidth, 5534 browser = oSettings.oBrowser, 5535 ie67 = browser.bScrollOversize; 5536 5537 var styleWidth = table.style.width; 5538 if ( styleWidth && styleWidth.indexOf('%') !== -1 ) { 5539 tableWidthAttr = styleWidth; 5540 } 5541 5542 /* Convert any user input sizes into pixel sizes */ 5543 for ( i=0 ; i<visibleColumns.length ; i++ ) { 5544 column = columns[ visibleColumns[i] ]; 5545 5546 if ( column.sWidth !== null ) { 5547 column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer ); 5548 5549 userInputs = true; 5550 } 5551 } 5552 5553 /* If the number of columns in the DOM equals the number that we have to 5554 * process in DataTables, then we can use the offsets that are created by 5555 * the web- browser. No custom sizes can be set in order for this to happen, 5556 * nor scrolling used 5557 */ 5558 if ( ie67 || ! userInputs && ! scrollX && ! scrollY && 5559 columnCount == _fnVisbleColumns( oSettings ) && 5560 columnCount == headerCells.length 5561 ) { 5562 for ( i=0 ; i<columnCount ; i++ ) { 5563 var colIdx = _fnVisibleToColumnIndex( oSettings, i ); 5564 5565 if ( colIdx !== null ) { 5566 columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() ); 5567 } 5568 } 5569 } 5570 else 5571 { 5572 // Otherwise construct a single row, worst case, table with the widest 5573 // node in the data, assign any user defined widths, then insert it into 5574 // the DOM and allow the browser to do all the hard work of calculating 5575 // table widths 5576 var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table 5577 .css( 'visibility', 'hidden' ) 5578 .removeAttr( 'id' ); 5579 5580 // Clean up the table body 5581 tmpTable.find('tbody tr').remove(); 5582 var tr = $('<tr/>').appendTo( tmpTable.find('tbody') ); 5583 5584 // Clone the table header and footer - we can't use the header / footer 5585 // from the cloned table, since if scrolling is active, the table's 5586 // real header and footer are contained in different table tags 5587 tmpTable.find('thead, tfoot').remove(); 5588 tmpTable 5589 .append( $(oSettings.nTHead).clone() ) 5590 .append( $(oSettings.nTFoot).clone() ); 5591 5592 // Remove any assigned widths from the footer (from scrolling) 5593 tmpTable.find('tfoot th, tfoot td').css('width', ''); 5594 5595 // Apply custom sizing to the cloned header 5596 headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] ); 5597 5598 for ( i=0 ; i<visibleColumns.length ; i++ ) { 5599 column = columns[ visibleColumns[i] ]; 5600 5601 headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ? 5602 _fnStringToCss( column.sWidthOrig ) : 5603 ''; 5604 5605 // For scrollX we need to force the column width otherwise the 5606 // browser will collapse it. If this width is smaller than the 5607 // width the column requires, then it will have no effect 5608 if ( column.sWidthOrig && scrollX ) { 5609 $( headerCells[i] ).append( $('<div/>').css( { 5610 width: column.sWidthOrig, 5611 margin: 0, 5612 padding: 0, 5613 border: 0, 5614 height: 1 5615 } ) ); 5616 } 5617 } 5618 5619 // Find the widest cell for each column and put it into the table 5620 if ( oSettings.aoData.length ) { 5621 for ( i=0 ; i<visibleColumns.length ; i++ ) { 5622 columnIdx = visibleColumns[i]; 5623 column = columns[ columnIdx ]; 5624 5625 $( _fnGetWidestNode( oSettings, columnIdx ) ) 5626 .clone( false ) 5627 .append( column.sContentPadding ) 5628 .appendTo( tr ); 5629 } 5630 } 5631 5632 // Tidy the temporary table - remove name attributes so there aren't 5633 // duplicated in the dom (radio elements for example) 5634 $('[name]', tmpTable).removeAttr('name'); 5635 5636 // Table has been built, attach to the document so we can work with it. 5637 // A holding element is used, positioned at the top of the container 5638 // with minimal height, so it has no effect on if the container scrolls 5639 // or not. Otherwise it might trigger scrolling when it actually isn't 5640 // needed 5641 var holder = $('<div/>').css( scrollX || scrollY ? 5642 { 5643 position: 'absolute', 5644 top: 0, 5645 left: 0, 5646 height: 1, 5647 right: 0, 5648 overflow: 'hidden' 5649 } : 5650 {} 5651 ) 5652 .append( tmpTable ) 5653 .appendTo( tableContainer ); 5654 5655 // When scrolling (X or Y) we want to set the width of the table as 5656 // appropriate. However, when not scrolling leave the table width as it 5657 // is. This results in slightly different, but I think correct behaviour 5658 if ( scrollX && scrollXInner ) { 5659 tmpTable.width( scrollXInner ); 5660 } 5661 else if ( scrollX ) { 5662 tmpTable.css( 'width', 'auto' ); 5663 tmpTable.removeAttr('width'); 5664 5665 // If there is no width attribute or style, then allow the table to 5666 // collapse 5667 if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) { 5668 tmpTable.width( tableContainer.clientWidth ); 5669 } 5670 } 5671 else if ( scrollY ) { 5672 tmpTable.width( tableContainer.clientWidth ); 5673 } 5674 else if ( tableWidthAttr ) { 5675 tmpTable.width( tableWidthAttr ); 5676 } 5677 5678 // Get the width of each column in the constructed table - we need to 5679 // know the inner width (so it can be assigned to the other table's 5680 // cells) and the outer width so we can calculate the full width of the 5681 // table. This is safe since DataTables requires a unique cell for each 5682 // column, but if ever a header can span multiple columns, this will 5683 // need to be modified. 5684 var total = 0; 5685 for ( i=0 ; i<visibleColumns.length ; i++ ) { 5686 var cell = $(headerCells[i]); 5687 var border = cell.outerWidth() - cell.width(); 5688 5689 // Use getBounding... where possible (not IE8-) because it can give 5690 // sub-pixel accuracy, which we then want to round up! 5691 var bounding = browser.bBounding ? 5692 Math.ceil( headerCells[i].getBoundingClientRect().width ) : 5693 cell.outerWidth(); 5694 5695 // Total is tracked to remove any sub-pixel errors as the outerWidth 5696 // of the table might not equal the total given here (IE!). 5697 total += bounding; 5698 5699 // Width for each column to use 5700 columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border ); 5701 } 5702 5703 table.style.width = _fnStringToCss( total ); 5704 5705 // Finished with the table - ditch it 5706 holder.remove(); 5707 } 5708 5709 // If there is a width attr, we want to attach an event listener which 5710 // allows the table sizing to automatically adjust when the window is 5711 // resized. Use the width attr rather than CSS, since we can't know if the 5712 // CSS is a relative value or absolute - DOM read is always px. 5713 if ( tableWidthAttr ) { 5714 table.style.width = _fnStringToCss( tableWidthAttr ); 5715 } 5716 5717 if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) { 5718 var bindResize = function () { 5719 $(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () { 5720 _fnAdjustColumnSizing( oSettings ); 5721 } ) ); 5722 }; 5723 5724 // IE6/7 will crash if we bind a resize event handler on page load. 5725 // To be removed in 1.11 which drops IE6/7 support 5726 if ( ie67 ) { 5727 setTimeout( bindResize, 1000 ); 5728 } 5729 else { 5730 bindResize(); 5731 } 5732 5733 oSettings._reszEvt = true; 5734 } 5735 } 5736 5737 5738 /** 5739 * Throttle the calls to a function. Arguments and context are maintained for 5740 * the throttled function 5741 * @param {function} fn Function to be called 5742 * @param {int} [freq=200] call frequency in mS 5743 * @returns {function} wrapped function 5744 * @memberof DataTable#oApi 5745 */ 5746 var _fnThrottle = DataTable.util.throttle; 5747 5748 5749 /** 5750 * Convert a CSS unit width to pixels (e.g. 2em) 5751 * @param {string} width width to be converted 5752 * @param {node} parent parent to get the with for (required for relative widths) - optional 5753 * @returns {int} width in pixels 5754 * @memberof DataTable#oApi 5755 */ 5756 function _fnConvertToWidth ( width, parent ) 5757 { 5758 if ( ! width ) { 5759 return 0; 5760 } 5761 5762 var n = $('<div/>') 5763 .css( 'width', _fnStringToCss( width ) ) 5764 .appendTo( parent || document.body ); 5765 5766 var val = n[0].offsetWidth; 5767 n.remove(); 5768 5769 return val; 5770 } 5771 5772 5773 /** 5774 * Get the widest node 5775 * @param {object} settings dataTables settings object 5776 * @param {int} colIdx column of interest 5777 * @returns {node} widest table node 5778 * @memberof DataTable#oApi 5779 */ 5780 function _fnGetWidestNode( settings, colIdx ) 5781 { 5782 var idx = _fnGetMaxLenString( settings, colIdx ); 5783 if ( idx < 0 ) { 5784 return null; 5785 } 5786 5787 var data = settings.aoData[ idx ]; 5788 return ! data.nTr ? // Might not have been created when deferred rendering 5789 $('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] : 5790 data.anCells[ colIdx ]; 5791 } 5792 5793 5794 /** 5795 * Get the maximum strlen for each data column 5796 * @param {object} settings dataTables settings object 5797 * @param {int} colIdx column of interest 5798 * @returns {string} max string length for each column 5799 * @memberof DataTable#oApi 5800 */ 5801 function _fnGetMaxLenString( settings, colIdx ) 5802 { 5803 var s, max=-1, maxIdx = -1; 5804 5805 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 5806 s = _fnGetCellData( settings, i, colIdx, 'display' )+''; 5807 s = s.replace( __re_html_remove, '' ); 5808 s = s.replace( / /g, ' ' ); 5809 5810 if ( s.length > max ) { 5811 max = s.length; 5812 maxIdx = i; 5813 } 5814 } 5815 5816 return maxIdx; 5817 } 5818 5819 5820 /** 5821 * Append a CSS unit (only if required) to a string 5822 * @param {string} value to css-ify 5823 * @returns {string} value with css unit 5824 * @memberof DataTable#oApi 5825 */ 5826 function _fnStringToCss( s ) 5827 { 5828 if ( s === null ) { 5829 return '0px'; 5830 } 5831 5832 if ( typeof s == 'number' ) { 5833 return s < 0 ? 5834 '0px' : 5835 s+'px'; 5836 } 5837 5838 // Check it has a unit character already 5839 return s.match(/\d$/) ? 5840 s+'px' : 5841 s; 5842 } 5843 5844 5845 5846 function _fnSortFlatten ( settings ) 5847 { 5848 var 5849 i, iLen, k, kLen, 5850 aSort = [], 5851 aiOrig = [], 5852 aoColumns = settings.aoColumns, 5853 aDataSort, iCol, sType, srcCol, 5854 fixed = settings.aaSortingFixed, 5855 fixedObj = $.isPlainObject( fixed ), 5856 nestedSort = [], 5857 add = function ( a ) { 5858 if ( a.length && !
vendor: 39,758 bytes, lines 5858-7379
5858$.isArray( a[0] ) ) { 5859 // 1D array 5860 nestedSort.push( a ); 5861 } 5862 else { 5863 // 2D array 5864 $.merge( nestedSort, a ); 5865 } 5866 }; 5867 5868 // Build the sort array, with pre-fix and post-fix options if they have been 5869 // specified 5870 if ( $.isArray( fixed ) ) { 5871 add( fixed ); 5872 } 5873 5874 if ( fixedObj && fixed.pre ) { 5875 add( fixed.pre ); 5876 } 5877 5878 add( settings.aaSorting ); 5879 5880 if (fixedObj && fixed.post ) { 5881 add( fixed.post ); 5882 } 5883 5884 for ( i=0 ; i<nestedSort.length ; i++ ) 5885 { 5886 srcCol = nestedSort[i][0]; 5887 aDataSort = aoColumns[ srcCol ].aDataSort; 5888 5889 for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ ) 5890 { 5891 iCol = aDataSort[k]; 5892 sType = aoColumns[ iCol ].sType || 'string'; 5893 5894 if ( nestedSort[i]._idx === undefined ) { 5895 nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting ); 5896 } 5897 5898 aSort.push( { 5899 src: srcCol, 5900 col: iCol, 5901 dir: nestedSort[i][1], 5902 index: nestedSort[i]._idx, 5903 type: sType, 5904 formatter: DataTable.ext.type.order[ sType+"-pre" ] 5905 } ); 5906 } 5907 } 5908 5909 return aSort; 5910 } 5911 5912 /** 5913 * Change the order of the table 5914 * @param {object} oSettings dataTables settings object 5915 * @memberof DataTable#oApi 5916 * @todo This really needs split up! 5917 */ 5918 function _fnSort ( oSettings ) 5919 { 5920 var 5921 i, ien, iLen, j, jLen, k, kLen, 5922 sDataType, nTh, 5923 aiOrig = [], 5924 oExtSort = DataTable.ext.type.order, 5925 aoData = oSettings.aoData, 5926 aoColumns = oSettings.aoColumns, 5927 aDataSort, data, iCol, sType, oSort, 5928 formatters = 0, 5929 sortCol, 5930 displayMaster = oSettings.aiDisplayMaster, 5931 aSort; 5932 5933 // Resolve any column types that are unknown due to addition or invalidation 5934 // @todo Can this be moved into a 'data-ready' handler which is called when 5935 // data is going to be used in the table? 5936 _fnColumnTypes( oSettings ); 5937 5938 aSort = _fnSortFlatten( oSettings ); 5939 5940 for ( i=0, ien=aSort.length ; i<ien ; i++ ) { 5941 sortCol = aSort[i]; 5942 5943 // Track if we can use the fast sort algorithm 5944 if ( sortCol.formatter ) { 5945 formatters++; 5946 } 5947 5948 // Load the data needed for the sort, for each cell 5949 _fnSortData( oSettings, sortCol.col ); 5950 } 5951 5952 /* No sorting required if server-side or no sorting array */ 5953 if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 ) 5954 { 5955 // Create a value - key array of the current row positions such that we can use their 5956 // current position during the sort, if values match, in order to perform stable sorting 5957 for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) { 5958 aiOrig[ displayMaster[i] ] = i; 5959 } 5960 5961 /* Do the sort - here we want multi-column sorting based on a given data source (column) 5962 * and sorting function (from oSort) in a certain direction. It's reasonably complex to 5963 * follow on it's own, but this is what we want (example two column sorting): 5964 * fnLocalSorting = function(a,b){ 5965 * var iTest; 5966 * iTest = oSort['string-asc']('data11', 'data12'); 5967 * if (iTest !== 0) 5968 * return iTest; 5969 * iTest = oSort['numeric-desc']('data21', 'data22'); 5970 * if (iTest !== 0) 5971 * return iTest; 5972 * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] ); 5973 * } 5974 * Basically we have a test for each sorting column, if the data in that column is equal, 5975 * test the next column. If all columns match, then we use a numeric sort on the row 5976 * positions in the original data array to provide a stable sort. 5977 * 5978 * Note - I know it seems excessive to have two sorting methods, but the first is around 5979 * 15% faster, so the second is only maintained for backwards compatibility with sorting 5980 * methods which do not have a pre-sort formatting function. 5981 */ 5982 if ( formatters === aSort.length ) { 5983 // All sort types have formatting functions 5984 displayMaster.sort( function ( a, b ) { 5985 var 5986 x, y, k, test, sort, 5987 len=aSort.length, 5988 dataA = aoData[a]._aSortData, 5989 dataB = aoData[b]._aSortData; 5990 5991 for ( k=0 ; k<len ; k++ ) { 5992 sort = aSort[k]; 5993 5994 x = dataA[ sort.col ]; 5995 y = dataB[ sort.col ]; 5996 5997 test = x<y ? -1 : x>y ? 1 : 0; 5998 if ( test !== 0 ) { 5999 return sort.dir === 'asc' ? test : -test; 6000 } 6001 } 6002 6003 x = aiOrig[a]; 6004 y = aiOrig[b]; 6005 return x<y ? -1 : x>y ? 1 : 0; 6006 } ); 6007 } 6008 else { 6009 // Depreciated - remove in 1.11 (providing a plug-in option) 6010 // Not all sort types have formatting methods, so we have to call their sorting 6011 // methods. 6012 displayMaster.sort( function ( a, b ) { 6013 var 6014 x, y, k, l, test, sort, fn, 6015 len=aSort.length, 6016 dataA = aoData[a]._aSortData, 6017 dataB = aoData[b]._aSortData; 6018 6019 for ( k=0 ; k<len ; k++ ) { 6020 sort = aSort[k]; 6021 6022 x = dataA[ sort.col ]; 6023 y = dataB[ sort.col ]; 6024 6025 fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ]; 6026 test = fn( x, y ); 6027 if ( test !== 0 ) { 6028 return test; 6029 } 6030 } 6031 6032 x = aiOrig[a]; 6033 y = aiOrig[b]; 6034 return x<y ? -1 : x>y ? 1 : 0; 6035 } ); 6036 } 6037 } 6038 6039 /* Tell the draw function that we have sorted the data */ 6040 oSettings.bSorted = true; 6041 } 6042 6043 6044 function _fnSortAria ( settings ) 6045 { 6046 var label; 6047 var nextSort; 6048 var columns = settings.aoColumns; 6049 var aSort = _fnSortFlatten( settings ); 6050 var oAria = settings.oLanguage.oAria; 6051 6052 // ARIA attributes - need to loop all columns, to update all (removing old 6053 // attributes as needed) 6054 for ( var i=0, iLen=columns.length ; i<iLen ; i++ ) 6055 { 6056 var col = columns[i]; 6057 var asSorting = col.asSorting; 6058 var sTitle = col.sTitle.replace( /<.*?>/g, "" ); 6059 var th = col.nTh; 6060 6061 // IE7 is throwing an error when setting these properties with jQuery's 6062 // attr() and removeAttr() methods... 6063 th.removeAttribute('aria-sort'); 6064 6065 /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */ 6066 if ( col.bSortable ) { 6067 if ( aSort.length > 0 && aSort[0].col == i ) { 6068 th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" ); 6069 nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0]; 6070 } 6071 else { 6072 nextSort = asSorting[0]; 6073 } 6074 6075 label = sTitle + ( nextSort === "asc" ? 6076 oAria.sSortAscending : 6077 oAria.sSortDescending 6078 ); 6079 } 6080 else { 6081 label = sTitle; 6082 } 6083 6084 th.setAttribute('aria-label', label); 6085 } 6086 } 6087 6088 6089 /** 6090 * Function to run on user sort request 6091 * @param {object} settings dataTables settings object 6092 * @param {node} attachTo node to attach the handler to 6093 * @param {int} colIdx column sorting index 6094 * @param {boolean} [append=false] Append the requested sort to the existing 6095 * sort if true (i.e. multi-column sort) 6096 * @param {function} [callback] callback function 6097 * @memberof DataTable#oApi 6098 */ 6099 function _fnSortListener ( settings, colIdx, append, callback ) 6100 { 6101 var col = settings.aoColumns[ colIdx ]; 6102 var sorting = settings.aaSorting; 6103 var asSorting = col.asSorting; 6104 var nextSortIdx; 6105 var next = function ( a, overflow ) { 6106 var idx = a._idx; 6107 if ( idx === undefined ) { 6108 idx = $.inArray( a[1], asSorting ); 6109 } 6110 6111 return idx+1 < asSorting.length ? 6112 idx+1 : 6113 overflow ? 6114 null : 6115 0; 6116 }; 6117 6118 // Convert to 2D array if needed 6119 if ( typeof sorting[0] === 'number' ) { 6120 sorting = settings.aaSorting = [ sorting ]; 6121 } 6122 6123 // If appending the sort then we are multi-column sorting 6124 if ( append && settings.oFeatures.bSortMulti ) { 6125 // Are we already doing some kind of sort on this column? 6126 var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') ); 6127 6128 if ( sortIdx !== -1 ) { 6129 // Yes, modify the sort 6130 nextSortIdx = next( sorting[sortIdx], true ); 6131 6132 if ( nextSortIdx === null && sorting.length === 1 ) { 6133 nextSortIdx = 0; // can't remove sorting completely 6134 } 6135 6136 if ( nextSortIdx === null ) { 6137 sorting.splice( sortIdx, 1 ); 6138 } 6139 else { 6140 sorting[sortIdx][1] = asSorting[ nextSortIdx ]; 6141 sorting[sortIdx]._idx = nextSortIdx; 6142 } 6143 } 6144 else { 6145 // No sort on this column yet 6146 sorting.push( [ colIdx, asSorting[0], 0 ] ); 6147 sorting[sorting.length-1]._idx = 0; 6148 } 6149 } 6150 else if ( sorting.length && sorting[0][0] == colIdx ) { 6151 // Single column - already sorting on this column, modify the sort 6152 nextSortIdx = next( sorting[0] ); 6153 6154 sorting.length = 1; 6155 sorting[0][1] = asSorting[ nextSortIdx ]; 6156 sorting[0]._idx = nextSortIdx; 6157 } 6158 else { 6159 // Single column - sort only on this column 6160 sorting.length = 0; 6161 sorting.push( [ colIdx, asSorting[0] ] ); 6162 sorting[0]._idx = 0; 6163 } 6164 6165 // Run the sort by calling a full redraw 6166 _fnReDraw( settings ); 6167 6168 // callback used for async user interaction 6169 if ( typeof callback == 'function' ) { 6170 callback( settings ); 6171 } 6172 } 6173 6174 6175 /** 6176 * Attach a sort handler (click) to a node 6177 * @param {object} settings dataTables settings object 6178 * @param {node} attachTo node to attach the handler to 6179 * @param {int} colIdx column sorting index 6180 * @param {function} [callback] callback function 6181 * @memberof DataTable#oApi 6182 */ 6183 function _fnSortAttachListener ( settings, attachTo, colIdx, callback ) 6184 { 6185 var col = settings.aoColumns[ colIdx ]; 6186 6187 _fnBindAction( attachTo, {}, function (e) { 6188 /* If the column is not sortable - don't to anything */ 6189 if ( col.bSortable === false ) { 6190 return; 6191 } 6192 6193 // If processing is enabled use a timeout to allow the processing 6194 // display to be shown - otherwise to it synchronously 6195 if ( settings.oFeatures.bProcessing ) { 6196 _fnProcessingDisplay( settings, true ); 6197 6198 setTimeout( function() { 6199 _fnSortListener( settings, colIdx, e.shiftKey, callback ); 6200 6201 // In server-side processing, the draw callback will remove the 6202 // processing display 6203 if ( _fnDataSource( settings ) !== 'ssp' ) { 6204 _fnProcessingDisplay( settings, false ); 6205 } 6206 }, 0 ); 6207 } 6208 else { 6209 _fnSortListener( settings, colIdx, e.shiftKey, callback ); 6210 } 6211 } ); 6212 } 6213 6214 6215 /** 6216 * Set the sorting classes on table's body, Note: it is safe to call this function 6217 * when bSort and bSortClasses are false 6218 * @param {object} oSettings dataTables settings object 6219 * @memberof DataTable#oApi 6220 */ 6221 function _fnSortingClasses( settings ) 6222 { 6223 var oldSort = settings.aLastSort; 6224 var sortClass = settings.oClasses.sSortColumn; 6225 var sort = _fnSortFlatten( settings ); 6226 var features = settings.oFeatures; 6227 var i, ien, colIdx; 6228 6229 if ( features.bSort && features.bSortClasses ) { 6230 // Remove old sorting classes 6231 for ( i=0, ien=oldSort.length ; i<ien ; i++ ) { 6232 colIdx = oldSort[i].src; 6233 6234 // Remove column sorting 6235 $( _pluck( settings.aoData, 'anCells', colIdx ) ) 6236 .removeClass( sortClass + (i<2 ? i+1 : 3) ); 6237 } 6238 6239 // Add new column sorting 6240 for ( i=0, ien=sort.length ; i<ien ; i++ ) { 6241 colIdx = sort[i].src; 6242 6243 $( _pluck( settings.aoData, 'anCells', colIdx ) ) 6244 .addClass( sortClass + (i<2 ? i+1 : 3) ); 6245 } 6246 } 6247 6248 settings.aLastSort = sort; 6249 } 6250 6251 6252 // Get the data to sort a column, be it from cache, fresh (populating the 6253 // cache), or from a sort formatter 6254 function _fnSortData( settings, idx ) 6255 { 6256 // Custom sorting function - provided by the sort data type 6257 var column = settings.aoColumns[ idx ]; 6258 var customSort = DataTable.ext.order[ column.sSortDataType ]; 6259 var customData; 6260 6261 if ( customSort ) { 6262 customData = customSort.call( settings.oInstance, settings, idx, 6263 _fnColumnIndexToVisible( settings, idx ) 6264 ); 6265 } 6266 6267 // Use / populate cache 6268 var row, cellData; 6269 var formatter = DataTable.ext.type.order[ column.sType+"-pre" ]; 6270 6271 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 6272 row = settings.aoData[i]; 6273 6274 if ( ! row._aSortData ) { 6275 row._aSortData = []; 6276 } 6277 6278 if ( ! row._aSortData[idx] || customSort ) { 6279 cellData = customSort ? 6280 customData[i] : // If there was a custom sort function, use data from there 6281 _fnGetCellData( settings, i, idx, 'sort' ); 6282 6283 row._aSortData[ idx ] = formatter ? 6284 formatter( cellData ) : 6285 cellData; 6286 } 6287 } 6288 } 6289 6290 6291 6292 /** 6293 * Save the state of a table 6294 * @param {object} oSettings dataTables settings object 6295 * @memberof DataTable#oApi 6296 */ 6297 function _fnSaveState ( settings ) 6298 { 6299 if ( !settings.oFeatures.bStateSave || settings.bDestroying ) 6300 { 6301 return; 6302 } 6303 6304 /* Store the interesting variables */ 6305 var state = { 6306 time: +new Date(), 6307 start: settings._iDisplayStart, 6308 length: settings._iDisplayLength, 6309 order: $.extend( true, [], settings.aaSorting ), 6310 search: _fnSearchToCamel( settings.oPreviousSearch ), 6311 columns: $.map( settings.aoColumns, function ( col, i ) { 6312 return { 6313 visible: col.bVisible, 6314 search: _fnSearchToCamel( settings.aoPreSearchCols[i] ) 6315 }; 6316 } ) 6317 }; 6318 6319 _fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] ); 6320 6321 settings.oSavedState = state; 6322 settings.fnStateSaveCallback.call( settings.oInstance, settings, state ); 6323 } 6324 6325 6326 /** 6327 * Attempt to load a saved table state 6328 * @param {object} oSettings dataTables settings object 6329 * @param {object} oInit DataTables init object so we can override settings 6330 * @param {function} callback Callback to execute when the state has been loaded 6331 * @memberof DataTable#oApi 6332 */ 6333 function _fnLoadState ( settings, oInit, callback ) 6334 { 6335 var i, ien; 6336 var columns = settings.aoColumns; 6337 var loaded = function ( s ) { 6338 if ( ! s || ! s.time ) { 6339 callback(); 6340 return; 6341 } 6342 6343 // Allow custom and plug-in manipulation functions to alter the saved data set and 6344 // cancelling of loading by returning false 6345 var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] ); 6346 if ( $.inArray( false, abStateLoad ) !== -1 ) { 6347 callback(); 6348 return; 6349 } 6350 6351 // Reject old data 6352 var duration = settings.iStateDuration; 6353 if ( duration > 0 && s.time < +new Date() - (duration*1000) ) { 6354 callback(); 6355 return; 6356 } 6357 6358 // Number of columns have changed - all bets are off, no restore of settings 6359 if ( s.columns && columns.length !== s.columns.length ) { 6360 callback(); 6361 return; 6362 } 6363 6364 // Store the saved state so it might be accessed at any time 6365 settings.oLoadedState = $.extend( true, {}, s ); 6366 6367 // Restore key features - todo - for 1.11 this needs to be done by 6368 // subscribed events 6369 if ( s.start !== undefined ) { 6370 settings._iDisplayStart = s.start; 6371 settings.iInitDisplayStart = s.start; 6372 } 6373 if ( s.length !== undefined ) { 6374 settings._iDisplayLength = s.length; 6375 } 6376 6377 // Order 6378 if ( s.order !== undefined ) { 6379 settings.aaSorting = []; 6380 $.each( s.order, function ( i, col ) { 6381 settings.aaSorting.push( col[0] >= columns.length ? 6382 [ 0, col[1] ] : 6383 col 6384 ); 6385 } ); 6386 } 6387 6388 // Search 6389 if ( s.search !== undefined ) { 6390 $.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) ); 6391 } 6392 6393 // Columns 6394 // 6395 if ( s.columns ) { 6396 for ( i=0, ien=s.columns.length ; i<ien ; i++ ) { 6397 var col = s.columns[i]; 6398 6399 // Visibility 6400 if ( col.visible !== undefined ) { 6401 columns[i].bVisible = col.visible; 6402 } 6403 6404 // Search 6405 if ( col.search !== undefined ) { 6406 $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) ); 6407 } 6408 } 6409 } 6410 6411 _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] ); 6412 callback(); 6413 } 6414 6415 if ( ! settings.oFeatures.bStateSave ) { 6416 callback(); 6417 return; 6418 } 6419 6420 var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded ); 6421 6422 if ( state !== undefined ) { 6423 loaded( state ); 6424 } 6425 // otherwise, wait for the loaded callback to be executed 6426 } 6427 6428 6429 /** 6430 * Return the settings object for a particular table 6431 * @param {node} table table we are using as a dataTable 6432 * @returns {object} Settings object - or null if not found 6433 * @memberof DataTable#oApi 6434 */ 6435 function _fnSettingsFromNode ( table ) 6436 { 6437 var settings = DataTable.settings; 6438 var idx = $.inArray( table, _pluck( settings, 'nTable' ) ); 6439 6440 return idx !== -1 ? 6441 settings[ idx ] : 6442 null; 6443 } 6444 6445 6446 /** 6447 * Log an error message 6448 * @param {object} settings dataTables settings object 6449 * @param {int} level log error messages, or display them to the user 6450 * @param {string} msg error message 6451 * @param {int} tn Technical note id to get more information about the error. 6452 * @memberof DataTable#oApi 6453 */ 6454 function _fnLog( settings, level, msg, tn ) 6455 { 6456 msg = 'DataTables warning: '+ 6457 (settings ? 'table id='+settings.sTableId+' - ' : '')+msg; 6458 6459 if ( tn ) { 6460 msg += '. For more information about this error, please see '+ 6461 'http://datatables.net/tn/'+tn; 6462 } 6463 6464 if ( ! level ) { 6465 // Backwards compatibility pre 1.10 6466 var ext = DataTable.ext; 6467 var type = ext.sErrMode || ext.errMode; 6468 6469 if ( settings ) { 6470 _fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] ); 6471 } 6472 6473 if ( type == 'alert' ) { 6474 alert( msg ); 6475 } 6476 else if ( type == 'throw' ) { 6477 throw new Error(msg); 6478 } 6479 else if ( typeof type == 'function' ) { 6480 type( settings, tn, msg ); 6481 } 6482 } 6483 else if ( window.console && console.log ) { 6484 console.log( msg ); 6485 } 6486 } 6487 6488 6489 /** 6490 * See if a property is defined on one object, if so assign it to the other object 6491 * @param {object} ret target object 6492 * @param {object} src source object 6493 * @param {string} name property 6494 * @param {string} [mappedName] name to map too - optional, name used if not given 6495 * @memberof DataTable#oApi 6496 */ 6497 function _fnMap( ret, src, name, mappedName ) 6498 { 6499 if ( $.isArray( name ) ) { 6500 $.each( name, function (i, val) { 6501 if ( $.isArray( val ) ) { 6502 _fnMap( ret, src, val[0], val[1] ); 6503 } 6504 else { 6505 _fnMap( ret, src, val ); 6506 } 6507 } ); 6508 6509 return; 6510 } 6511 6512 if ( mappedName === undefined ) { 6513 mappedName = name; 6514 } 6515 6516 if ( src[name] !== undefined ) { 6517 ret[mappedName] = src[name]; 6518 } 6519 } 6520 6521 6522 /** 6523 * Extend objects - very similar to jQuery.extend, but deep copy objects, and 6524 * shallow copy arrays. The reason we need to do this, is that we don't want to 6525 * deep copy array init values (such as aaSorting) since the dev wouldn't be 6526 * able to override them, but we do want to deep copy arrays. 6527 * @param {object} out Object to extend 6528 * @param {object} extender Object from which the properties will be applied to 6529 * out 6530 * @param {boolean} breakRefs If true, then arrays will be sliced to take an 6531 * independent copy with the exception of the `data` or `aaData` parameters 6532 * if they are present. This is so you can pass in a collection to 6533 * DataTables and have that used as your data source without breaking the 6534 * references 6535 * @returns {object} out Reference, just for convenience - out === the return. 6536 * @memberof DataTable#oApi 6537 * @todo This doesn't take account of arrays inside the deep copied objects. 6538 */ 6539 function _fnExtend( out, extender, breakRefs ) 6540 { 6541 var val; 6542 6543 for ( var prop in extender ) { 6544 if ( extender.hasOwnProperty(prop) ) { 6545 val = extender[prop]; 6546 6547 if ( $.isPlainObject( val ) ) { 6548 if ( ! $.isPlainObject( out[prop] ) ) { 6549 out[prop] = {}; 6550 } 6551 $.extend( true, out[prop], val ); 6552 } 6553 else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) { 6554 out[prop] = val.slice(); 6555 } 6556 else { 6557 out[prop] = val; 6558 } 6559 } 6560 } 6561 6562 return out; 6563 } 6564 6565 6566 /** 6567 * Bind an event handers to allow a click or return key to activate the callback. 6568 * This is good for accessibility since a return on the keyboard will have the 6569 * same effect as a click, if the element has focus. 6570 * @param {element} n Element to bind the action to 6571 * @param {object} oData Data object to pass to the triggered function 6572 * @param {function} fn Callback function for when the event is triggered 6573 * @memberof DataTable#oApi 6574 */ 6575 function _fnBindAction( n, oData, fn ) 6576 { 6577 $(n) 6578 .on( 'click.DT', oData, function (e) { 6579 $(n).blur(); // Remove focus outline for mouse users 6580 fn(e); 6581 } ) 6582 .on( 'keypress.DT', oData, function (e){ 6583 if ( e.which === 13 ) { 6584 e.preventDefault(); 6585 fn(e); 6586 } 6587 } ) 6588 .on( 'selectstart.DT', function () { 6589 /* Take the brutal approach to cancelling text selection */ 6590 return false; 6591 } ); 6592 } 6593 6594 6595 /** 6596 * Register a callback function. Easily allows a callback function to be added to 6597 * an array store of callback functions that can then all be called together. 6598 * @param {object} oSettings dataTables settings object 6599 * @param {string} sStore Name of the array storage for the callbacks in oSettings 6600 * @param {function} fn Function to be called back 6601 * @param {string} sName Identifying name for the callback (i.e. a label) 6602 * @memberof DataTable#oApi 6603 */ 6604 function _fnCallbackReg( oSettings, sStore, fn, sName ) 6605 { 6606 if ( fn ) 6607 { 6608 oSettings[sStore].push( { 6609 "fn": fn, 6610 "sName": sName 6611 } ); 6612 } 6613 } 6614 6615 6616 /** 6617 * Fire callback functions and trigger events. Note that the loop over the 6618 * callback array store is done backwards! Further note that you do not want to 6619 * fire off triggers in time sensitive applications (for example cell creation) 6620 * as its slow. 6621 * @param {object} settings dataTables settings object 6622 * @param {string} callbackArr Name of the array storage for the callbacks in 6623 * oSettings 6624 * @param {string} eventName Name of the jQuery custom event to trigger. If 6625 * null no trigger is fired 6626 * @param {array} args Array of arguments to pass to the callback function / 6627 * trigger 6628 * @memberof DataTable#oApi 6629 */ 6630 function _fnCallbackFire( settings, callbackArr, eventName, args ) 6631 { 6632 var ret = []; 6633 6634 if ( callbackArr ) { 6635 ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) { 6636 return val.fn.apply( settings.oInstance, args ); 6637 } ); 6638 } 6639 6640 if ( eventName !== null ) { 6641 var e = $.Event( eventName+'.dt' ); 6642 6643 $(settings.nTable).trigger( e, args ); 6644 6645 ret.push( e.result ); 6646 } 6647 6648 return ret; 6649 } 6650 6651 6652 function _fnLengthOverflow ( settings ) 6653 { 6654 var 6655 start = settings._iDisplayStart, 6656 end = settings.fnDisplayEnd(), 6657 len = settings._iDisplayLength; 6658 6659 /* If we have space to show extra rows (backing up from the end point - then do so */ 6660 if ( start >= end ) 6661 { 6662 start = end - len; 6663 } 6664 6665 // Keep the start record on the current page 6666 start -= (start % len); 6667 6668 if ( len === -1 || start < 0 ) 6669 { 6670 start = 0; 6671 } 6672 6673 settings._iDisplayStart = start; 6674 } 6675 6676 6677 function _fnRenderer( settings, type ) 6678 { 6679 var renderer = settings.renderer; 6680 var host = DataTable.ext.renderer[type]; 6681 6682 if ( $.isPlainObject( renderer ) && renderer[type] ) { 6683 // Specific renderer for this type. If available use it, otherwise use 6684 // the default. 6685 return host[renderer[type]] || host._; 6686 } 6687 else if ( typeof renderer === 'string' ) { 6688 // Common renderer - if there is one available for this type use it, 6689 // otherwise use the default 6690 return host[renderer] || host._; 6691 } 6692 6693 // Use the default 6694 return host._; 6695 } 6696 6697 6698 /** 6699 * Detect the data source being used for the table. Used to simplify the code 6700 * a little (ajax) and to make it compress a little smaller. 6701 * 6702 * @param {object} settings dataTables settings object 6703 * @returns {string} Data source 6704 * @memberof DataTable#oApi 6705 */ 6706 function _fnDataSource ( settings ) 6707 { 6708 if ( settings.oFeatures.bServerSide ) { 6709 return 'ssp'; 6710 } 6711 else if ( settings.ajax || settings.sAjaxSource ) { 6712 return 'ajax'; 6713 } 6714 return 'dom'; 6715 } 6716 6717 6718 6719 6720 /** 6721 * Computed structure of the DataTables API, defined by the options passed to 6722 * `DataTable.Api.register()` when building the API. 6723 * 6724 * The structure is built in order to speed creation and extension of the Api 6725 * objects since the extensions are effectively pre-parsed. 6726 * 6727 * The array is an array of objects with the following structure, where this 6728 * base array represents the Api prototype base: 6729 * 6730 * [ 6731 * { 6732 * name: 'data' -- string - Property name 6733 * val: function () {}, -- function - Api method (or undefined if just an object 6734 * methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result 6735 * propExt: [ ... ] -- array - Array of Api object definitions to extend the property 6736 * }, 6737 * { 6738 * name: 'row' 6739 * val: {}, 6740 * methodExt: [ ... ], 6741 * propExt: [ 6742 * { 6743 * name: 'data' 6744 * val: function () {}, 6745 * methodExt: [ ... ], 6746 * propExt: [ ... ] 6747 * }, 6748 * ... 6749 * ] 6750 * } 6751 * ] 6752 * 6753 * @type {Array} 6754 * @ignore 6755 */ 6756 var __apiStruct = []; 6757 6758 6759 /** 6760 * `Array.prototype` reference. 6761 * 6762 * @type object 6763 * @ignore 6764 */ 6765 var __arrayProto = Array.prototype; 6766 6767 6768 /** 6769 * Abstraction for `context` parameter of the `Api` constructor to allow it to 6770 * take several different forms for ease of use. 6771 * 6772 * Each of the input parameter types will be converted to a DataTables settings 6773 * object where possible. 6774 * 6775 * @param {string|node|jQuery|object} mixed DataTable identifier. Can be one 6776 * of: 6777 * 6778 * * `string` - jQuery selector. Any DataTables' matching the given selector 6779 * with be found and used. 6780 * * `node` - `TABLE` node which has already been formed into a DataTable. 6781 * * `jQuery` - A jQuery object of `TABLE` nodes. 6782 * * `object` - DataTables settings object 6783 * * `DataTables.Api` - API instance 6784 * @return {array|null} Matching DataTables settings objects. `null` or 6785 * `undefined` is returned if no matching DataTable is found. 6786 * @ignore 6787 */ 6788 var _toSettings = function ( mixed ) 6789 { 6790 var idx, jq; 6791 var settings = DataTable.settings; 6792 var tables = $.map( settings, function (el, i) { 6793 return el.nTable; 6794 } ); 6795 6796 if ( ! mixed ) { 6797 return []; 6798 } 6799 else if ( mixed.nTable && mixed.oApi ) { 6800 // DataTables settings object 6801 return [ mixed ]; 6802 } 6803 else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) { 6804 // Table node 6805 idx = $.inArray( mixed, tables ); 6806 return idx !== -1 ? [ settings[idx] ] : null; 6807 } 6808 else if ( mixed && typeof mixed.settings === 'function' ) { 6809 return mixed.settings().toArray(); 6810 } 6811 else if ( typeof mixed === 'string' ) { 6812 // jQuery selector 6813 jq = $(mixed); 6814 } 6815 else if ( mixed instanceof $ ) { 6816 // jQuery object (also DataTables instance) 6817 jq = mixed; 6818 } 6819 6820 if ( jq ) { 6821 return jq.map( function(i) { 6822 idx = $.inArray( this, tables ); 6823 return idx !== -1 ? settings[idx] : null; 6824 } ).toArray(); 6825 } 6826 }; 6827 6828 6829 /** 6830 * DataTables API class - used to control and interface with one or more 6831 * DataTables enhanced tables. 6832 * 6833 * The API class is heavily based on jQuery, presenting a chainable interface 6834 * that you can use to interact with tables. Each instance of the API class has 6835 * a "context" - i.e. the tables that it will operate on. This could be a single 6836 * table, all tables on a page or a sub-set thereof. 6837 * 6838 * Additionally the API is designed to allow you to easily work with the data in 6839 * the tables, retrieving and manipulating it as required. This is done by 6840 * presenting the API class as an array like interface. The contents of the 6841 * array depend upon the actions requested by each method (for example 6842 * `rows().nodes()` will return an array of nodes, while `rows().data()` will 6843 * return an array of objects or arrays depending upon your table's 6844 * configuration). The API object has a number of array like methods (`push`, 6845 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`, 6846 * `unique` etc) to assist your working with the data held in a table. 6847 * 6848 * Most methods (those which return an Api instance) are chainable, which means 6849 * the return from a method call also has all of the methods available that the 6850 * top level object had. For example, these two calls are equivalent: 6851 * 6852 * // Not chained 6853 * api.row.add( {...} ); 6854 * api.draw(); 6855 * 6856 * // Chained 6857 * api.row.add( {...} ).draw(); 6858 * 6859 * @class DataTable.Api 6860 * @param {array|object|string|jQuery} context DataTable identifier. This is 6861 * used to define which DataTables enhanced tables this API will operate on. 6862 * Can be one of: 6863 * 6864 * * `string` - jQuery selector. Any DataTables' matching the given selector 6865 * with be found and used. 6866 * * `node` - `TABLE` node which has already been formed into a DataTable. 6867 * * `jQuery` - A jQuery object of `TABLE` nodes. 6868 * * `object` - DataTables settings object 6869 * @param {array} [data] Data to initialise the Api instance with. 6870 * 6871 * @example 6872 * // Direct initialisation during DataTables construction 6873 * var api = $('#example').DataTable(); 6874 * 6875 * @example 6876 * // Initialisation using a DataTables jQuery object 6877 * var api = $('#example').dataTable().api(); 6878 * 6879 * @example 6880 * // Initialisation as a constructor 6881 * var api = new $.fn.DataTable.Api( 'table.dataTable' ); 6882 */ 6883 _Api = function ( context, data ) 6884 { 6885 if ( ! (this instanceof _Api) ) { 6886 return new _Api( context, data ); 6887 } 6888 6889 var settings = []; 6890 var ctxSettings = function ( o ) { 6891 var a = _toSettings( o ); 6892 if ( a ) { 6893 settings = settings.concat( a ); 6894 } 6895 }; 6896 6897 if ( $.isArray( context ) ) { 6898 for ( var i=0, ien=context.length ; i<ien ; i++ ) { 6899 ctxSettings( context[i] ); 6900 } 6901 } 6902 else { 6903 ctxSettings( context ); 6904 } 6905 6906 // Remove duplicates 6907 this.context = _unique( settings ); 6908 6909 // Initial data 6910 if ( data ) { 6911 $.merge( this, data ); 6912 } 6913 6914 // selector 6915 this.selector = { 6916 rows: null, 6917 cols: null, 6918 opts: null 6919 }; 6920 6921 _Api.extend( this, this, __apiStruct ); 6922 }; 6923 6924 DataTable.Api = _Api; 6925 6926 // Don't destroy the existing prototype, just extend it. Required for jQuery 2's 6927 // isPlainObject. 6928 $.extend( _Api.prototype, { 6929 any: function () 6930 { 6931 return this.count() !== 0; 6932 }, 6933 6934 6935 concat: __arrayProto.concat, 6936 6937 6938 context: [], // array of table settings objects 6939 6940 6941 count: function () 6942 { 6943 return this.flatten().length; 6944 }, 6945 6946 6947 each: function ( fn ) 6948 { 6949 for ( var i=0, ien=this.length ; i<ien; i++ ) { 6950 fn.call( this, this[i], i, this ); 6951 } 6952 6953 return this; 6954 }, 6955 6956 6957 eq: function ( idx ) 6958 { 6959 var ctx = this.context; 6960 6961 return ctx.length > idx ? 6962 new _Api( ctx[idx], this[idx] ) : 6963 null; 6964 }, 6965 6966 6967 filter: function ( fn ) 6968 { 6969 var a = []; 6970 6971 if ( __arrayProto.filter ) { 6972 a = __arrayProto.filter.call( this, fn, this ); 6973 } 6974 else { 6975 // Compatibility for browsers without EMCA-252-5 (JS 1.6) 6976 for ( var i=0, ien=this.length ; i<ien ; i++ ) { 6977 if ( fn.call( this, this[i], i, this ) ) { 6978 a.push( this[i] ); 6979 } 6980 } 6981 } 6982 6983 return new _Api( this.context, a ); 6984 }, 6985 6986 6987 flatten: function () 6988 { 6989 var a = []; 6990 return new _Api( this.context, a.concat.apply( a, this.toArray() ) ); 6991 }, 6992 6993 6994 join: __arrayProto.join, 6995 6996 6997 indexOf: __arrayProto.indexOf || function (obj, start) 6998 { 6999 for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) { 7000 if ( this[i] === obj ) { 7001 return i; 7002 } 7003 } 7004 return -1; 7005 }, 7006 7007 iterator: function ( flatten, type, fn, alwaysNew ) { 7008 var 7009 a = [], ret, 7010 i, ien, j, jen, 7011 context = this.context, 7012 rows, items, item, 7013 selector = this.selector; 7014 7015 // Argument shifting 7016 if ( typeof flatten === 'string' ) { 7017 alwaysNew = fn; 7018 fn = type; 7019 type = flatten; 7020 flatten = false; 7021 } 7022 7023 for ( i=0, ien=context.length ; i<ien ; i++ ) { 7024 var apiInst = new _Api( context[i] ); 7025 7026 if ( type === 'table' ) { 7027 ret = fn.call( apiInst, context[i], i ); 7028 7029 if ( ret !== undefined ) { 7030 a.push( ret ); 7031 } 7032 } 7033 else if ( type === 'columns' || type === 'rows' ) { 7034 // this has same length as context - one entry for each table 7035 ret = fn.call( apiInst, context[i], this[i], i ); 7036 7037 if ( ret !== undefined ) { 7038 a.push( ret ); 7039 } 7040 } 7041 else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) { 7042 // columns and rows share the same structure. 7043 // 'this' is an array of column indexes for each context 7044 items = this[i]; 7045 7046 if ( type === 'column-rows' ) { 7047 rows = _selector_row_indexes( context[i], selector.opts ); 7048 } 7049 7050 for ( j=0, jen=items.length ; j<jen ; j++ ) { 7051 item = items[j]; 7052 7053 if ( type === 'cell' ) { 7054 ret = fn.call( apiInst, context[i], item.row, item.column, i, j ); 7055 } 7056 else { 7057 ret = fn.call( apiInst, context[i], item, i, j, rows ); 7058 } 7059 7060 if ( ret !== undefined ) { 7061 a.push( ret ); 7062 } 7063 } 7064 } 7065 } 7066 7067 if ( a.length || alwaysNew ) { 7068 var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a ); 7069 var apiSelector = api.selector; 7070 apiSelector.rows = selector.rows; 7071 apiSelector.cols = selector.cols; 7072 apiSelector.opts = selector.opts; 7073 return api; 7074 } 7075 return this; 7076 }, 7077 7078 7079 lastIndexOf: __arrayProto.lastIndexOf || function (obj, start) 7080 { 7081 // Bit cheeky... 7082 return this.indexOf.apply( this.toArray.reverse(), arguments ); 7083 }, 7084 7085 7086 length: 0, 7087 7088 7089 map: function ( fn ) 7090 { 7091 var a = []; 7092 7093 if ( __arrayProto.map ) { 7094 a = __arrayProto.map.call( this, fn, this ); 7095 } 7096 else { 7097 // Compatibility for browsers without EMCA-252-5 (JS 1.6) 7098 for ( var i=0, ien=this.length ; i<ien ; i++ ) { 7099 a.push( fn.call( this, this[i], i ) ); 7100 } 7101 } 7102 7103 return new _Api( this.context, a ); 7104 }, 7105 7106 7107 pluck: function ( prop ) 7108 { 7109 return this.map( function ( el ) { 7110 return el[ prop ]; 7111 } ); 7112 }, 7113 7114 pop: __arrayProto.pop, 7115 7116 7117 push: __arrayProto.push, 7118 7119 7120 // Does not return an API instance 7121 reduce: __arrayProto.reduce || function ( fn, init ) 7122 { 7123 return _fnReduce( this, fn, init, 0, this.length, 1 ); 7124 }, 7125 7126 7127 reduceRight: __arrayProto.reduceRight || function ( fn, init ) 7128 { 7129 return _fnReduce( this, fn, init, this.length-1, -1, -1 ); 7130 }, 7131 7132 7133 reverse: __arrayProto.reverse, 7134 7135 7136 // Object with rows, columns and opts 7137 selector: null, 7138 7139 7140 shift: __arrayProto.shift, 7141 7142 7143 slice: function () { 7144 return new _Api( this.context, this ); 7145 }, 7146 7147 7148 sort: __arrayProto.sort, // ? name - order? 7149 7150 7151 splice: __arrayProto.splice, 7152 7153 7154 toArray: function () 7155 { 7156 return __arrayProto.slice.call( this ); 7157 }, 7158 7159 7160 to$: function () 7161 { 7162 return $( this ); 7163 }, 7164 7165 7166 toJQuery: function () 7167 { 7168 return $( this ); 7169 }, 7170 7171 7172 unique: function () 7173 { 7174 return new _Api( this.context, _unique(this) ); 7175 }, 7176 7177 7178 unshift: __arrayProto.unshift 7179 } ); 7180 7181 7182 _Api.extend = function ( scope, obj, ext ) 7183 { 7184 // Only extend API instances and static properties of the API 7185 if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) { 7186 return; 7187 } 7188 7189 var 7190 i, ien, 7191 j, jen, 7192 struct, inner, 7193 methodScoping = function ( scope, fn, struc ) { 7194 return function () { 7195 var ret = fn.apply( scope, arguments ); 7196 7197 // Method extension 7198 _Api.extend( ret, ret, struc.methodExt ); 7199 return ret; 7200 }; 7201 }; 7202 7203 for ( i=0, ien=ext.length ; i<ien ; i++ ) { 7204 struct = ext[i]; 7205 7206 // Value 7207 obj[ struct.name ] = typeof struct.val === 'function' ? 7208 methodScoping( scope, struct.val, struct ) : 7209 $.isPlainObject( struct.val ) ? 7210 {} : 7211 struct.val; 7212 7213 obj[ struct.name ].__dt_wrapper = true; 7214 7215 // Property extension 7216 _Api.extend( scope, obj[ struct.name ], struct.propExt ); 7217 } 7218 }; 7219 7220 7221 // @todo - Is there need for an augment function? 7222 // _Api.augment = function ( inst, name ) 7223 // { 7224 // // Find src object in the structure from the name 7225 // var parts = name.split('.'); 7226 7227 // _Api.extend( inst, obj ); 7228 // }; 7229 7230 7231 // [ 7232 // { 7233 // name: 'data' -- string - Property name 7234 // val: function () {}, -- function - Api method (or undefined if just an object 7235 // methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result 7236 // propExt: [ ... ] -- array - Array of Api object definitions to extend the property 7237 // }, 7238 // { 7239 // name: 'row' 7240 // val: {}, 7241 // methodExt: [ ... ], 7242 // propExt: [ 7243 // { 7244 // name: 'data' 7245 // val: function () {}, 7246 // methodExt: [ ... ], 7247 // propExt: [ ... ] 7248 // }, 7249 // ... 7250 // ] 7251 // } 7252 // ] 7253 7254 _Api.register = _api_register = function ( name, val ) 7255 { 7256 if ( $.isArray( name ) ) { 7257 for ( var j=0, jen=name.length ; j<jen ; j++ ) { 7258 _Api.register( name[j], val ); 7259 } 7260 return; 7261 } 7262 7263 var 7264 i, ien, 7265 heir = name.split('.'), 7266 struct = __apiStruct, 7267 key, method; 7268 7269 var find = function ( src, name ) { 7270 for ( var i=0, ien=src.length ; i<ien ; i++ ) { 7271 if ( src[i].name === name ) { 7272 return src[i]; 7273 } 7274 } 7275 return null; 7276 }; 7277 7278 for ( i=0, ien=heir.length ; i<ien ; i++ ) { 7279 method = heir[i].indexOf('()') !== -1; 7280 key = method ? 7281 heir[i].replace('()', '') : 7282 heir[i]; 7283 7284 var src = find( struct, key ); 7285 if ( ! src ) { 7286 src = { 7287 name: key, 7288 val: {}, 7289 methodExt: [], 7290 propExt: [] 7291 }; 7292 struct.push( src ); 7293 } 7294 7295 if ( i === ien-1 ) { 7296 src.val = val; 7297 } 7298 else { 7299 struct = method ? 7300 src.methodExt : 7301 src.propExt; 7302 } 7303 } 7304 }; 7305 7306 7307 _Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) { 7308 _Api.register( pluralName, val ); 7309 7310 _Api.register( singularName, function () { 7311 var ret = val.apply( this, arguments ); 7312 7313 if ( ret === this ) { 7314 // Returned item is the API instance that was passed in, return it 7315 return this; 7316 } 7317 else if ( ret instanceof _Api ) { 7318 // New API instance returned, want the value from the first item 7319 // in the returned array for the singular result. 7320 return ret.length ? 7321 $.isArray( ret[0] ) ? 7322 new _Api( ret.context, ret[0] ) : // Array results are 'enhanced' 7323 ret[0] : 7324 undefined; 7325 } 7326 7327 // Non-API return - just fire it back 7328 return ret; 7329 } ); 7330 }; 7331 7332 7333 /** 7334 * Selector for HTML tables. Apply the given selector to the give array of 7335 * DataTables settings objects. 7336 * 7337 * @param {string|integer} [selector] jQuery selector string or integer 7338 * @param {array} Array of DataTables settings objects to be filtered 7339 * @return {array} 7340 * @ignore 7341 */ 7342 var __table_selector = function ( selector, a ) 7343 { 7344 // Integer is used to pick out a table by index 7345 if ( typeof selector === 'number' ) { 7346 return [ a[ selector ] ]; 7347 } 7348 7349 // Perform a jQuery selector on the table nodes 7350 var nodes = $.map( a, function (el, i) { 7351 return el.nTable; 7352 } ); 7353 7354 return $(nodes) 7355 .filter( selector ) 7356 .map( function (i) { 7357 // Need to translate back from the table node to the settings 7358 var idx = $.inArray( this, nodes ); 7359 return a[ idx ]; 7360 } ) 7361 .toArray(); 7362 }; 7363 7364 7365 7366 /** 7367 * Context selector for the API's context (i.e. the tables the API instance 7368 * refers to. 7369 * 7370 * @name DataTable.Api#tables 7371 * @param {string|integer} [selector] Selector to pick which tables the iterator 7372 * should operate on. If not given, all tables in the current context are 7373 * used. This can be given as a jQuery selector (for example `':gt(0)'`) to 7374 * select multiple tables or as an integer to select a single table. 7375 * @returns {DataTable.Api} Returns a new API instance if a selector is given. 7376 */ 7377 _api_register( 'tables()', function ( selector ) { 7378 // A new instance is created if there was a selector specified 7379 return selector
vendor: 9,632 bytes, lines 7379-7727
7379 ? 7380 new _Api( __table_selector( selector, this.context ) ) : 7381 this; 7382 } ); 7383 7384 7385 _api_register( 'table()', function ( selector ) { 7386 var tables = this.tables( selector ); 7387 var ctx = tables.context; 7388 7389 // Truncate to the first matched table 7390 return ctx.length ? 7391 new _Api( ctx[0] ) : 7392 tables; 7393 } ); 7394 7395 7396 _api_registerPlural( 'tables().nodes()', 'table().node()' , function () { 7397 return this.iterator( 'table', function ( ctx ) { 7398 return ctx.nTable; 7399 }, 1 ); 7400 } ); 7401 7402 7403 _api_registerPlural( 'tables().body()', 'table().body()' , function () { 7404 return this.iterator( 'table', function ( ctx ) { 7405 return ctx.nTBody; 7406 }, 1 ); 7407 } ); 7408 7409 7410 _api_registerPlural( 'tables().header()', 'table().header()' , function () { 7411 return this.iterator( 'table', function ( ctx ) { 7412 return ctx.nTHead; 7413 }, 1 ); 7414 } ); 7415 7416 7417 _api_registerPlural( 'tables().footer()', 'table().footer()' , function () { 7418 return this.iterator( 'table', function ( ctx ) { 7419 return ctx.nTFoot; 7420 }, 1 ); 7421 } ); 7422 7423 7424 _api_registerPlural( 'tables().containers()', 'table().container()' , function () { 7425 return this.iterator( 'table', function ( ctx ) { 7426 return ctx.nTableWrapper; 7427 }, 1 ); 7428 } ); 7429 7430 7431 7432 /** 7433 * Redraw the tables in the current context. 7434 */ 7435 _api_register( 'draw()', function ( paging ) { 7436 return this.iterator( 'table', function ( settings ) { 7437 if ( paging === 'page' ) { 7438 _fnDraw( settings ); 7439 } 7440 else { 7441 if ( typeof paging === 'string' ) { 7442 paging = paging === 'full-hold' ? 7443 false : 7444 true; 7445 } 7446 7447 _fnReDraw( settings, paging===false ); 7448 } 7449 } ); 7450 } ); 7451 7452 7453 7454 /** 7455 * Get the current page index. 7456 * 7457 * @return {integer} Current page index (zero based) 7458 *//** 7459 * Set the current page. 7460 * 7461 * Note that if you attempt to show a page which does not exist, DataTables will 7462 * not throw an error, but rather reset the paging. 7463 * 7464 * @param {integer|string} action The paging action to take. This can be one of: 7465 * * `integer` - The page index to jump to 7466 * * `string` - An action to take: 7467 * * `first` - Jump to first page. 7468 * * `next` - Jump to the next page 7469 * * `previous` - Jump to previous page 7470 * * `last` - Jump to the last page. 7471 * @returns {DataTables.Api} this 7472 */ 7473 _api_register( 'page()', function ( action ) { 7474 if ( action === undefined ) { 7475 return this.page.info().page; // not an expensive call 7476 } 7477 7478 // else, have an action to take on all tables 7479 return this.iterator( 'table', function ( settings ) { 7480 _fnPageChange( settings, action ); 7481 } ); 7482 } ); 7483 7484 7485 /** 7486 * Paging information for the first table in the current context. 7487 * 7488 * If you require paging information for another table, use the `table()` method 7489 * with a suitable selector. 7490 * 7491 * @return {object} Object with the following properties set: 7492 * * `page` - Current page index (zero based - i.e. the first page is `0`) 7493 * * `pages` - Total number of pages 7494 * * `start` - Display index for the first record shown on the current page 7495 * * `end` - Display index for the last record shown on the current page 7496 * * `length` - Display length (number of records). Note that generally `start 7497 * + length = end`, but this is not always true, for example if there are 7498 * only 2 records to show on the final page, with a length of 10. 7499 * * `recordsTotal` - Full data set length 7500 * * `recordsDisplay` - Data set length once the current filtering criterion 7501 * are applied. 7502 */ 7503 _api_register( 'page.info()', function ( action ) { 7504 if ( this.context.length === 0 ) { 7505 return undefined; 7506 } 7507 7508 var 7509 settings = this.context[0], 7510 start = settings._iDisplayStart, 7511 len = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1, 7512 visRecords = settings.fnRecordsDisplay(), 7513 all = len === -1; 7514 7515 return { 7516 "page": all ? 0 : Math.floor( start / len ), 7517 "pages": all ? 1 : Math.ceil( visRecords / len ), 7518 "start": start, 7519 "end": settings.fnDisplayEnd(), 7520 "length": len, 7521 "recordsTotal": settings.fnRecordsTotal(), 7522 "recordsDisplay": visRecords, 7523 "serverSide": _fnDataSource( settings ) === 'ssp' 7524 }; 7525 } ); 7526 7527 7528 /** 7529 * Get the current page length. 7530 * 7531 * @return {integer} Current page length. Note `-1` indicates that all records 7532 * are to be shown. 7533 *//** 7534 * Set the current page length. 7535 * 7536 * @param {integer} Page length to set. Use `-1` to show all records. 7537 * @returns {DataTables.Api} this 7538 */ 7539 _api_register( 'page.len()', function ( len ) { 7540 // Note that we can't call this function 'length()' because `length` 7541 // is a Javascript property of functions which defines how many arguments 7542 // the function expects. 7543 if ( len === undefined ) { 7544 return this.context.length !== 0 ? 7545 this.context[0]._iDisplayLength : 7546 undefined; 7547 } 7548 7549 // else, set the page length 7550 return this.iterator( 'table', function ( settings ) { 7551 _fnLengthChange( settings, len ); 7552 } ); 7553 } ); 7554 7555 7556 7557 var __reload = function ( settings, holdPosition, callback ) { 7558 // Use the draw event to trigger a callback 7559 if ( callback ) { 7560 var api = new _Api( settings ); 7561 7562 api.one( 'draw', function () { 7563 callback( api.ajax.json() ); 7564 } ); 7565 } 7566 7567 if ( _fnDataSource( settings ) == 'ssp' ) { 7568 _fnReDraw( settings, holdPosition ); 7569 } 7570 else { 7571 _fnProcessingDisplay( settings, true ); 7572 7573 // Cancel an existing request 7574 var xhr = settings.jqXHR; 7575 if ( xhr && xhr.readyState !== 4 ) { 7576 xhr.abort(); 7577 } 7578 7579 // Trigger xhr 7580 _fnBuildAjax( settings, [], function( json ) { 7581 _fnClearTable( settings ); 7582 7583 var data = _fnAjaxDataSrc( settings, json ); 7584 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 7585 _fnAddData( settings, data[i] ); 7586 } 7587 7588 _fnReDraw( settings, holdPosition ); 7589 _fnProcessingDisplay( settings, false ); 7590 } ); 7591 } 7592 }; 7593 7594 7595 /** 7596 * Get the JSON response from the last Ajax request that DataTables made to the 7597 * server. Note that this returns the JSON from the first table in the current 7598 * context. 7599 * 7600 * @return {object} JSON received from the server. 7601 */ 7602 _api_register( 'ajax.json()', function () { 7603 var ctx = this.context; 7604 7605 if ( ctx.length > 0 ) { 7606 return ctx[0].json; 7607 } 7608 7609 // else return undefined; 7610 } ); 7611 7612 7613 /** 7614 * Get the data submitted in the last Ajax request 7615 */ 7616 _api_register( 'ajax.params()', function () { 7617 var ctx = this.context; 7618 7619 if ( ctx.length > 0 ) { 7620 return ctx[0].oAjaxData; 7621 } 7622 7623 // else return undefined; 7624 } ); 7625 7626 7627 /** 7628 * Reload tables from the Ajax data source. Note that this function will 7629 * automatically re-draw the table when the remote data has been loaded. 7630 * 7631 * @param {boolean} [reset=true] Reset (default) or hold the current paging 7632 * position. A full re-sort and re-filter is performed when this method is 7633 * called, which is why the pagination reset is the default action. 7634 * @returns {DataTables.Api} this 7635 */ 7636 _api_register( 'ajax.reload()', function ( callback, resetPaging ) { 7637 return this.iterator( 'table', function (settings) { 7638 __reload( settings, resetPaging===false, callback ); 7639 } ); 7640 } ); 7641 7642 7643 /** 7644 * Get the current Ajax URL. Note that this returns the URL from the first 7645 * table in the current context. 7646 * 7647 * @return {string} Current Ajax source URL 7648 *//** 7649 * Set the Ajax URL. Note that this will set the URL for all tables in the 7650 * current context. 7651 * 7652 * @param {string} url URL to set. 7653 * @returns {DataTables.Api} this 7654 */ 7655 _api_register( 'ajax.url()', function ( url ) { 7656 var ctx = this.context; 7657 7658 if ( url === undefined ) { 7659 // get 7660 if ( ctx.length === 0 ) { 7661 return undefined; 7662 } 7663 ctx = ctx[0]; 7664 7665 return ctx.ajax ? 7666 $.isPlainObject( ctx.ajax ) ? 7667 ctx.ajax.url : 7668 ctx.ajax : 7669 ctx.sAjaxSource; 7670 } 7671 7672 // set 7673 return this.iterator( 'table', function ( settings ) { 7674 if ( $.isPlainObject( settings.ajax ) ) { 7675 settings.ajax.url = url; 7676 } 7677 else { 7678 settings.ajax = url; 7679 } 7680 // No need to consider sAjaxSource here since DataTables gives priority 7681 // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any 7682 // value of `sAjaxSource` redundant. 7683 } ); 7684 } ); 7685 7686 7687 /** 7688 * Load data from the newly set Ajax URL. Note that this method is only 7689 * available when `ajax.url()` is used to set a URL. Additionally, this method 7690 * has the same effect as calling `ajax.reload()` but is provided for 7691 * convenience when setting a new URL. Like `ajax.reload()` it will 7692 * automatically redraw the table once the remote data has been loaded. 7693 * 7694 * @returns {DataTables.Api} this 7695 */ 7696 _api_register( 'ajax.url().load()', function ( callback, resetPaging ) { 7697 // Same as a reload, but makes sense to present it for easy access after a 7698 // url change 7699 return this.iterator( 'table', function ( ctx ) { 7700 __reload( ctx, resetPaging===false, callback ); 7701 } ); 7702 } ); 7703 7704 7705 7706 7707 var _selector_run = function ( type, selector, selectFn, settings, opts ) 7708 { 7709 var 7710 out = [], res, 7711 a, i, ien, j, jen, 7712 selectorType = typeof selector; 7713 7714 // Can't just check for isArray here, as an API or jQuery instance might be 7715 // given with their array like look 7716 if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) { 7717 selector = [ selector ]; 7718 } 7719 7720 for ( i=0, ien=selector.length ; i<ien ; i++ ) { 7721 // Only split on simple strings - complex expressions will be jQuery selectors 7722 a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ? 7723 selector[i].split(',') : 7724 [ selector[i] ]; 7725 7726 for ( j=0, jen=a.length ; j<jen ; j++ ) { 7727 res = selectFn( typeof a[j] === 'string' ?
vendor: 47,870 bytes, lines 7727-9526
7727$.trim(a[j]) : a[j] ); 7728 7729 if ( res && res.length ) { 7730 out = out.concat( res ); 7731 } 7732 } 7733 } 7734 7735 // selector extensions 7736 var ext = _ext.selector[ type ]; 7737 if ( ext.length ) { 7738 for ( i=0, ien=ext.length ; i<ien ; i++ ) { 7739 out = ext[i]( settings, opts, out ); 7740 } 7741 } 7742 7743 return _unique( out ); 7744 }; 7745 7746 7747 var _selector_opts = function ( opts ) 7748 { 7749 if ( ! opts ) { 7750 opts = {}; 7751 } 7752 7753 // Backwards compatibility for 1.9- which used the terminology filter rather 7754 // than search 7755 if ( opts.filter && opts.search === undefined ) { 7756 opts.search = opts.filter; 7757 } 7758 7759 return $.extend( { 7760 search: 'none', 7761 order: 'current', 7762 page: 'all' 7763 }, opts ); 7764 }; 7765 7766 7767 var _selector_first = function ( inst ) 7768 { 7769 // Reduce the API instance to the first item found 7770 for ( var i=0, ien=inst.length ; i<ien ; i++ ) { 7771 if ( inst[i].length > 0 ) { 7772 // Assign the first element to the first item in the instance 7773 // and truncate the instance and context 7774 inst[0] = inst[i]; 7775 inst[0].length = 1; 7776 inst.length = 1; 7777 inst.context = [ inst.context[i] ]; 7778 7779 return inst; 7780 } 7781 } 7782 7783 // Not found - return an empty instance 7784 inst.length = 0; 7785 return inst; 7786 }; 7787 7788 7789 var _selector_row_indexes = function ( settings, opts ) 7790 { 7791 var 7792 i, ien, tmp, a=[], 7793 displayFiltered = settings.aiDisplay, 7794 displayMaster = settings.aiDisplayMaster; 7795 7796 var 7797 search = opts.search, // none, applied, removed 7798 order = opts.order, // applied, current, index (original - compatibility with 1.9) 7799 page = opts.page; // all, current 7800 7801 if ( _fnDataSource( settings ) == 'ssp' ) { 7802 // In server-side processing mode, most options are irrelevant since 7803 // rows not shown don't exist and the index order is the applied order 7804 // Removed is a special case - for consistency just return an empty 7805 // array 7806 return search === 'removed' ? 7807 [] : 7808 _range( 0, displayMaster.length ); 7809 } 7810 else if ( page == 'current' ) { 7811 // Current page implies that order=current and fitler=applied, since it is 7812 // fairly senseless otherwise, regardless of what order and search actually 7813 // are 7814 for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) { 7815 a.push( displayFiltered[i] ); 7816 } 7817 } 7818 else if ( order == 'current' || order == 'applied' ) { 7819 if ( search == 'none') { 7820 a = displayMaster.slice(); 7821 } 7822 else if ( search == 'applied' ) { 7823 a = displayFiltered.slice(); 7824 } 7825 else if ( search == 'removed' ) { 7826 // O(n+m) solution by creating a hash map 7827 var displayFilteredMap = {}; 7828 7829 for ( var i=0, ien=displayFiltered.length ; i<ien ; i++ ) { 7830 displayFilteredMap[displayFiltered[i]] = null; 7831 } 7832 7833 a = $.map( displayMaster, function (el) { 7834 return ! displayFilteredMap.hasOwnProperty(el) ? 7835 el : 7836 null; 7837 } ); 7838 } 7839 } 7840 else if ( order == 'index' || order == 'original' ) { 7841 for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 7842 if ( search == 'none' ) { 7843 a.push( i ); 7844 } 7845 else { // applied | removed 7846 tmp = $.inArray( i, displayFiltered ); 7847 7848 if ((tmp === -1 && search == 'removed') || 7849 (tmp >= 0 && search == 'applied') ) 7850 { 7851 a.push( i ); 7852 } 7853 } 7854 } 7855 } 7856 7857 return a; 7858 }; 7859 7860 7861 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 7862 * Rows 7863 * 7864 * {} - no selector - use all available rows 7865 * {integer} - row aoData index 7866 * {node} - TR node 7867 * {string} - jQuery selector to apply to the TR elements 7868 * {array} - jQuery array of nodes, or simply an array of TR nodes 7869 * 7870 */ 7871 var __row_selector = function ( settings, selector, opts ) 7872 { 7873 var rows; 7874 var run = function ( sel ) { 7875 var selInt = _intVal( sel ); 7876 var i, ien; 7877 var aoData = settings.aoData; 7878 7879 // Short cut - selector is a number and no options provided (default is 7880 // all records, so no need to check if the index is in there, since it 7881 // must be - dev error if the index doesn't exist). 7882 if ( selInt !== null && ! opts ) { 7883 return [ selInt ]; 7884 } 7885 7886 if ( ! rows ) { 7887 rows = _selector_row_indexes( settings, opts ); 7888 } 7889 7890 if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) { 7891 // Selector - integer 7892 return [ selInt ]; 7893 } 7894 else if ( sel === null || sel === undefined || sel === '' ) { 7895 // Selector - none 7896 return rows; 7897 } 7898 7899 // Selector - function 7900 if ( typeof sel === 'function' ) { 7901 return $.map( rows, function (idx) { 7902 var row = aoData[ idx ]; 7903 return sel( idx, row._aData, row.nTr ) ? idx : null; 7904 } ); 7905 } 7906 7907 // Selector - node 7908 if ( sel.nodeName ) { 7909 var rowIdx = sel._DT_RowIndex; // Property added by DT for fast lookup 7910 var cellIdx = sel._DT_CellIndex; 7911 7912 if ( rowIdx !== undefined ) { 7913 // Make sure that the row is actually still present in the table 7914 return aoData[ rowIdx ] && aoData[ rowIdx ].nTr === sel ? 7915 [ rowIdx ] : 7916 []; 7917 } 7918 else if ( cellIdx ) { 7919 return aoData[ cellIdx.row ] && aoData[ cellIdx.row ].nTr === sel ? 7920 [ cellIdx.row ] : 7921 []; 7922 } 7923 else { 7924 var host = $(sel).closest('*[data-dt-row]'); 7925 return host.length ? 7926 [ host.data('dt-row') ] : 7927 []; 7928 } 7929 } 7930 7931 // ID selector. Want to always be able to select rows by id, regardless 7932 // of if the tr element has been created or not, so can't rely upon 7933 // jQuery here - hence a custom implementation. This does not match 7934 // Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything, 7935 // but to select it using a CSS selector engine (like Sizzle or 7936 // querySelect) it would need to need to be escaped for some characters. 7937 // DataTables simplifies this for row selectors since you can select 7938 // only a row. A # indicates an id any anything that follows is the id - 7939 // unescaped. 7940 if ( typeof sel === 'string' && sel.charAt(0) === '#' ) { 7941 // get row index from id 7942 var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ]; 7943 if ( rowObj !== undefined ) { 7944 return [ rowObj.idx ]; 7945 } 7946 7947 // need to fall through to jQuery in case there is DOM id that 7948 // matches 7949 } 7950 7951 // Get nodes in the order from the `rows` array with null values removed 7952 var nodes = _removeEmpty( 7953 _pluck_order( settings.aoData, rows, 'nTr' ) 7954 ); 7955 7956 // Selector - jQuery selector string, array of nodes or jQuery object/ 7957 // As jQuery's .filter() allows jQuery objects to be passed in filter, 7958 // it also allows arrays, so this will cope with all three options 7959 return $(nodes) 7960 .filter( sel ) 7961 .map( function () { 7962 return this._DT_RowIndex; 7963 } ) 7964 .toArray(); 7965 }; 7966 7967 return _selector_run( 'row', selector, run, settings, opts ); 7968 }; 7969 7970 7971 _api_register( 'rows()', function ( selector, opts ) { 7972 // argument shifting 7973 if ( selector === undefined ) { 7974 selector = ''; 7975 } 7976 else if ( $.isPlainObject( selector ) ) { 7977 opts = selector; 7978 selector = ''; 7979 } 7980 7981 opts = _selector_opts( opts ); 7982 7983 var inst = this.iterator( 'table', function ( settings ) { 7984 return __row_selector( settings, selector, opts ); 7985 }, 1 ); 7986 7987 // Want argument shifting here and in __row_selector? 7988 inst.selector.rows = selector; 7989 inst.selector.opts = opts; 7990 7991 return inst; 7992 } ); 7993 7994 _api_register( 'rows().nodes()', function () { 7995 return this.iterator( 'row', function ( settings, row ) { 7996 return settings.aoData[ row ].nTr || undefined; 7997 }, 1 ); 7998 } ); 7999 8000 _api_register( 'rows().data()', function () { 8001 return this.iterator( true, 'rows', function ( settings, rows ) { 8002 return _pluck_order( settings.aoData, rows, '_aData' ); 8003 }, 1 ); 8004 } ); 8005 8006 _api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) { 8007 return this.iterator( 'row', function ( settings, row ) { 8008 var r = settings.aoData[ row ]; 8009 return type === 'search' ? r._aFilterData : r._aSortData; 8010 }, 1 ); 8011 } ); 8012 8013 _api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) { 8014 return this.iterator( 'row', function ( settings, row ) { 8015 _fnInvalidate( settings, row, src ); 8016 } ); 8017 } ); 8018 8019 _api_registerPlural( 'rows().indexes()', 'row().index()', function () { 8020 return this.iterator( 'row', function ( settings, row ) { 8021 return row; 8022 }, 1 ); 8023 } ); 8024 8025 _api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) { 8026 var a = []; 8027 var context = this.context; 8028 8029 // `iterator` will drop undefined values, but in this case we want them 8030 for ( var i=0, ien=context.length ; i<ien ; i++ ) { 8031 for ( var j=0, jen=this[i].length ; j<jen ; j++ ) { 8032 var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData ); 8033 a.push( (hash === true ? '#' : '' )+ id ); 8034 } 8035 } 8036 8037 return new _Api( context, a ); 8038 } ); 8039 8040 _api_registerPlural( 'rows().remove()', 'row().remove()', function () { 8041 var that = this; 8042 8043 this.iterator( 'row', function ( settings, row, thatIdx ) { 8044 var data = settings.aoData; 8045 var rowData = data[ row ]; 8046 var i, ien, j, jen; 8047 var loopRow, loopCells; 8048 8049 data.splice( row, 1 ); 8050 8051 // Update the cached indexes 8052 for ( i=0, ien=data.length ; i<ien ; i++ ) { 8053 loopRow = data[i]; 8054 loopCells = loopRow.anCells; 8055 8056 // Rows 8057 if ( loopRow.nTr !== null ) { 8058 loopRow.nTr._DT_RowIndex = i; 8059 } 8060 8061 // Cells 8062 if ( loopCells !== null ) { 8063 for ( j=0, jen=loopCells.length ; j<jen ; j++ ) { 8064 loopCells[j]._DT_CellIndex.row = i; 8065 } 8066 } 8067 } 8068 8069 // Delete from the display arrays 8070 _fnDeleteIndex( settings.aiDisplayMaster, row ); 8071 _fnDeleteIndex( settings.aiDisplay, row ); 8072 _fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes 8073 8074 // For server-side processing tables - subtract the deleted row from the count 8075 if ( settings._iRecordsDisplay > 0 ) { 8076 settings._iRecordsDisplay--; 8077 } 8078 8079 // Check for an 'overflow' they case for displaying the table 8080 _fnLengthOverflow( settings ); 8081 8082 // Remove the row's ID reference if there is one 8083 var id = settings.rowIdFn( rowData._aData ); 8084 if ( id !== undefined ) { 8085 delete settings.aIds[ id ]; 8086 } 8087 } ); 8088 8089 this.iterator( 'table', function ( settings ) { 8090 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 8091 settings.aoData[i].idx = i; 8092 } 8093 } ); 8094 8095 return this; 8096 } ); 8097 8098 8099 _api_register( 'rows.add()', function ( rows ) { 8100 var newRows = this.iterator( 'table', function ( settings ) { 8101 var row, i, ien; 8102 var out = []; 8103 8104 for ( i=0, ien=rows.length ; i<ien ; i++ ) { 8105 row = rows[i]; 8106 8107 if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) { 8108 out.push( _fnAddTr( settings, row )[0] ); 8109 } 8110 else { 8111 out.push( _fnAddData( settings, row ) ); 8112 } 8113 } 8114 8115 return out; 8116 }, 1 ); 8117 8118 // Return an Api.rows() extended instance, so rows().nodes() etc can be used 8119 var modRows = this.rows( -1 ); 8120 modRows.pop(); 8121 $.merge( modRows, newRows ); 8122 8123 return modRows; 8124 } ); 8125 8126 8127 8128 8129 8130 /** 8131 * 8132 */ 8133 _api_register( 'row()', function ( selector, opts ) { 8134 return _selector_first( this.rows( selector, opts ) ); 8135 } ); 8136 8137 8138 _api_register( 'row().data()', function ( data ) { 8139 var ctx = this.context; 8140 8141 if ( data === undefined ) { 8142 // Get 8143 return ctx.length && this.length ? 8144 ctx[0].aoData[ this[0] ]._aData : 8145 undefined; 8146 } 8147 8148 // Set 8149 var row = ctx[0].aoData[ this[0] ]; 8150 row._aData = data; 8151 8152 // If the DOM has an id, and the data source is an array 8153 if ( $.isArray( data ) && row.nTr.id ) { 8154 _fnSetObjectDataFn( ctx[0].rowId )( data, row.nTr.id ); 8155 } 8156 8157 // Automatically invalidate 8158 _fnInvalidate( ctx[0], this[0], 'data' ); 8159 8160 return this; 8161 } ); 8162 8163 8164 _api_register( 'row().node()', function () { 8165 var ctx = this.context; 8166 8167 return ctx.length && this.length ? 8168 ctx[0].aoData[ this[0] ].nTr || null : 8169 null; 8170 } ); 8171 8172 8173 _api_register( 'row.add()', function ( row ) { 8174 // Allow a jQuery object to be passed in - only a single row is added from 8175 // it though - the first element in the set 8176 if ( row instanceof $ && row.length ) { 8177 row = row[0]; 8178 } 8179 8180 var rows = this.iterator( 'table', function ( settings ) { 8181 if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) { 8182 return _fnAddTr( settings, row )[0]; 8183 } 8184 return _fnAddData( settings, row ); 8185 } ); 8186 8187 // Return an Api.rows() extended instance, with the newly added row selected 8188 return this.row( rows[0] ); 8189 } ); 8190 8191 8192 8193 var __details_add = function ( ctx, row, data, klass ) 8194 { 8195 // Convert to array of TR elements 8196 var rows = []; 8197 var addRow = function ( r, k ) { 8198 // Recursion to allow for arrays of jQuery objects 8199 if ( $.isArray( r ) || r instanceof $ ) { 8200 for ( var i=0, ien=r.length ; i<ien ; i++ ) { 8201 addRow( r[i], k ); 8202 } 8203 return; 8204 } 8205 8206 // If we get a TR element, then just add it directly - up to the dev 8207 // to add the correct number of columns etc 8208 if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) { 8209 rows.push( r ); 8210 } 8211 else { 8212 // Otherwise create a row with a wrapper 8213 var created = $('<tr><td/></tr>').addClass( k ); 8214 $('td', created) 8215 .addClass( k ) 8216 .html( r ) 8217 [0].colSpan = _fnVisbleColumns( ctx ); 8218 8219 rows.push( created[0] ); 8220 } 8221 }; 8222 8223 addRow( data, klass ); 8224 8225 if ( row._details ) { 8226 row._details.detach(); 8227 } 8228 8229 row._details = $(rows); 8230 8231 // If the children were already shown, that state should be retained 8232 if ( row._detailsShow ) { 8233 row._details.insertAfter( row.nTr ); 8234 } 8235 }; 8236 8237 8238 var __details_remove = function ( api, idx ) 8239 { 8240 var ctx = api.context; 8241 8242 if ( ctx.length ) { 8243 var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ]; 8244 8245 if ( row && row._details ) { 8246 row._details.remove(); 8247 8248 row._detailsShow = undefined; 8249 row._details = undefined; 8250 } 8251 } 8252 }; 8253 8254 8255 var __details_display = function ( api, show ) { 8256 var ctx = api.context; 8257 8258 if ( ctx.length && api.length ) { 8259 var row = ctx[0].aoData[ api[0] ]; 8260 8261 if ( row._details ) { 8262 row._detailsShow = show; 8263 8264 if ( show ) { 8265 row._details.insertAfter( row.nTr ); 8266 } 8267 else { 8268 row._details.detach(); 8269 } 8270 8271 __details_events( ctx[0] ); 8272 } 8273 } 8274 }; 8275 8276 8277 var __details_events = function ( settings ) 8278 { 8279 var api = new _Api( settings ); 8280 var namespace = '.dt.DT_details'; 8281 var drawEvent = 'draw'+namespace; 8282 var colvisEvent = 'column-visibility'+namespace; 8283 var destroyEvent = 'destroy'+namespace; 8284 var data = settings.aoData; 8285 8286 api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent ); 8287 8288 if ( _pluck( data, '_details' ).length > 0 ) { 8289 // On each draw, insert the required elements into the document 8290 api.on( drawEvent, function ( e, ctx ) { 8291 if ( settings !== ctx ) { 8292 return; 8293 } 8294 8295 api.rows( {page:'current'} ).eq(0).each( function (idx) { 8296 // Internal data grab 8297 var row = data[ idx ]; 8298 8299 if ( row._detailsShow ) { 8300 row._details.insertAfter( row.nTr ); 8301 } 8302 } ); 8303 } ); 8304 8305 // Column visibility change - update the colspan 8306 api.on( colvisEvent, function ( e, ctx, idx, vis ) { 8307 if ( settings !== ctx ) { 8308 return; 8309 } 8310 8311 // Update the colspan for the details rows (note, only if it already has 8312 // a colspan) 8313 var row, visible = _fnVisbleColumns( ctx ); 8314 8315 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 8316 row = data[i]; 8317 8318 if ( row._details ) { 8319 row._details.children('td[colspan]').attr('colspan', visible ); 8320 } 8321 } 8322 } ); 8323 8324 // Table destroyed - nuke any child rows 8325 api.on( destroyEvent, function ( e, ctx ) { 8326 if ( settings !== ctx ) { 8327 return; 8328 } 8329 8330 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 8331 if ( data[i]._details ) { 8332 __details_remove( api, i ); 8333 } 8334 } 8335 } ); 8336 } 8337 }; 8338 8339 // Strings for the method names to help minification 8340 var _emp = ''; 8341 var _child_obj = _emp+'row().child'; 8342 var _child_mth = _child_obj+'()'; 8343 8344 // data can be: 8345 // tr 8346 // string 8347 // jQuery or array of any of the above 8348 _api_register( _child_mth, function ( data, klass ) { 8349 var ctx = this.context; 8350 8351 if ( data === undefined ) { 8352 // get 8353 return ctx.length && this.length ? 8354 ctx[0].aoData[ this[0] ]._details : 8355 undefined; 8356 } 8357 else if ( data === true ) { 8358 // show 8359 this.child.show(); 8360 } 8361 else if ( data === false ) { 8362 // remove 8363 __details_remove( this ); 8364 } 8365 else if ( ctx.length && this.length ) { 8366 // set 8367 __details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass ); 8368 } 8369 8370 return this; 8371 } ); 8372 8373 8374 _api_register( [ 8375 _child_obj+'.show()', 8376 _child_mth+'.show()' // only when `child()` was called with parameters (without 8377 ], function ( show ) { // it returns an object and this method is not executed) 8378 __details_display( this, true ); 8379 return this; 8380 } ); 8381 8382 8383 _api_register( [ 8384 _child_obj+'.hide()', 8385 _child_mth+'.hide()' // only when `child()` was called with parameters (without 8386 ], function () { // it returns an object and this method is not executed) 8387 __details_display( this, false ); 8388 return this; 8389 } ); 8390 8391 8392 _api_register( [ 8393 _child_obj+'.remove()', 8394 _child_mth+'.remove()' // only when `child()` was called with parameters (without 8395 ], function () { // it returns an object and this method is not executed) 8396 __details_remove( this ); 8397 return this; 8398 } ); 8399 8400 8401 _api_register( _child_obj+'.isShown()', function () { 8402 var ctx = this.context; 8403 8404 if ( ctx.length && this.length ) { 8405 // _detailsShown as false or undefined will fall through to return false 8406 return ctx[0].aoData[ this[0] ]._detailsShow || false; 8407 } 8408 return false; 8409 } ); 8410 8411 8412 8413 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 8414 * Columns 8415 * 8416 * {integer} - column index (>=0 count from left, <0 count from right) 8417 * "{integer}:visIdx" - visible column index (i.e. translate to column index) (>=0 count from left, <0 count from right) 8418 * "{integer}:visible" - alias for {integer}:visIdx (>=0 count from left, <0 count from right) 8419 * "{string}:name" - column name 8420 * "{string}" - jQuery selector on column header nodes 8421 * 8422 */ 8423 8424 // can be an array of these items, comma separated list, or an array of comma 8425 // separated lists 8426 8427 var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/; 8428 8429 8430 // r1 and r2 are redundant - but it means that the parameters match for the 8431 // iterator callback in columns().data() 8432 var __columnData = function ( settings, column, r1, r2, rows ) { 8433 var a = []; 8434 for ( var row=0, ien=rows.length ; row<ien ; row++ ) { 8435 a.push( _fnGetCellData( settings, rows[row], column ) ); 8436 } 8437 return a; 8438 }; 8439 8440 8441 var __column_selector = function ( settings, selector, opts ) 8442 { 8443 var 8444 columns = settings.aoColumns, 8445 names = _pluck( columns, 'sName' ), 8446 nodes = _pluck( columns, 'nTh' ); 8447 8448 var run = function ( s ) { 8449 var selInt = _intVal( s ); 8450 8451 // Selector - all 8452 if ( s === '' ) { 8453 return _range( columns.length ); 8454 } 8455 8456 // Selector - index 8457 if ( selInt !== null ) { 8458 return [ selInt >= 0 ? 8459 selInt : // Count from left 8460 columns.length + selInt // Count from right (+ because its a negative value) 8461 ]; 8462 } 8463 8464 // Selector = function 8465 if ( typeof s === 'function' ) { 8466 var rows = _selector_row_indexes( settings, opts ); 8467 8468 return $.map( columns, function (col, idx) { 8469 return s( 8470 idx, 8471 __columnData( settings, idx, 0, 0, rows ), 8472 nodes[ idx ] 8473 ) ? idx : null; 8474 } ); 8475 } 8476 8477 // jQuery or string selector 8478 var match = typeof s === 'string' ? 8479 s.match( __re_column_selector ) : 8480 ''; 8481 8482 if ( match ) { 8483 switch( match[2] ) { 8484 case 'visIdx': 8485 case 'visible': 8486 var idx = parseInt( match[1], 10 ); 8487 // Visible index given, convert to column index 8488 if ( idx < 0 ) { 8489 // Counting from the right 8490 var visColumns = $.map( columns, function (col,i) { 8491 return col.bVisible ? i : null; 8492 } ); 8493 return [ visColumns[ visColumns.length + idx ] ]; 8494 } 8495 // Counting from the left 8496 return [ _fnVisibleToColumnIndex( settings, idx ) ]; 8497 8498 case 'name': 8499 // match by name. `names` is column index complete and in order 8500 return $.map( names, function (name, i) { 8501 return name === match[1] ? i : null; 8502 } ); 8503 8504 default: 8505 return []; 8506 } 8507 } 8508 8509 // Cell in the table body 8510 if ( s.nodeName && s._DT_CellIndex ) { 8511 return [ s._DT_CellIndex.column ]; 8512 } 8513 8514 // jQuery selector on the TH elements for the columns 8515 var jqResult = $( nodes ) 8516 .filter( s ) 8517 .map( function () { 8518 return $.inArray( this, nodes ); // `nodes` is column index complete and in order 8519 } ) 8520 .toArray(); 8521 8522 if ( jqResult.length || ! s.nodeName ) { 8523 return jqResult; 8524 } 8525 8526 // Otherwise a node which might have a `dt-column` data attribute, or be 8527 // a child or such an element 8528 var host = $(s).closest('*[data-dt-column]'); 8529 return host.length ? 8530 [ host.data('dt-column') ] : 8531 []; 8532 }; 8533 8534 return _selector_run( 'column', selector, run, settings, opts ); 8535 }; 8536 8537 8538 var __setColumnVis = function ( settings, column, vis ) { 8539 var 8540 cols = settings.aoColumns, 8541 col = cols[ column ], 8542 data = settings.aoData, 8543 row, cells, i, ien, tr; 8544 8545 // Get 8546 if ( vis === undefined ) { 8547 return col.bVisible; 8548 } 8549 8550 // Set 8551 // No change 8552 if ( col.bVisible === vis ) { 8553 return; 8554 } 8555 8556 if ( vis ) { 8557 // Insert column 8558 // Need to decide if we should use appendChild or insertBefore 8559 var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 ); 8560 8561 for ( i=0, ien=data.length ; i<ien ; i++ ) { 8562 tr = data[i].nTr; 8563 cells = data[i].anCells; 8564 8565 if ( tr ) { 8566 // insertBefore can act like appendChild if 2nd arg is null 8567 tr.insertBefore( cells[ column ], cells[ insertBefore ] || null ); 8568 } 8569 } 8570 } 8571 else { 8572 // Remove column 8573 $( _pluck( settings.aoData, 'anCells', column ) ).detach(); 8574 } 8575 8576 // Common actions 8577 col.bVisible = vis; 8578 _fnDrawHead( settings, settings.aoHeader ); 8579 _fnDrawHead( settings, settings.aoFooter ); 8580 8581 // Update colspan for no records display. Child rows and extensions will use their own 8582 // listeners to do this - only need to update the empty table item here 8583 if ( ! settings.aiDisplay.length ) { 8584 $(settings.nTBody).find('td[colspan]').attr('colspan', _fnVisbleColumns(settings)); 8585 } 8586 8587 _fnSaveState( settings ); 8588 }; 8589 8590 8591 _api_register( 'columns()', function ( selector, opts ) { 8592 // argument shifting 8593 if ( selector === undefined ) { 8594 selector = ''; 8595 } 8596 else if ( $.isPlainObject( selector ) ) { 8597 opts = selector; 8598 selector = ''; 8599 } 8600 8601 opts = _selector_opts( opts ); 8602 8603 var inst = this.iterator( 'table', function ( settings ) { 8604 return __column_selector( settings, selector, opts ); 8605 }, 1 ); 8606 8607 // Want argument shifting here and in _row_selector? 8608 inst.selector.cols = selector; 8609 inst.selector.opts = opts; 8610 8611 return inst; 8612 } ); 8613 8614 _api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) { 8615 return this.iterator( 'column', function ( settings, column ) { 8616 return settings.aoColumns[column].nTh; 8617 }, 1 ); 8618 } ); 8619 8620 _api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) { 8621 return this.iterator( 'column', function ( settings, column ) { 8622 return settings.aoColumns[column].nTf; 8623 }, 1 ); 8624 } ); 8625 8626 _api_registerPlural( 'columns().data()', 'column().data()', function () { 8627 return this.iterator( 'column-rows', __columnData, 1 ); 8628 } ); 8629 8630 _api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () { 8631 return this.iterator( 'column', function ( settings, column ) { 8632 return settings.aoColumns[column].mData; 8633 }, 1 ); 8634 } ); 8635 8636 _api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) { 8637 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) { 8638 return _pluck_order( settings.aoData, rows, 8639 type === 'search' ? '_aFilterData' : '_aSortData', column 8640 ); 8641 }, 1 ); 8642 } ); 8643 8644 _api_registerPlural( 'columns().nodes()', 'column().nodes()', function () { 8645 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) { 8646 return _pluck_order( settings.aoData, rows, 'anCells', column ) ; 8647 }, 1 ); 8648 } ); 8649 8650 _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) { 8651 var ret = this.iterator( 'column', function ( settings, column ) { 8652 if ( vis === undefined ) { 8653 return settings.aoColumns[ column ].bVisible; 8654 } // else 8655 __setColumnVis( settings, column, vis ); 8656 } ); 8657 8658 // Group the column visibility changes 8659 if ( vis !== undefined ) { 8660 // Second loop once the first is done for events 8661 this.iterator( 'column', function ( settings, column ) { 8662 _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] ); 8663 } ); 8664 8665 if ( calc === undefined || calc ) { 8666 this.columns.adjust(); 8667 } 8668 } 8669 8670 return ret; 8671 } ); 8672 8673 _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) { 8674 return this.iterator( 'column', function ( settings, column ) { 8675 return type === 'visible' ? 8676 _fnColumnIndexToVisible( settings, column ) : 8677 column; 8678 }, 1 ); 8679 } ); 8680 8681 _api_register( 'columns.adjust()', function () { 8682 return this.iterator( 'table', function ( settings ) { 8683 _fnAdjustColumnSizing( settings ); 8684 }, 1 ); 8685 } ); 8686 8687 _api_register( 'column.index()', function ( type, idx ) { 8688 if ( this.context.length !== 0 ) { 8689 var ctx = this.context[0]; 8690 8691 if ( type === 'fromVisible' || type === 'toData' ) { 8692 return _fnVisibleToColumnIndex( ctx, idx ); 8693 } 8694 else if ( type === 'fromData' || type === 'toVisible' ) { 8695 return _fnColumnIndexToVisible( ctx, idx ); 8696 } 8697 } 8698 } ); 8699 8700 _api_register( 'column()', function ( selector, opts ) { 8701 return _selector_first( this.columns( selector, opts ) ); 8702 } ); 8703 8704 8705 8706 var __cell_selector = function ( settings, selector, opts ) 8707 { 8708 var data = settings.aoData; 8709 var rows = _selector_row_indexes( settings, opts ); 8710 var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) ); 8711 var allCells = $( [].concat.apply([], cells) ); 8712 var row; 8713 var columns = settings.aoColumns.length; 8714 var a, i, ien, j, o, host; 8715 8716 var run = function ( s ) { 8717 var fnSelector = typeof s === 'function'; 8718 8719 if ( s === null || s === undefined || fnSelector ) { 8720 // All cells and function selectors 8721 a = []; 8722 8723 for ( i=0, ien=rows.length ; i<ien ; i++ ) { 8724 row = rows[i]; 8725 8726 for ( j=0 ; j<columns ; j++ ) { 8727 o = { 8728 row: row, 8729 column: j 8730 }; 8731 8732 if ( fnSelector ) { 8733 // Selector - function 8734 host = data[ row ]; 8735 8736 if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) { 8737 a.push( o ); 8738 } 8739 } 8740 else { 8741 // Selector - all 8742 a.push( o ); 8743 } 8744 } 8745 } 8746 8747 return a; 8748 } 8749 8750 // Selector - index 8751 if ( $.isPlainObject( s ) ) { 8752 // Valid cell index and its in the array of selectable rows 8753 return s.column !== undefined && s.row !== undefined && $.inArray( s.row, rows ) !== -1 ? 8754 [s] : 8755 []; 8756 } 8757 8758 // Selector - jQuery filtered cells 8759 var jqResult = allCells 8760 .filter( s ) 8761 .map( function (i, el) { 8762 return { // use a new object, in case someone changes the values 8763 row: el._DT_CellIndex.row, 8764 column: el._DT_CellIndex.column 8765 }; 8766 } ) 8767 .toArray(); 8768 8769 if ( jqResult.length || ! s.nodeName ) { 8770 return jqResult; 8771 } 8772 8773 // Otherwise the selector is a node, and there is one last option - the 8774 // element might be a child of an element which has dt-row and dt-column 8775 // data attributes 8776 host = $(s).closest('*[data-dt-row]'); 8777 return host.length ? 8778 [ { 8779 row: host.data('dt-row'), 8780 column: host.data('dt-column') 8781 } ] : 8782 []; 8783 }; 8784 8785 return _selector_run( 'cell', selector, run, settings, opts ); 8786 }; 8787 8788 8789 8790 8791 _api_register( 'cells()', function ( rowSelector, columnSelector, opts ) { 8792 // Argument shifting 8793 if ( $.isPlainObject( rowSelector ) ) { 8794 // Indexes 8795 if ( rowSelector.row === undefined ) { 8796 // Selector options in first parameter 8797 opts = rowSelector; 8798 rowSelector = null; 8799 } 8800 else { 8801 // Cell index objects in first parameter 8802 opts = columnSelector; 8803 columnSelector = null; 8804 } 8805 } 8806 if ( $.isPlainObject( columnSelector ) ) { 8807 opts = columnSelector; 8808 columnSelector = null; 8809 } 8810 8811 // Cell selector 8812 if ( columnSelector === null || columnSelector === undefined ) { 8813 return this.iterator( 'table', function ( settings ) { 8814 return __cell_selector( settings, rowSelector, _selector_opts( opts ) ); 8815 } ); 8816 } 8817 8818 // Row + column selector 8819 var columns = this.columns( columnSelector ); 8820 var rows = this.rows( rowSelector ); 8821 var a, i, ien, j, jen; 8822 8823 this.iterator( 'table', function ( settings, idx ) { 8824 a = []; 8825 8826 for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) { 8827 for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) { 8828 a.push( { 8829 row: rows[idx][i], 8830 column: columns[idx][j] 8831 } ); 8832 } 8833 } 8834 }, 1 ); 8835 8836 // Now pass through the cell selector for options 8837 var cells = this.cells( a, opts ); 8838 8839 $.extend( cells.selector, { 8840 cols: columnSelector, 8841 rows: rowSelector, 8842 opts: opts 8843 } ); 8844 8845 return cells; 8846 } ); 8847 8848 8849 _api_registerPlural( 'cells().nodes()', 'cell().node()', function () { 8850 return this.iterator( 'cell', function ( settings, row, column ) { 8851 var data = settings.aoData[ row ]; 8852 8853 return data && data.anCells ? 8854 data.anCells[ column ] : 8855 undefined; 8856 }, 1 ); 8857 } ); 8858 8859 8860 _api_register( 'cells().data()', function () { 8861 return this.iterator( 'cell', function ( settings, row, column ) { 8862 return _fnGetCellData( settings, row, column ); 8863 }, 1 ); 8864 } ); 8865 8866 8867 _api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) { 8868 type = type === 'search' ? '_aFilterData' : '_aSortData'; 8869 8870 return this.iterator( 'cell', function ( settings, row, column ) { 8871 return settings.aoData[ row ][ type ][ column ]; 8872 }, 1 ); 8873 } ); 8874 8875 8876 _api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) { 8877 return this.iterator( 'cell', function ( settings, row, column ) { 8878 return _fnGetCellData( settings, row, column, type ); 8879 }, 1 ); 8880 } ); 8881 8882 8883 _api_registerPlural( 'cells().indexes()', 'cell().index()', function () { 8884 return this.iterator( 'cell', function ( settings, row, column ) { 8885 return { 8886 row: row, 8887 column: column, 8888 columnVisible: _fnColumnIndexToVisible( settings, column ) 8889 }; 8890 }, 1 ); 8891 } ); 8892 8893 8894 _api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) { 8895 return this.iterator( 'cell', function ( settings, row, column ) { 8896 _fnInvalidate( settings, row, src, column ); 8897 } ); 8898 } ); 8899 8900 8901 8902 _api_register( 'cell()', function ( rowSelector, columnSelector, opts ) { 8903 return _selector_first( this.cells( rowSelector, columnSelector, opts ) ); 8904 } ); 8905 8906 8907 _api_register( 'cell().data()', function ( data ) { 8908 var ctx = this.context; 8909 var cell = this[0]; 8910 8911 if ( data === undefined ) { 8912 // Get 8913 return ctx.length && cell.length ? 8914 _fnGetCellData( ctx[0], cell[0].row, cell[0].column ) : 8915 undefined; 8916 } 8917 8918 // Set 8919 _fnSetCellData( ctx[0], cell[0].row, cell[0].column, data ); 8920 _fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column ); 8921 8922 return this; 8923 } ); 8924 8925 8926 8927 /** 8928 * Get current ordering (sorting) that has been applied to the table. 8929 * 8930 * @returns {array} 2D array containing the sorting information for the first 8931 * table in the current context. Each element in the parent array represents 8932 * a column being sorted upon (i.e. multi-sorting with two columns would have 8933 * 2 inner arrays). The inner arrays may have 2 or 3 elements. The first is 8934 * the column index that the sorting condition applies to, the second is the 8935 * direction of the sort (`desc` or `asc`) and, optionally, the third is the 8936 * index of the sorting order from the `column.sorting` initialisation array. 8937 *//** 8938 * Set the ordering for the table. 8939 * 8940 * @param {integer} order Column index to sort upon. 8941 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`) 8942 * @returns {DataTables.Api} this 8943 *//** 8944 * Set the ordering for the table. 8945 * 8946 * @param {array} order 1D array of sorting information to be applied. 8947 * @param {array} [...] Optional additional sorting conditions 8948 * @returns {DataTables.Api} this 8949 *//** 8950 * Set the ordering for the table. 8951 * 8952 * @param {array} order 2D array of sorting information to be applied. 8953 * @returns {DataTables.Api} this 8954 */ 8955 _api_register( 'order()', function ( order, dir ) { 8956 var ctx = this.context; 8957 8958 if ( order === undefined ) { 8959 // get 8960 return ctx.length !== 0 ? 8961 ctx[0].aaSorting : 8962 undefined; 8963 } 8964 8965 // set 8966 if ( typeof order === 'number' ) { 8967 // Simple column / direction passed in 8968 order = [ [ order, dir ] ]; 8969 } 8970 else if ( order.length && ! $.isArray( order[0] ) ) { 8971 // Arguments passed in (list of 1D arrays) 8972 order = Array.prototype.slice.call( arguments ); 8973 } 8974 // otherwise a 2D array was passed in 8975 8976 return this.iterator( 'table', function ( settings ) { 8977 settings.aaSorting = order.slice(); 8978 } ); 8979 } ); 8980 8981 8982 /** 8983 * Attach a sort listener to an element for a given column 8984 * 8985 * @param {node|jQuery|string} node Identifier for the element(s) to attach the 8986 * listener to. This can take the form of a single DOM node, a jQuery 8987 * collection of nodes or a jQuery selector which will identify the node(s). 8988 * @param {integer} column the column that a click on this node will sort on 8989 * @param {function} [callback] callback function when sort is run 8990 * @returns {DataTables.Api} this 8991 */ 8992 _api_register( 'order.listener()', function ( node, column, callback ) { 8993 return this.iterator( 'table', function ( settings ) { 8994 _fnSortAttachListener( settings, node, column, callback ); 8995 } ); 8996 } ); 8997 8998 8999 _api_register( 'order.fixed()', function ( set ) { 9000 if ( ! set ) { 9001 var ctx = this.context; 9002 var fixed = ctx.length ? 9003 ctx[0].aaSortingFixed : 9004 undefined; 9005 9006 return $.isArray( fixed ) ? 9007 { pre: fixed } : 9008 fixed; 9009 } 9010 9011 return this.iterator( 'table', function ( settings ) { 9012 settings.aaSortingFixed = $.extend( true, {}, set ); 9013 } ); 9014 } ); 9015 9016 9017 // Order by the selected column(s) 9018 _api_register( [ 9019 'columns().order()', 9020 'column().order()' 9021 ], function ( dir ) { 9022 var that = this; 9023 9024 return this.iterator( 'table', function ( settings, i ) { 9025 var sort = []; 9026 9027 $.each( that[i], function (j, col) { 9028 sort.push( [ col, dir ] ); 9029 } ); 9030 9031 settings.aaSorting = sort; 9032 } ); 9033 } ); 9034 9035 9036 9037 _api_register( 'search()', function ( input, regex, smart, caseInsen ) { 9038 var ctx = this.context; 9039 9040 if ( input === undefined ) { 9041 // get 9042 return ctx.length !== 0 ? 9043 ctx[0].oPreviousSearch.sSearch : 9044 undefined; 9045 } 9046 9047 // set 9048 return this.iterator( 'table', function ( settings ) { 9049 if ( ! settings.oFeatures.bFilter ) { 9050 return; 9051 } 9052 9053 _fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, { 9054 "sSearch": input+"", 9055 "bRegex": regex === null ? false : regex, 9056 "bSmart": smart === null ? true : smart, 9057 "bCaseInsensitive": caseInsen === null ? true : caseInsen 9058 } ), 1 ); 9059 } ); 9060 } ); 9061 9062 9063 _api_registerPlural( 9064 'columns().search()', 9065 'column().search()', 9066 function ( input, regex, smart, caseInsen ) { 9067 return this.iterator( 'column', function ( settings, column ) { 9068 var preSearch = settings.aoPreSearchCols; 9069 9070 if ( input === undefined ) { 9071 // get 9072 return preSearch[ column ].sSearch; 9073 } 9074 9075 // set 9076 if ( ! settings.oFeatures.bFilter ) { 9077 return; 9078 } 9079 9080 $.extend( preSearch[ column ], { 9081 "sSearch": input+"", 9082 "bRegex": regex === null ? false : regex, 9083 "bSmart": smart === null ? true : smart, 9084 "bCaseInsensitive": caseInsen === null ? true : caseInsen 9085 } ); 9086 9087 _fnFilterComplete( settings, settings.oPreviousSearch, 1 ); 9088 } ); 9089 } 9090 ); 9091 9092 /* 9093 * State API methods 9094 */ 9095 9096 _api_register( 'state()', function () { 9097 return this.context.length ? 9098 this.context[0].oSavedState : 9099 null; 9100 } ); 9101 9102 9103 _api_register( 'state.clear()', function () { 9104 return this.iterator( 'table', function ( settings ) { 9105 // Save an empty object 9106 settings.fnStateSaveCallback.call( settings.oInstance, settings, {} ); 9107 } ); 9108 } ); 9109 9110 9111 _api_register( 'state.loaded()', function () { 9112 return this.context.length ? 9113 this.context[0].oLoadedState : 9114 null; 9115 } ); 9116 9117 9118 _api_register( 'state.save()', function () { 9119 return this.iterator( 'table', function ( settings ) { 9120 _fnSaveState( settings ); 9121 } ); 9122 } ); 9123 9124 9125 9126 /** 9127 * Provide a common method for plug-ins to check the version of DataTables being 9128 * used, in order to ensure compatibility. 9129 * 9130 * @param {string} version Version string to check for, in the format "X.Y.Z". 9131 * Note that the formats "X" and "X.Y" are also acceptable. 9132 * @returns {boolean} true if this version of DataTables is greater or equal to 9133 * the required version, or false if this version of DataTales is not 9134 * suitable 9135 * @static 9136 * @dtopt API-Static 9137 * 9138 * @example 9139 * alert( $.fn.dataTable.versionCheck( '1.9.0' ) ); 9140 */ 9141 DataTable.versionCheck = DataTable.fnVersionCheck = function( version ) 9142 { 9143 var aThis = DataTable.version.split('.'); 9144 var aThat = version.split('.'); 9145 var iThis, iThat; 9146 9147 for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) { 9148 iThis = parseInt( aThis[i], 10 ) || 0; 9149 iThat = parseInt( aThat[i], 10 ) || 0; 9150 9151 // Parts are the same, keep comparing 9152 if (iThis === iThat) { 9153 continue; 9154 } 9155 9156 // Parts are different, return immediately 9157 return iThis > iThat; 9158 } 9159 9160 return true; 9161 }; 9162 9163 9164 /** 9165 * Check if a `<table>` node is a DataTable table already or not. 9166 * 9167 * @param {node|jquery|string} table Table node, jQuery object or jQuery 9168 * selector for the table to test. Note that if more than more than one 9169 * table is passed on, only the first will be checked 9170 * @returns {boolean} true the table given is a DataTable, or false otherwise 9171 * @static 9172 * @dtopt API-Static 9173 * 9174 * @example 9175 * if ( ! $.fn.DataTable.isDataTable( '#example' ) ) { 9176 * $('#example').dataTable(); 9177 * } 9178 */ 9179 DataTable.isDataTable = DataTable.fnIsDataTable = function ( table ) 9180 { 9181 var t = $(table).get(0); 9182 var is = false; 9183 9184 if ( table instanceof DataTable.Api ) { 9185 return true; 9186 } 9187 9188 $.each( DataTable.settings, function (i, o) { 9189 var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null; 9190 var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null; 9191 9192 if ( o.nTable === t || head === t || foot === t ) { 9193 is = true; 9194 } 9195 } ); 9196 9197 return is; 9198 }; 9199 9200 9201 /** 9202 * Get all DataTable tables that have been initialised - optionally you can 9203 * select to get only currently visible tables. 9204 * 9205 * @param {boolean} [visible=false] Flag to indicate if you want all (default) 9206 * or visible tables only. 9207 * @returns {array} Array of `table` nodes (not DataTable instances) which are 9208 * DataTables 9209 * @static 9210 * @dtopt API-Static 9211 * 9212 * @example 9213 * $.each( $.fn.dataTable.tables(true), function () { 9214 * $(table).DataTable().columns.adjust(); 9215 * } ); 9216 */ 9217 DataTable.tables = DataTable.fnTables = function ( visible ) 9218 { 9219 var api = false; 9220 9221 if ( $.isPlainObject( visible ) ) { 9222 api = visible.api; 9223 visible = visible.visible; 9224 } 9225 9226 var a = $.map( DataTable.settings, function (o) { 9227 if ( !visible || (visible && $(o.nTable).is(':visible')) ) { 9228 return o.nTable; 9229 } 9230 } ); 9231 9232 return api ? 9233 new _Api( a ) : 9234 a; 9235 }; 9236 9237 9238 /** 9239 * Convert from camel case parameters to Hungarian notation. This is made public 9240 * for the extensions to provide the same ability as DataTables core to accept 9241 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase 9242 * parameters. 9243 * 9244 * @param {object} src The model object which holds all parameters that can be 9245 * mapped. 9246 * @param {object} user The object to convert from camel case to Hungarian. 9247 * @param {boolean} force When set to `true`, properties which already have a 9248 * Hungarian value in the `user` object will be overwritten. Otherwise they 9249 * won't be. 9250 */ 9251 DataTable.camelToHungarian = _fnCamelToHungarian; 9252 9253 9254 9255 /** 9256 * 9257 */ 9258 _api_register( '$()', function ( selector, opts ) { 9259 var 9260 rows = this.rows( opts ).nodes(), // Get all rows 9261 jqRows = $(rows); 9262 9263 return $( [].concat( 9264 jqRows.filter( selector ).toArray(), 9265 jqRows.find( selector ).toArray() 9266 ) ); 9267 } ); 9268 9269 9270 // jQuery functions to operate on the tables 9271 $.each( [ 'on', 'one', 'off' ], function (i, key) { 9272 _api_register( key+'()', function ( /* event, handler */ ) { 9273 var args = Array.prototype.slice.call(arguments); 9274 9275 // Add the `dt` namespace automatically if it isn't already present 9276 args[0] = $.map( args[0].split( /\s/ ), function ( e ) { 9277 return ! e.match(/\.dt\b/) ? 9278 e+'.dt' : 9279 e; 9280 } ).join( ' ' ); 9281 9282 var inst = $( this.tables().nodes() ); 9283 inst[key].apply( inst, args ); 9284 return this; 9285 } ); 9286 } ); 9287 9288 9289 _api_register( 'clear()', function () { 9290 return this.iterator( 'table', function ( settings ) { 9291 _fnClearTable( settings ); 9292 } ); 9293 } ); 9294 9295 9296 _api_register( 'settings()', function () { 9297 return new _Api( this.context, this.context ); 9298 } ); 9299 9300 9301 _api_register( 'init()', function () { 9302 var ctx = this.context; 9303 return ctx.length ? ctx[0].oInit : null; 9304 } ); 9305 9306 9307 _api_register( 'data()', function () { 9308 return this.iterator( 'table', function ( settings ) { 9309 return _pluck( settings.aoData, '_aData' ); 9310 } ).flatten(); 9311 } ); 9312 9313 9314 _api_register( 'destroy()', function ( remove ) { 9315 remove = remove || false; 9316 9317 return this.iterator( 'table', function ( settings ) { 9318 var orig = settings.nTableWrapper.parentNode; 9319 var classes = settings.oClasses; 9320 var table = settings.nTable; 9321 var tbody = settings.nTBody; 9322 var thead = settings.nTHead; 9323 var tfoot = settings.nTFoot; 9324 var jqTable = $(table); 9325 var jqTbody = $(tbody); 9326 var jqWrapper = $(settings.nTableWrapper); 9327 var rows = $.map( settings.aoData, function (r) { return r.nTr; } ); 9328 var i, ien; 9329 9330 // Flag to note that the table is currently being destroyed - no action 9331 // should be taken 9332 settings.bDestroying = true; 9333 9334 // Fire off the destroy callbacks for plug-ins etc 9335 _fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] ); 9336 9337 // If not being removed from the document, make all columns visible 9338 if ( ! remove ) { 9339 new _Api( settings ).columns().visible( true ); 9340 } 9341 9342 // Blitz all `DT` namespaced events (these are internal events, the 9343 // lowercase, `dt` events are user subscribed and they are responsible 9344 // for removing them 9345 jqWrapper.off('.DT').find(':not(tbody *)').off('.DT'); 9346 $(window).off('.DT-'+settings.sInstance); 9347 9348 // When scrolling we had to break the table up - restore it 9349 if ( table != thead.parentNode ) { 9350 jqTable.children('thead').detach(); 9351 jqTable.append( thead ); 9352 } 9353 9354 if ( tfoot && table != tfoot.parentNode ) { 9355 jqTable.children('tfoot').detach(); 9356 jqTable.append( tfoot ); 9357 } 9358 9359 settings.aaSorting = []; 9360 settings.aaSortingFixed = []; 9361 _fnSortingClasses( settings ); 9362 9363 $( rows ).removeClass( settings.asStripeClasses.join(' ') ); 9364 9365 $('th, td', thead).removeClass( classes.sSortable+' '+ 9366 classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone 9367 ); 9368 9369 // Add the TR elements back into the table in their original order 9370 jqTbody.children().detach(); 9371 jqTbody.append( rows ); 9372 9373 // Remove the DataTables generated nodes, events and classes 9374 var removedMethod = remove ? 'remove' : 'detach'; 9375 jqTable[ removedMethod ](); 9376 jqWrapper[ removedMethod ](); 9377 9378 // If we need to reattach the table to the document 9379 if ( ! remove && orig ) { 9380 // insertBefore acts like appendChild if !arg[1] 9381 orig.insertBefore( table, settings.nTableReinsertBefore ); 9382 9383 // Restore the width of the original table - was read from the style property, 9384 // so we can restore directly to that 9385 jqTable 9386 .css( 'width', settings.sDestroyWidth ) 9387 .removeClass( classes.sTable ); 9388 9389 // If the were originally stripe classes - then we add them back here. 9390 // Note this is not fool proof (for example if not all rows had stripe 9391 // classes - but it's a good effort without getting carried away 9392 ien = settings.asDestroyStripes.length; 9393 9394 if ( ien ) { 9395 jqTbody.children().each( function (i) { 9396 $(this).addClass( settings.asDestroyStripes[i % ien] ); 9397 } ); 9398 } 9399 } 9400 9401 /* Remove the settings object from the settings array */ 9402 var idx = $.inArray( settings, DataTable.settings ); 9403 if ( idx !== -1 ) { 9404 DataTable.settings.splice( idx, 1 ); 9405 } 9406 } ); 9407 } ); 9408 9409 9410 // Add the `every()` method for rows, columns and cells in a compact form 9411 $.each( [ 'column', 'row', 'cell' ], function ( i, type ) { 9412 _api_register( type+'s().every()', function ( fn ) { 9413 var opts = this.selector.opts; 9414 var api = this; 9415 9416 return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) { 9417 // Rows and columns: 9418 // arg1 - index 9419 // arg2 - table counter 9420 // arg3 - loop counter 9421 // arg4 - undefined 9422 // Cells: 9423 // arg1 - row index 9424 // arg2 - column index 9425 // arg3 - table counter 9426 // arg4 - loop counter 9427 fn.call( 9428 api[ type ]( 9429 arg1, 9430 type==='cell' ? arg2 : opts, 9431 type==='cell' ? opts : undefined 9432 ), 9433 arg1, arg2, arg3, arg4 9434 ); 9435 } ); 9436 } ); 9437 } ); 9438 9439 9440 // i18n method for extensions to be able to use the language object from the 9441 // DataTable 9442 _api_register( 'i18n()', function ( token, def, plural ) { 9443 var ctx = this.context[0]; 9444 var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage ); 9445 9446 if ( resolved === undefined ) { 9447 resolved = def; 9448 } 9449 9450 if ( plural !== undefined && $.isPlainObject( resolved ) ) { 9451 resolved = resolved[ plural ] !== undefined ? 9452 resolved[ plural ] : 9453 resolved._; 9454 } 9455 9456 return resolved.replace( '%d', plural ); // nb: plural might be undefined, 9457 } ); 9458 /** 9459 * Version string for plug-ins to check compatibility. Allowed format is 9460 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used 9461 * only for non-release builds. See http://semver.org/ for more information. 9462 * @member 9463 * @type string 9464 * @default Version number 9465 */ 9466 DataTable.version = "1.10.19"; 9467 9468 /** 9469 * Private data store, containing all of the settings objects that are 9470 * created for the tables on a given page. 9471 * 9472 * Note that the `DataTable.settings` object is aliased to 9473 * `jQuery.fn.dataTableExt` through which it may be accessed and 9474 * manipulated, or `jQuery.fn.dataTable.settings`. 9475 * @member 9476 * @type array 9477 * @default [] 9478 * @private 9479 */ 9480 DataTable.settings = []; 9481 9482 /** 9483 * Object models container, for the various models that DataTables has 9484 * available to it. These models define the objects that are used to hold 9485 * the active state and configuration of the table. 9486 * @namespace 9487 */ 9488 DataTable.models = {}; 9489 9490 9491 9492 /** 9493 * Template object for the way in which DataTables holds information about 9494 * search information for the global filter and individual column filters. 9495 * @namespace 9496 */ 9497 DataTable.models.oSearch = { 9498 /** 9499 * Flag to indicate if the filtering should be case insensitive or not 9500 * @type boolean 9501 * @default true 9502 */ 9503 "bCaseInsensitive": true, 9504 9505 /** 9506 * Applied search term 9507 * @type string 9508 * @default <i>Empty string</i> 9509 */ 9510 "sSearch": "", 9511 9512 /** 9513 * Flag to indicate if the search term should be interpreted as a 9514 * regular expression (true) or not (false) and therefore and special 9515 * regex characters escaped. 9516 * @type boolean 9517 * @default false 9518 */ 9519 "bRegex": false, 9520 9521 /** 9522 * Flag to indicate if DataTables is to use its smart filtering or not. 9523 * @type boolean 9524 * @default true 9525 */ 9526 "bSmart": tru
vendor: 11,217 bytes, lines 9526-9884
9526e 9527 }; 9528 9529 9530 9531 9532 /** 9533 * Template object for the way in which DataTables holds information about 9534 * each individual row. This is the object format used for the settings 9535 * aoData array. 9536 * @namespace 9537 */ 9538 DataTable.models.oRow = { 9539 /** 9540 * TR element for the row 9541 * @type node 9542 * @default null 9543 */ 9544 "nTr": null, 9545 9546 /** 9547 * Array of TD elements for each row. This is null until the row has been 9548 * created. 9549 * @type array nodes 9550 * @default [] 9551 */ 9552 "anCells": null, 9553 9554 /** 9555 * Data object from the original data source for the row. This is either 9556 * an array if using the traditional form of DataTables, or an object if 9557 * using mData options. The exact type will depend on the passed in 9558 * data from the data source, or will be an array if using DOM a data 9559 * source. 9560 * @type array|object 9561 * @default [] 9562 */ 9563 "_aData": [], 9564 9565 /** 9566 * Sorting data cache - this array is ostensibly the same length as the 9567 * number of columns (although each index is generated only as it is 9568 * needed), and holds the data that is used for sorting each column in the 9569 * row. We do this cache generation at the start of the sort in order that 9570 * the formatting of the sort data need be done only once for each cell 9571 * per sort. This array should not be read from or written to by anything 9572 * other than the master sorting methods. 9573 * @type array 9574 * @default null 9575 * @private 9576 */ 9577 "_aSortData": null, 9578 9579 /** 9580 * Per cell filtering data cache. As per the sort data cache, used to 9581 * increase the performance of the filtering in DataTables 9582 * @type array 9583 * @default null 9584 * @private 9585 */ 9586 "_aFilterData": null, 9587 9588 /** 9589 * Filtering data cache. This is the same as the cell filtering cache, but 9590 * in this case a string rather than an array. This is easily computed with 9591 * a join on `_aFilterData`, but is provided as a cache so the join isn't 9592 * needed on every search (memory traded for performance) 9593 * @type array 9594 * @default null 9595 * @private 9596 */ 9597 "_sFilterRow": null, 9598 9599 /** 9600 * Cache of the class name that DataTables has applied to the row, so we 9601 * can quickly look at this variable rather than needing to do a DOM check 9602 * on className for the nTr property. 9603 * @type string 9604 * @default <i>Empty string</i> 9605 * @private 9606 */ 9607 "_sRowStripe": "", 9608 9609 /** 9610 * Denote if the original data source was from the DOM, or the data source 9611 * object. This is used for invalidating data, so DataTables can 9612 * automatically read data from the original source, unless uninstructed 9613 * otherwise. 9614 * @type string 9615 * @default null 9616 * @private 9617 */ 9618 "src": null, 9619 9620 /** 9621 * Index in the aoData array. This saves an indexOf lookup when we have the 9622 * object, but want to know the index 9623 * @type integer 9624 * @default -1 9625 * @private 9626 */ 9627 "idx": -1 9628 }; 9629 9630 9631 /** 9632 * Template object for the column information object in DataTables. This object 9633 * is held in the settings aoColumns array and contains all the information that 9634 * DataTables needs about each individual column. 9635 * 9636 * Note that this object is related to {@link DataTable.defaults.column} 9637 * but this one is the internal data store for DataTables's cache of columns. 9638 * It should NOT be manipulated outside of DataTables. Any configuration should 9639 * be done through the initialisation options. 9640 * @namespace 9641 */ 9642 DataTable.models.oColumn = { 9643 /** 9644 * Column index. This could be worked out on-the-fly with $.inArray, but it 9645 * is faster to just hold it as a variable 9646 * @type integer 9647 * @default null 9648 */ 9649 "idx": null, 9650 9651 /** 9652 * A list of the columns that sorting should occur on when this column 9653 * is sorted. That this property is an array allows multi-column sorting 9654 * to be defined for a column (for example first name / last name columns 9655 * would benefit from this). The values are integers pointing to the 9656 * columns to be sorted on (typically it will be a single integer pointing 9657 * at itself, but that doesn't need to be the case). 9658 * @type array 9659 */ 9660 "aDataSort": null, 9661 9662 /** 9663 * Define the sorting directions that are applied to the column, in sequence 9664 * as the column is repeatedly sorted upon - i.e. the first value is used 9665 * as the sorting direction when the column if first sorted (clicked on). 9666 * Sort it again (click again) and it will move on to the next index. 9667 * Repeat until loop. 9668 * @type array 9669 */ 9670 "asSorting": null, 9671 9672 /** 9673 * Flag to indicate if the column is searchable, and thus should be included 9674 * in the filtering or not. 9675 * @type boolean 9676 */ 9677 "bSearchable": null, 9678 9679 /** 9680 * Flag to indicate if the column is sortable or not. 9681 * @type boolean 9682 */ 9683 "bSortable": null, 9684 9685 /** 9686 * Flag to indicate if the column is currently visible in the table or not 9687 * @type boolean 9688 */ 9689 "bVisible": null, 9690 9691 /** 9692 * Store for manual type assignment using the `column.type` option. This 9693 * is held in store so we can manipulate the column's `sType` property. 9694 * @type string 9695 * @default null 9696 * @private 9697 */ 9698 "_sManualType": null, 9699 9700 /** 9701 * Flag to indicate if HTML5 data attributes should be used as the data 9702 * source for filtering or sorting. True is either are. 9703 * @type boolean 9704 * @default false 9705 * @private 9706 */ 9707 "_bAttrSrc": false, 9708 9709 /** 9710 * Developer definable function that is called whenever a cell is created (Ajax source, 9711 * etc) or processed for input (DOM source). This can be used as a compliment to mRender 9712 * allowing you to modify the DOM element (add background colour for example) when the 9713 * element is available. 9714 * @type function 9715 * @param {element} nTd The TD node that has been created 9716 * @param {*} sData The Data for the cell 9717 * @param {array|object} oData The data for the whole row 9718 * @param {int} iRow The row index for the aoData data store 9719 * @default null 9720 */ 9721 "fnCreatedCell": null, 9722 9723 /** 9724 * Function to get data from a cell in a column. You should <b>never</b> 9725 * access data directly through _aData internally in DataTables - always use 9726 * the method attached to this property. It allows mData to function as 9727 * required. This function is automatically assigned by the column 9728 * initialisation method 9729 * @type function 9730 * @param {array|object} oData The data array/object for the array 9731 * (i.e. aoData[]._aData) 9732 * @param {string} sSpecific The specific data type you want to get - 9733 * 'display', 'type' 'filter' 'sort' 9734 * @returns {*} The data for the cell from the given row's data 9735 * @default null 9736 */ 9737 "fnGetData": null, 9738 9739 /** 9740 * Function to set data for a cell in the column. You should <b>never</b> 9741 * set the data directly to _aData internally in DataTables - always use 9742 * this method. It allows mData to function as required. This function 9743 * is automatically assigned by the column initialisation method 9744 * @type function 9745 * @param {array|object} oData The data array/object for the array 9746 * (i.e. aoData[]._aData) 9747 * @param {*} sValue Value to set 9748 * @default null 9749 */ 9750 "fnSetData": null, 9751 9752 /** 9753 * Property to read the value for the cells in the column from the data 9754 * source array / object. If null, then the default content is used, if a 9755 * function is given then the return from the function is used. 9756 * @type function|int|string|null 9757 * @default null 9758 */ 9759 "mData": null, 9760 9761 /** 9762 * Partner property to mData which is used (only when defined) to get 9763 * the data - i.e. it is basically the same as mData, but without the 9764 * 'set' option, and also the data fed to it is the result from mData. 9765 * This is the rendering method to match the data method of mData. 9766 * @type function|int|string|null 9767 * @default null 9768 */ 9769 "mRender": null, 9770 9771 /** 9772 * Unique header TH/TD element for this column - this is what the sorting 9773 * listener is attached to (if sorting is enabled.) 9774 * @type node 9775 * @default null 9776 */ 9777 "nTh": null, 9778 9779 /** 9780 * Unique footer TH/TD element for this column (if there is one). Not used 9781 * in DataTables as such, but can be used for plug-ins to reference the 9782 * footer for each column. 9783 * @type node 9784 * @default null 9785 */ 9786 "nTf": null, 9787 9788 /** 9789 * The class to apply to all TD elements in the table's TBODY for the column 9790 * @type string 9791 * @default null 9792 */ 9793 "sClass": null, 9794 9795 /** 9796 * When DataTables calculates the column widths to assign to each column, 9797 * it finds the longest string in each column and then constructs a 9798 * temporary table and reads the widths from that. The problem with this 9799 * is that "mmm" is much wider then "iiii", but the latter is a longer 9800 * string - thus the calculation can go wrong (doing it properly and putting 9801 * it into an DOM object and measuring that is horribly(!) slow). Thus as 9802 * a "work around" we provide this option. It will append its value to the 9803 * text that is found to be the longest string for the column - i.e. padding. 9804 * @type string 9805 */ 9806 "sContentPadding": null, 9807 9808 /** 9809 * Allows a default value to be given for a column's data, and will be used 9810 * whenever a null data source is encountered (this can be because mData 9811 * is set to null, or because the data source itself is null). 9812 * @type string 9813 * @default null 9814 */ 9815 "sDefaultContent": null, 9816 9817 /** 9818 * Name for the column, allowing reference to the column by name as well as 9819 * by index (needs a lookup to work by name). 9820 * @type string 9821 */ 9822 "sName": null, 9823 9824 /** 9825 * Custom sorting data type - defines which of the available plug-ins in 9826 * afnSortData the custom sorting will use - if any is defined. 9827 * @type string 9828 * @default std 9829 */ 9830 "sSortDataType": 'std', 9831 9832 /** 9833 * Class to be applied to the header element when sorting on this column 9834 * @type string 9835 * @default null 9836 */ 9837 "sSortingClass": null, 9838 9839 /** 9840 * Class to be applied to the header element when sorting on this column - 9841 * when jQuery UI theming is used. 9842 * @type string 9843 * @default null 9844 */ 9845 "sSortingClassJUI": null, 9846 9847 /** 9848 * Title of the column - what is seen in the TH element (nTh). 9849 * @type string 9850 */ 9851 "sTitle": null, 9852 9853 /** 9854 * Column sorting and filtering type 9855 * @type string 9856 * @default null 9857 */ 9858 "sType": null, 9859 9860 /** 9861 * Width of the column 9862 * @type string 9863 * @default null 9864 */ 9865 "sWidth": null, 9866 9867 /** 9868 * Width of the column when it was first "encountered" 9869 * @type string 9870 * @default null 9871 */ 9872 "sWidthOrig": null 9873 }; 9874 9875 9876 /* 9877 * Developer note: The properties of the object below are given in Hungarian 9878 * notation, that was used as the interface for DataTables prior to v1.10, however 9879 * from v1.10 onwards the primary interface is camel case. In order to avoid 9880 * breaking backwards compatibility utterly with this change, the Hungarian 9881 * version is still, internally the primary interface, but is is not documented 9882 * - hence the @name tags in each doc comment. This allows a Javascript function 9883 * to create a map from Hungarian notation to camel case (going the other direction 9884 * would require each property to be listed, which would a
9884t around 3K to the size 9885 * of DataTables, while this method is about a 0.5K hit
vendor: 57,087 bytes, lines 9885-11661
9885. 9886 * 9887 * Ultimately this does pave the way for Hungarian notation to be dropped 9888 * completely, but that is a massive amount of work and will break current 9889 * installs (therefore is on-hold until v2). 9890 */ 9891 9892 /** 9893 * Initialisation options that can be given to DataTables at initialisation 9894 * time. 9895 * @namespace 9896 */ 9897 DataTable.defaults = { 9898 /** 9899 * An array of data to use for the table, passed in at initialisation which 9900 * will be used in preference to any data which is already in the DOM. This is 9901 * particularly useful for constructing tables purely in Javascript, for 9902 * example with a custom Ajax call. 9903 * @type array 9904 * @default null 9905 * 9906 * @dtopt Option 9907 * @name DataTable.defaults.data 9908 * 9909 * @example 9910 * // Using a 2D array data source 9911 * $(document).ready( function () { 9912 * $('#example').dataTable( { 9913 * "data": [ 9914 * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'], 9915 * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'], 9916 * ], 9917 * "columns": [ 9918 * { "title": "Engine" }, 9919 * { "title": "Browser" }, 9920 * { "title": "Platform" }, 9921 * { "title": "Version" }, 9922 * { "title": "Grade" } 9923 * ] 9924 * } ); 9925 * } ); 9926 * 9927 * @example 9928 * // Using an array of objects as a data source (`data`) 9929 * $(document).ready( function () { 9930 * $('#example').dataTable( { 9931 * "data": [ 9932 * { 9933 * "engine": "Trident", 9934 * "browser": "Internet Explorer 4.0", 9935 * "platform": "Win 95+", 9936 * "version": 4, 9937 * "grade": "X" 9938 * }, 9939 * { 9940 * "engine": "Trident", 9941 * "browser": "Internet Explorer 5.0", 9942 * "platform": "Win 95+", 9943 * "version": 5, 9944 * "grade": "C" 9945 * } 9946 * ], 9947 * "columns": [ 9948 * { "title": "Engine", "data": "engine" }, 9949 * { "title": "Browser", "data": "browser" }, 9950 * { "title": "Platform", "data": "platform" }, 9951 * { "title": "Version", "data": "version" }, 9952 * { "title": "Grade", "data": "grade" } 9953 * ] 9954 * } ); 9955 * } ); 9956 */ 9957 "aaData": null, 9958 9959 9960 /** 9961 * If ordering is enabled, then DataTables will perform a first pass sort on 9962 * initialisation. You can define which column(s) the sort is performed 9963 * upon, and the sorting direction, with this variable. The `sorting` array 9964 * should contain an array for each column to be sorted initially containing 9965 * the column's index and a direction string ('asc' or 'desc'). 9966 * @type array 9967 * @default [[0,'asc']] 9968 * 9969 * @dtopt Option 9970 * @name DataTable.defaults.order 9971 * 9972 * @example 9973 * // Sort by 3rd column first, and then 4th column 9974 * $(document).ready( function() { 9975 * $('#example').dataTable( { 9976 * "order": [[2,'asc'], [3,'desc']] 9977 * } ); 9978 * } ); 9979 * 9980 * // No initial sorting 9981 * $(document).ready( function() { 9982 * $('#example').dataTable( { 9983 * "order": [] 9984 * } ); 9985 * } ); 9986 */ 9987 "aaSorting": [[0,'asc']], 9988 9989 9990 /** 9991 * This parameter is basically identical to the `sorting` parameter, but 9992 * cannot be overridden by user interaction with the table. What this means 9993 * is that you could have a column (visible or hidden) which the sorting 9994 * will always be forced on first - any sorting after that (from the user) 9995 * will then be performed as required. This can be useful for grouping rows 9996 * together. 9997 * @type array 9998 * @default null 9999 * 10000 * @dtopt Option 10001 * @name DataTable.defaults.orderFixed 10002 * 10003 * @example 10004 * $(document).ready( function() { 10005 * $('#example').dataTable( { 10006 * "orderFixed": [[0,'asc']] 10007 * } ); 10008 * } ) 10009 */ 10010 "aaSortingFixed": [], 10011 10012 10013 /** 10014 * DataTables can be instructed to load data to display in the table from a 10015 * Ajax source. This option defines how that Ajax call is made and where to. 10016 * 10017 * The `ajax` property has three different modes of operation, depending on 10018 * how it is defined. These are: 10019 * 10020 * * `string` - Set the URL from where the data should be loaded from. 10021 * * `object` - Define properties for `jQuery.ajax`. 10022 * * `function` - Custom data get function 10023 * 10024 * `string` 10025 * -------- 10026 * 10027 * As a string, the `ajax` property simply defines the URL from which 10028 * DataTables will load data. 10029 * 10030 * `object` 10031 * -------- 10032 * 10033 * As an object, the parameters in the object are passed to 10034 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control 10035 * of the Ajax request. DataTables has a number of default parameters which 10036 * you can override using this option. Please refer to the jQuery 10037 * documentation for a full description of the options available, although 10038 * the following parameters provide additional options in DataTables or 10039 * require special consideration: 10040 * 10041 * * `data` - As with jQuery, `data` can be provided as an object, but it 10042 * can also be used as a function to manipulate the data DataTables sends 10043 * to the server. The function takes a single parameter, an object of 10044 * parameters with the values that DataTables has readied for sending. An 10045 * object may be returned which will be merged into the DataTables 10046 * defaults, or you can add the items to the object that was passed in and 10047 * not return anything from the function. This supersedes `fnServerParams` 10048 * from DataTables 1.9-. 10049 * 10050 * * `dataSrc` - By default DataTables will look for the property `data` (or 10051 * `aaData` for compatibility with DataTables 1.9-) when obtaining data 10052 * from an Ajax source or for server-side processing - this parameter 10053 * allows that property to be changed. You can use Javascript dotted 10054 * object notation to get a data source for multiple levels of nesting, or 10055 * it my be used as a function. As a function it takes a single parameter, 10056 * the JSON returned from the server, which can be manipulated as 10057 * required, with the returned value being that used by DataTables as the 10058 * data source for the table. This supersedes `sAjaxDataProp` from 10059 * DataTables 1.9-. 10060 * 10061 * * `success` - Should not be overridden it is used internally in 10062 * DataTables. To manipulate / transform the data returned by the server 10063 * use `ajax.dataSrc`, or use `ajax` as a function (see below). 10064 * 10065 * `function` 10066 * ---------- 10067 * 10068 * As a function, making the Ajax call is left up to yourself allowing 10069 * complete control of the Ajax request. Indeed, if desired, a method other 10070 * than Ajax could be used to obtain the required data, such as Web storage 10071 * or an AIR database. 10072 * 10073 * The function is given four parameters and no return is required. The 10074 * parameters are: 10075 * 10076 * 1. _object_ - Data to send to the server 10077 * 2. _function_ - Callback function that must be executed when the required 10078 * data has been obtained. That data should be passed into the callback 10079 * as the only parameter 10080 * 3. _object_ - DataTables settings object for the table 10081 * 10082 * Note that this supersedes `fnServerData` from DataTables 1.9-. 10083 * 10084 * @type string|object|function 10085 * @default null 10086 * 10087 * @dtopt Option 10088 * @name DataTable.defaults.ajax 10089 * @since 1.10.0 10090 * 10091 * @example 10092 * // Get JSON data from a file via Ajax. 10093 * // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default). 10094 * $('#example').dataTable( { 10095 * "ajax": "data.json" 10096 * } ); 10097 * 10098 * @example 10099 * // Get JSON data from a file via Ajax, using `dataSrc` to change 10100 * // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`) 10101 * $('#example').dataTable( { 10102 * "ajax": { 10103 * "url": "data.json", 10104 * "dataSrc": "tableData" 10105 * } 10106 * } ); 10107 * 10108 * @example 10109 * // Get JSON data from a file via Ajax, using `dataSrc` to read data 10110 * // from a plain array rather than an array in an object 10111 * $('#example').dataTable( { 10112 * "ajax": { 10113 * "url": "data.json", 10114 * "dataSrc": "" 10115 * } 10116 * } ); 10117 * 10118 * @example 10119 * // Manipulate the data returned from the server - add a link to data 10120 * // (note this can, should, be done using `render` for the column - this 10121 * // is just a simple example of how the data can be manipulated). 10122 * $('#example').dataTable( { 10123 * "ajax": { 10124 * "url": "data.json", 10125 * "dataSrc": function ( json ) { 10126 * for ( var i=0, ien=json.length ; i<ien ; i++ ) { 10127 * json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>'; 10128 * } 10129 * return json; 10130 * } 10131 * } 10132 * } ); 10133 * 10134 * @example 10135 * // Add data to the request 10136 * $('#example').dataTable( { 10137 * "ajax": { 10138 * "url": "data.json", 10139 * "data": function ( d ) { 10140 * return { 10141 * "extra_search": $('#extra').val() 10142 * }; 10143 * } 10144 * } 10145 * } ); 10146 * 10147 * @example 10148 * // Send request as POST 10149 * $('#example').dataTable( { 10150 * "ajax": { 10151 * "url": "data.json", 10152 * "type": "POST" 10153 * } 10154 * } ); 10155 * 10156 * @example 10157 * // Get the data from localStorage (could interface with a form for 10158 * // adding, editing and removing rows). 10159 * $('#example').dataTable( { 10160 * "ajax": function (data, callback, settings) { 10161 * callback( 10162 * JSON.parse( localStorage.getItem('dataTablesData') ) 10163 * ); 10164 * } 10165 * } ); 10166 */ 10167 "ajax": null, 10168 10169 10170 /** 10171 * This parameter allows you to readily specify the entries in the length drop 10172 * down menu that DataTables shows when pagination is enabled. It can be 10173 * either a 1D array of options which will be used for both the displayed 10174 * option and the value, or a 2D array which will use the array in the first 10175 * position as the value, and the array in the second position as the 10176 * displayed options (useful for language strings such as 'All'). 10177 * 10178 * Note that the `pageLength` property will be automatically set to the 10179 * first value given in this array, unless `pageLength` is also provided. 10180 * @type array 10181 * @default [ 10, 25, 50, 100 ] 10182 * 10183 * @dtopt Option 10184 * @name DataTable.defaults.lengthMenu 10185 * 10186 * @example 10187 * $(document).ready( function() { 10188 * $('#example').dataTable( { 10189 * "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]] 10190 * } ); 10191 * } ); 10192 */ 10193 "aLengthMenu": [ 10, 25, 50, 100 ], 10194 10195 10196 /** 10197 * The `columns` option in the initialisation parameter allows you to define 10198 * details about the way individual columns behave. For a full list of 10199 * column options that can be set, please see 10200 * {@link DataTable.defaults.column}. Note that if you use `columns` to 10201 * define your columns, you must have an entry in the array for every single 10202 * column that you have in your table (these can be null if you don't which 10203 * to specify any options). 10204 * @member 10205 * 10206 * @name DataTable.defaults.column 10207 */ 10208 "aoColumns": null, 10209 10210 /** 10211 * Very similar to `columns`, `columnDefs` allows you to target a specific 10212 * column, multiple columns, or all columns, using the `targets` property of 10213 * each object in the array. This allows great flexibility when creating 10214 * tables, as the `columnDefs` arrays can be of any length, targeting the 10215 * columns you specifically want. `columnDefs` may use any of the column 10216 * options available: {@link DataTable.defaults.column}, but it _must_ 10217 * have `targets` defined in each object in the array. Values in the `targets` 10218 * array may be: 10219 * <ul> 10220 * <li>a string - class name will be matched on the TH for the column</li> 10221 * <li>0 or a positive integer - column index counting from the left</li> 10222 * <li>a negative integer - column index counting from the right</li> 10223 * <li>the string "_all" - all columns (i.e. assign a default)</li> 10224 * </ul> 10225 * @member 10226 * 10227 * @name DataTable.defaults.columnDefs 10228 */ 10229 "aoColumnDefs": null, 10230 10231 10232 /** 10233 * Basically the same as `search`, this parameter defines the individual column 10234 * filtering state at initialisation time. The array must be of the same size 10235 * as the number of columns, and each element be an object with the parameters 10236 * `search` and `escapeRegex` (the latter is optional). 'null' is also 10237 * accepted and the default will be used. 10238 * @type array 10239 * @default [] 10240 * 10241 * @dtopt Option 10242 * @name DataTable.defaults.searchCols 10243 * 10244 * @example 10245 * $(document).ready( function() { 10246 * $('#example').dataTable( { 10247 * "searchCols": [ 10248 * null, 10249 * { "search": "My filter" }, 10250 * null, 10251 * { "search": "^[0-9]", "escapeRegex": false } 10252 * ] 10253 * } ); 10254 * } ) 10255 */ 10256 "aoSearchCols": [], 10257 10258 10259 /** 10260 * An array of CSS classes that should be applied to displayed rows. This 10261 * array may be of any length, and DataTables will apply each class 10262 * sequentially, looping when required. 10263 * @type array 10264 * @default null <i>Will take the values determined by the `oClasses.stripe*` 10265 * options</i> 10266 * 10267 * @dtopt Option 10268 * @name DataTable.defaults.stripeClasses 10269 * 10270 * @example 10271 * $(document).ready( function() { 10272 * $('#example').dataTable( { 10273 * "stripeClasses": [ 'strip1', 'strip2', 'strip3' ] 10274 * } ); 10275 * } ) 10276 */ 10277 "asStripeClasses": null, 10278 10279 10280 /** 10281 * Enable or disable automatic column width calculation. This can be disabled 10282 * as an optimisation (it takes some time to calculate the widths) if the 10283 * tables widths are passed in using `columns`. 10284 * @type boolean 10285 * @default true 10286 * 10287 * @dtopt Features 10288 * @name DataTable.defaults.autoWidth 10289 * 10290 * @example 10291 * $(document).ready( function () { 10292 * $('#example').dataTable( { 10293 * "autoWidth": false 10294 * } ); 10295 * } ); 10296 */ 10297 "bAutoWidth": true, 10298 10299 10300 /** 10301 * Deferred rendering can provide DataTables with a huge speed boost when you 10302 * are using an Ajax or JS data source for the table. This option, when set to 10303 * true, will cause DataTables to defer the creation of the table elements for 10304 * each row until they are needed for a draw - saving a significant amount of 10305 * time. 10306 * @type boolean 10307 * @default false 10308 * 10309 * @dtopt Features 10310 * @name DataTable.defaults.deferRender 10311 * 10312 * @example 10313 * $(document).ready( function() { 10314 * $('#example').dataTable( { 10315 * "ajax": "sources/arrays.txt", 10316 * "deferRender": true 10317 * } ); 10318 * } ); 10319 */ 10320 "bDeferRender": false, 10321 10322 10323 /** 10324 * Replace a DataTable which matches the given selector and replace it with 10325 * one which has the properties of the new initialisation object passed. If no 10326 * table matches the selector, then the new DataTable will be constructed as 10327 * per normal. 10328 * @type boolean 10329 * @default false 10330 * 10331 * @dtopt Options 10332 * @name DataTable.defaults.destroy 10333 * 10334 * @example 10335 * $(document).ready( function() { 10336 * $('#example').dataTable( { 10337 * "srollY": "200px", 10338 * "paginate": false 10339 * } ); 10340 * 10341 * // Some time later.... 10342 * $('#example').dataTable( { 10343 * "filter": false, 10344 * "destroy": true 10345 * } ); 10346 * } ); 10347 */ 10348 "bDestroy": false, 10349 10350 10351 /** 10352 * Enable or disable filtering of data. Filtering in DataTables is "smart" in 10353 * that it allows the end user to input multiple words (space separated) and 10354 * will match a row containing those words, even if not in the order that was 10355 * specified (this allow matching across multiple columns). Note that if you 10356 * wish to use filtering in DataTables this must remain 'true' - to remove the 10357 * default filtering input box and retain filtering abilities, please use 10358 * {@link DataTable.defaults.dom}. 10359 * @type boolean 10360 * @default true 10361 * 10362 * @dtopt Features 10363 * @name DataTable.defaults.searching 10364 * 10365 * @example 10366 * $(document).ready( function () { 10367 * $('#example').dataTable( { 10368 * "searching": false 10369 * } ); 10370 * } ); 10371 */ 10372 "bFilter": true, 10373 10374 10375 /** 10376 * Enable or disable the table information display. This shows information 10377 * about the data that is currently visible on the page, including information 10378 * about filtered data if that action is being performed. 10379 * @type boolean 10380 * @default true 10381 * 10382 * @dtopt Features 10383 * @name DataTable.defaults.info 10384 * 10385 * @example 10386 * $(document).ready( function () { 10387 * $('#example').dataTable( { 10388 * "info": false 10389 * } ); 10390 * } ); 10391 */ 10392 "bInfo": true, 10393 10394 10395 /** 10396 * Allows the end user to select the size of a formatted page from a select 10397 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`). 10398 * @type boolean 10399 * @default true 10400 * 10401 * @dtopt Features 10402 * @name DataTable.defaults.lengthChange 10403 * 10404 * @example 10405 * $(document).ready( function () { 10406 * $('#example').dataTable( { 10407 * "lengthChange": false 10408 * } ); 10409 * } ); 10410 */ 10411 "bLengthChange": true, 10412 10413 10414 /** 10415 * Enable or disable pagination. 10416 * @type boolean 10417 * @default true 10418 * 10419 * @dtopt Features 10420 * @name DataTable.defaults.paging 10421 * 10422 * @example 10423 * $(document).ready( function () { 10424 * $('#example').dataTable( { 10425 * "paging": false 10426 * } ); 10427 * } ); 10428 */ 10429 "bPaginate": true, 10430 10431 10432 /** 10433 * Enable or disable the display of a 'processing' indicator when the table is 10434 * being processed (e.g. a sort). This is particularly useful for tables with 10435 * large amounts of data where it can take a noticeable amount of time to sort 10436 * the entries. 10437 * @type boolean 10438 * @default false 10439 * 10440 * @dtopt Features 10441 * @name DataTable.defaults.processing 10442 * 10443 * @example 10444 * $(document).ready( function () { 10445 * $('#example').dataTable( { 10446 * "processing": true 10447 * } ); 10448 * } ); 10449 */ 10450 "bProcessing": false, 10451 10452 10453 /** 10454 * Retrieve the DataTables object for the given selector. Note that if the 10455 * table has already been initialised, this parameter will cause DataTables 10456 * to simply return the object that has already been set up - it will not take 10457 * account of any changes you might have made to the initialisation object 10458 * passed to DataTables (setting this parameter to true is an acknowledgement 10459 * that you understand this). `destroy` can be used to reinitialise a table if 10460 * you need. 10461 * @type boolean 10462 * @default false 10463 * 10464 * @dtopt Options 10465 * @name DataTable.defaults.retrieve 10466 * 10467 * @example 10468 * $(document).ready( function() { 10469 * initTable(); 10470 * tableActions(); 10471 * } ); 10472 * 10473 * function initTable () 10474 * { 10475 * return $('#example').dataTable( { 10476 * "scrollY": "200px", 10477 * "paginate": false, 10478 * "retrieve": true 10479 * } ); 10480 * } 10481 * 10482 * function tableActions () 10483 * { 10484 * var table = initTable(); 10485 * // perform API operations with oTable 10486 * } 10487 */ 10488 "bRetrieve": false, 10489 10490 10491 /** 10492 * When vertical (y) scrolling is enabled, DataTables will force the height of 10493 * the table's viewport to the given height at all times (useful for layout). 10494 * However, this can look odd when filtering data down to a small data set, 10495 * and the footer is left "floating" further down. This parameter (when 10496 * enabled) will cause DataTables to collapse the table's viewport down when 10497 * the result set will fit within the given Y height. 10498 * @type boolean 10499 * @default false 10500 * 10501 * @dtopt Options 10502 * @name DataTable.defaults.scrollCollapse 10503 * 10504 * @example 10505 * $(document).ready( function() { 10506 * $('#example').dataTable( { 10507 * "scrollY": "200", 10508 * "scrollCollapse": true 10509 * } ); 10510 * } ); 10511 */ 10512 "bScrollCollapse": false, 10513 10514 10515 /** 10516 * Configure DataTables to use server-side processing. Note that the 10517 * `ajax` parameter must also be given in order to give DataTables a 10518 * source to obtain the required data for each draw. 10519 * @type boolean 10520 * @default false 10521 * 10522 * @dtopt Features 10523 * @dtopt Server-side 10524 * @name DataTable.defaults.serverSide 10525 * 10526 * @example 10527 * $(document).ready( function () { 10528 * $('#example').dataTable( { 10529 * "serverSide": true, 10530 * "ajax": "xhr.php" 10531 * } ); 10532 * } ); 10533 */ 10534 "bServerSide": false, 10535 10536 10537 /** 10538 * Enable or disable sorting of columns. Sorting of individual columns can be 10539 * disabled by the `sortable` option for each column. 10540 * @type boolean 10541 * @default true 10542 * 10543 * @dtopt Features 10544 * @name DataTable.defaults.ordering 10545 * 10546 * @example 10547 * $(document).ready( function () { 10548 * $('#example').dataTable( { 10549 * "ordering": false 10550 * } ); 10551 * } ); 10552 */ 10553 "bSort": true, 10554 10555 10556 /** 10557 * Enable or display DataTables' ability to sort multiple columns at the 10558 * same time (activated by shift-click by the user). 10559 * @type boolean 10560 * @default true 10561 * 10562 * @dtopt Options 10563 * @name DataTable.defaults.orderMulti 10564 * 10565 * @example 10566 * // Disable multiple column sorting ability 10567 * $(document).ready( function () { 10568 * $('#example').dataTable( { 10569 * "orderMulti": false 10570 * } ); 10571 * } ); 10572 */ 10573 "bSortMulti": true, 10574 10575 10576 /** 10577 * Allows control over whether DataTables should use the top (true) unique 10578 * cell that is found for a single column, or the bottom (false - default). 10579 * This is useful when using complex headers. 10580 * @type boolean 10581 * @default false 10582 * 10583 * @dtopt Options 10584 * @name DataTable.defaults.orderCellsTop 10585 * 10586 * @example 10587 * $(document).ready( function() { 10588 * $('#example').dataTable( { 10589 * "orderCellsTop": true 10590 * } ); 10591 * } ); 10592 */ 10593 "bSortCellsTop": false, 10594 10595 10596 /** 10597 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and 10598 * `sorting\_3` to the columns which are currently being sorted on. This is 10599 * presented as a feature switch as it can increase processing time (while 10600 * classes are removed and added) so for large data sets you might want to 10601 * turn this off. 10602 * @type boolean 10603 * @default true 10604 * 10605 * @dtopt Features 10606 * @name DataTable.defaults.orderClasses 10607 * 10608 * @example 10609 * $(document).ready( function () { 10610 * $('#example').dataTable( { 10611 * "orderClasses": false 10612 * } ); 10613 * } ); 10614 */ 10615 "bSortClasses": true, 10616 10617 10618 /** 10619 * Enable or disable state saving. When enabled HTML5 `localStorage` will be 10620 * used to save table display information such as pagination information, 10621 * display length, filtering and sorting. As such when the end user reloads 10622 * the page the display display will match what thy had previously set up. 10623 * 10624 * Due to the use of `localStorage` the default state saving is not supported 10625 * in IE6 or 7. If state saving is required in those browsers, use 10626 * `stateSaveCallback` to provide a storage solution such as cookies. 10627 * @type boolean 10628 * @default false 10629 * 10630 * @dtopt Features 10631 * @name DataTable.defaults.stateSave 10632 * 10633 * @example 10634 * $(document).ready( function () { 10635 * $('#example').dataTable( { 10636 * "stateSave": true 10637 * } ); 10638 * } ); 10639 */ 10640 "bStateSave": false, 10641 10642 10643 /** 10644 * This function is called when a TR element is created (and all TD child 10645 * elements have been inserted), or registered if using a DOM source, allowing 10646 * manipulation of the TR element (adding classes etc). 10647 * @type function 10648 * @param {node} row "TR" element for the current row 10649 * @param {array} data Raw data array for this row 10650 * @param {int} dataIndex The index of this row in the internal aoData array 10651 * 10652 * @dtopt Callbacks 10653 * @name DataTable.defaults.createdRow 10654 * 10655 * @example 10656 * $(document).ready( function() { 10657 * $('#example').dataTable( { 10658 * "createdRow": function( row, data, dataIndex ) { 10659 * // Bold the grade for all 'A' grade browsers 10660 * if ( data[4] == "A" ) 10661 * { 10662 * $('td:eq(4)', row).html( '<b>A</b>' ); 10663 * } 10664 * } 10665 * } ); 10666 * } ); 10667 */ 10668 "fnCreatedRow": null, 10669 10670 10671 /** 10672 * This function is called on every 'draw' event, and allows you to 10673 * dynamically modify any aspect you want about the created DOM. 10674 * @type function 10675 * @param {object} settings DataTables settings object 10676 * 10677 * @dtopt Callbacks 10678 * @name DataTable.defaults.drawCallback 10679 * 10680 * @example 10681 * $(document).ready( function() { 10682 * $('#example').dataTable( { 10683 * "drawCallback": function( settings ) { 10684 * alert( 'DataTables has redrawn the table' ); 10685 * } 10686 * } ); 10687 * } ); 10688 */ 10689 "fnDrawCallback": null, 10690 10691 10692 /** 10693 * Identical to fnHeaderCallback() but for the table footer this function 10694 * allows you to modify the table footer on every 'draw' event. 10695 * @type function 10696 * @param {node} foot "TR" element for the footer 10697 * @param {array} data Full table data (as derived from the original HTML) 10698 * @param {int} start Index for the current display starting point in the 10699 * display array 10700 * @param {int} end Index for the current display ending point in the 10701 * display array 10702 * @param {array int} display Index array to translate the visual position 10703 * to the full data array 10704 * 10705 * @dtopt Callbacks 10706 * @name DataTable.defaults.footerCallback 10707 * 10708 * @example 10709 * $(document).ready( function() { 10710 * $('#example').dataTable( { 10711 * "footerCallback": function( tfoot, data, start, end, display ) { 10712 * tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start; 10713 * } 10714 * } ); 10715 * } ) 10716 */ 10717 "fnFooterCallback": null, 10718 10719 10720 /** 10721 * When rendering large numbers in the information element for the table 10722 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers 10723 * to have a comma separator for the 'thousands' units (e.g. 1 million is 10724 * rendered as "1,000,000") to help readability for the end user. This 10725 * function will override the default method DataTables uses. 10726 * @type function 10727 * @member 10728 * @param {int} toFormat number to be formatted 10729 * @returns {string} formatted string for DataTables to show the number 10730 * 10731 * @dtopt Callbacks 10732 * @name DataTable.defaults.formatNumber 10733 * 10734 * @example 10735 * // Format a number using a single quote for the separator (note that 10736 * // this can also be done with the language.thousands option) 10737 * $(document).ready( function() { 10738 * $('#example').dataTable( { 10739 * "formatNumber": function ( toFormat ) { 10740 * return toFormat.toString().replace( 10741 * /\B(?=(\d{3})+(?!\d))/g, "'" 10742 * ); 10743 * }; 10744 * } ); 10745 * } ); 10746 */ 10747 "fnFormatNumber": function ( toFormat ) { 10748 return toFormat.toString().replace( 10749 /\B(?=(\d{3})+(?!\d))/g, 10750 this.oLanguage.sThousands 10751 ); 10752 }, 10753 10754 10755 /** 10756 * This function is called on every 'draw' event, and allows you to 10757 * dynamically modify the header row. This can be used to calculate and 10758 * display useful information about the table. 10759 * @type function 10760 * @param {node} head "TR" element for the header 10761 * @param {array} data Full table data (as derived from the original HTML) 10762 * @param {int} start Index for the current display starting point in the 10763 * display array 10764 * @param {int} end Index for the current display ending point in the 10765 * display array 10766 * @param {array int} display Index array to translate the visual position 10767 * to the full data array 10768 * 10769 * @dtopt Callbacks 10770 * @name DataTable.defaults.headerCallback 10771 * 10772 * @example 10773 * $(document).ready( function() { 10774 * $('#example').dataTable( { 10775 * "fheaderCallback": function( head, data, start, end, display ) { 10776 * head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records"; 10777 * } 10778 * } ); 10779 * } ) 10780 */ 10781 "fnHeaderCallback": null, 10782 10783 10784 /** 10785 * The information element can be used to convey information about the current 10786 * state of the table. Although the internationalisation options presented by 10787 * DataTables are quite capable of dealing with most customisations, there may 10788 * be times where you wish to customise the string further. This callback 10789 * allows you to do exactly that. 10790 * @type function 10791 * @param {object} oSettings DataTables settings object 10792 * @param {int} start Starting position in data for the draw 10793 * @param {int} end End position in data for the draw 10794 * @param {int} max Total number of rows in the table (regardless of 10795 * filtering) 10796 * @param {int} total Total number of rows in the data set, after filtering 10797 * @param {string} pre The string that DataTables has formatted using it's 10798 * own rules 10799 * @returns {string} The string to be displayed in the information element. 10800 * 10801 * @dtopt Callbacks 10802 * @name DataTable.defaults.infoCallback 10803 * 10804 * @example 10805 * $('#example').dataTable( { 10806 * "infoCallback": function( settings, start, end, max, total, pre ) { 10807 * return start +" to "+ end; 10808 * } 10809 * } ); 10810 */ 10811 "fnInfoCallback": null, 10812 10813 10814 /** 10815 * Called when the table has been initialised. Normally DataTables will 10816 * initialise sequentially and there will be no need for this function, 10817 * however, this does not hold true when using external language information 10818 * since that is obtained using an async XHR call. 10819 * @type function 10820 * @param {object} settings DataTables settings object 10821 * @param {object} json The JSON object request from the server - only 10822 * present if client-side Ajax sourced data is used 10823 * 10824 * @dtopt Callbacks 10825 * @name DataTable.defaults.initComplete 10826 * 10827 * @example 10828 * $(document).ready( function() { 10829 * $('#example').dataTable( { 10830 * "initComplete": function(settings, json) { 10831 * alert( 'DataTables has finished its initialisation.' ); 10832 * } 10833 * } ); 10834 * } ) 10835 */ 10836 "fnInitComplete": null, 10837 10838 10839 /** 10840 * Called at the very start of each table draw and can be used to cancel the 10841 * draw by returning false, any other return (including undefined) results in 10842 * the full draw occurring). 10843 * @type function 10844 * @param {object} settings DataTables settings object 10845 * @returns {boolean} False will cancel the draw, anything else (including no 10846 * return) will allow it to complete. 10847 * 10848 * @dtopt Callbacks 10849 * @name DataTable.defaults.preDrawCallback 10850 * 10851 * @example 10852 * $(document).ready( function() { 10853 * $('#example').dataTable( { 10854 * "preDrawCallback": function( settings ) { 10855 * if ( $('#test').val() == 1 ) { 10856 * return false; 10857 * } 10858 * } 10859 * } ); 10860 * } ); 10861 */ 10862 "fnPreDrawCallback": null, 10863 10864 10865 /** 10866 * This function allows you to 'post process' each row after it have been 10867 * generated for each table draw, but before it is rendered on screen. This 10868 * function might be used for setting the row class name etc. 10869 * @type function 10870 * @param {node} row "TR" element for the current row 10871 * @param {array} data Raw data array for this row 10872 * @param {int} displayIndex The display index for the current table draw 10873 * @param {int} displayIndexFull The index of the data in the full list of 10874 * rows (after filtering) 10875 * 10876 * @dtopt Callbacks 10877 * @name DataTable.defaults.rowCallback 10878 * 10879 * @example 10880 * $(document).ready( function() { 10881 * $('#example').dataTable( { 10882 * "rowCallback": function( row, data, displayIndex, displayIndexFull ) { 10883 * // Bold the grade for all 'A' grade browsers 10884 * if ( data[4] == "A" ) { 10885 * $('td:eq(4)', row).html( '<b>A</b>' ); 10886 * } 10887 * } 10888 * } ); 10889 * } ); 10890 */ 10891 "fnRowCallback": null, 10892 10893 10894 /** 10895 * __Deprecated__ The functionality provided by this parameter has now been 10896 * superseded by that provided through `ajax`, which should be used instead. 10897 * 10898 * This parameter allows you to override the default function which obtains 10899 * the data from the server so something more suitable for your application. 10900 * For example you could use POST data, or pull information from a Gears or 10901 * AIR database. 10902 * @type function 10903 * @member 10904 * @param {string} source HTTP source to obtain the data from (`ajax`) 10905 * @param {array} data A key/value pair object containing the data to send 10906 * to the server 10907 * @param {function} callback to be called on completion of the data get 10908 * process that will draw the data on the page. 10909 * @param {object} settings DataTables settings object 10910 * 10911 * @dtopt Callbacks 10912 * @dtopt Server-side 10913 * @name DataTable.defaults.serverData 10914 * 10915 * @deprecated 1.10. Please use `ajax` for this functionality now. 10916 */ 10917 "fnServerData": null, 10918 10919 10920 /** 10921 * __Deprecated__ The functionality provided by this parameter has now been 10922 * superseded by that provided through `ajax`, which should be used instead. 10923 * 10924 * It is often useful to send extra data to the server when making an Ajax 10925 * request - for example custom filtering information, and this callback 10926 * function makes it trivial to send extra information to the server. The 10927 * passed in parameter is the data set that has been constructed by 10928 * DataTables, and you can add to this or modify it as you require. 10929 * @type function 10930 * @param {array} data Data array (array of objects which are name/value 10931 * pairs) that has been constructed by DataTables and will be sent to the 10932 * server. In the case of Ajax sourced data with server-side processing 10933 * this will be an empty array, for server-side processing there will be a 10934 * significant number of parameters! 10935 * @returns {undefined} Ensure that you modify the data array passed in, 10936 * as this is passed by reference. 10937 * 10938 * @dtopt Callbacks 10939 * @dtopt Server-side 10940 * @name DataTable.defaults.serverParams 10941 * 10942 * @deprecated 1.10. Please use `ajax` for this functionality now. 10943 */ 10944 "fnServerParams": null, 10945 10946 10947 /** 10948 * Load the table state. With this function you can define from where, and how, the 10949 * state of a table is loaded. By default DataTables will load from `localStorage` 10950 * but you might wish to use a server-side database or cookies. 10951 * @type function 10952 * @member 10953 * @param {object} settings DataTables settings object 10954 * @param {object} callback Callback that can be executed when done. It 10955 * should be passed the loaded state object. 10956 * @return {object} The DataTables state object to be loaded 10957 * 10958 * @dtopt Callbacks 10959 * @name DataTable.defaults.stateLoadCallback 10960 * 10961 * @example 10962 * $(document).ready( function() { 10963 * $('#example').dataTable( { 10964 * "stateSave": true, 10965 * "stateLoadCallback": function (settings, callback) { 10966 * $.ajax( { 10967 * "url": "/state_load", 10968 * "dataType": "json", 10969 * "success": function (json) { 10970 * callback( json ); 10971 * } 10972 * } ); 10973 * } 10974 * } ); 10975 * } ); 10976 */ 10977 "fnStateLoadCallback": function ( settings ) { 10978 try { 10979 return JSON.parse( 10980 (settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem( 10981 'DataTables_'+settings.sInstance+'_'+location.pathname 10982 ) 10983 ); 10984 } catch (e) {} 10985 }, 10986 10987 10988 /** 10989 * Callback which allows modification of the saved state prior to loading that state. 10990 * This callback is called when the table is loading state from the stored data, but 10991 * prior to the settings object being modified by the saved state. Note that for 10992 * plug-in authors, you should use the `stateLoadParams` event to load parameters for 10993 * a plug-in. 10994 * @type function 10995 * @param {object} settings DataTables settings object 10996 * @param {object} data The state object that is to be loaded 10997 * 10998 * @dtopt Callbacks 10999 * @name DataTable.defaults.stateLoadParams 11000 * 11001 * @example 11002 * // Remove a saved filter, so filtering is never loaded 11003 * $(document).ready( function() { 11004 * $('#example').dataTable( { 11005 * "stateSave": true, 11006 * "stateLoadParams": function (settings, data) { 11007 * data.oSearch.sSearch = ""; 11008 * } 11009 * } ); 11010 * } ); 11011 * 11012 * @example 11013 * // Disallow state loading by returning false 11014 * $(document).ready( function() { 11015 * $('#example').dataTable( { 11016 * "stateSave": true, 11017 * "stateLoadParams": function (settings, data) { 11018 * return false; 11019 * } 11020 * } ); 11021 * } ); 11022 */ 11023 "fnStateLoadParams": null, 11024 11025 11026 /** 11027 * Callback that is called when the state has been loaded from the state saving method 11028 * and the DataTables settings object has been modified as a result of the loaded state. 11029 * @type function 11030 * @param {object} settings DataTables settings object 11031 * @param {object} data The state object that was loaded 11032 * 11033 * @dtopt Callbacks 11034 * @name DataTable.defaults.stateLoaded 11035 * 11036 * @example 11037 * // Show an alert with the filtering value that was saved 11038 * $(document).ready( function() { 11039 * $('#example').dataTable( { 11040 * "stateSave": true, 11041 * "stateLoaded": function (settings, data) { 11042 * alert( 'Saved filter was: '+data.oSearch.sSearch ); 11043 * } 11044 * } ); 11045 * } ); 11046 */ 11047 "fnStateLoaded": null, 11048 11049 11050 /** 11051 * Save the table state. This function allows you to define where and how the state 11052 * information for the table is stored By default DataTables will use `localStorage` 11053 * but you might wish to use a server-side database or cookies. 11054 * @type function 11055 * @member 11056 * @param {object} settings DataTables settings object 11057 * @param {object} data The state object to be saved 11058 * 11059 * @dtopt Callbacks 11060 * @name DataTable.defaults.stateSaveCallback 11061 * 11062 * @example 11063 * $(document).ready( function() { 11064 * $('#example').dataTable( { 11065 * "stateSave": true, 11066 * "stateSaveCallback": function (settings, data) { 11067 * // Send an Ajax request to the server with the state object 11068 * $.ajax( { 11069 * "url": "/state_save", 11070 * "data": data, 11071 * "dataType": "json", 11072 * "method": "POST" 11073 * "success": function () {} 11074 * } ); 11075 * } 11076 * } ); 11077 * } ); 11078 */ 11079 "fnStateSaveCallback": function ( settings, data ) { 11080 try { 11081 (settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem( 11082 'DataTables_'+settings.sInstance+'_'+location.pathname, 11083 JSON.stringify( data ) 11084 ); 11085 } catch (e) {} 11086 }, 11087 11088 11089 /** 11090 * Callback which allows modification of the state to be saved. Called when the table 11091 * has changed state a new state save is required. This method allows modification of 11092 * the state saving object prior to actually doing the save, including addition or 11093 * other state properties or modification. Note that for plug-in authors, you should 11094 * use the `stateSaveParams` event to save parameters for a plug-in. 11095 * @type function 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.stateSaveParams 11101 * 11102 * @example 11103 * // Remove a saved filter, so filtering is never saved 11104 * $(document).ready( function() { 11105 * $('#example').dataTable( { 11106 * "stateSave": true, 11107 * "stateSaveParams": function (settings, data) { 11108 * data.oSearch.sSearch = ""; 11109 * } 11110 * } ); 11111 * } ); 11112 */ 11113 "fnStateSaveParams": null, 11114 11115 11116 /** 11117 * Duration for which the saved state information is considered valid. After this period 11118 * has elapsed the state will be returned to the default. 11119 * Value is given in seconds. 11120 * @type int 11121 * @default 7200 <i>(2 hours)</i> 11122 * 11123 * @dtopt Options 11124 * @name DataTable.defaults.stateDuration 11125 * 11126 * @example 11127 * $(document).ready( function() { 11128 * $('#example').dataTable( { 11129 * "stateDuration": 60*60*24; // 1 day 11130 * } ); 11131 * } ) 11132 */ 11133 "iStateDuration": 7200, 11134 11135 11136 /** 11137 * When enabled DataTables will not make a request to the server for the first 11138 * page draw - rather it will use the data already on the page (no sorting etc 11139 * will be applied to it), thus saving on an XHR at load time. `deferLoading` 11140 * is used to indicate that deferred loading is required, but it is also used 11141 * to tell DataTables how many records there are in the full table (allowing 11142 * the information element and pagination to be displayed correctly). In the case 11143 * where a filtering is applied to the table on initial load, this can be 11144 * indicated by giving the parameter as an array, where the first element is 11145 * the number of records available after filtering and the second element is the 11146 * number of records without filtering (allowing the table information element 11147 * to be shown correctly). 11148 * @type int | array 11149 * @default null 11150 * 11151 * @dtopt Options 11152 * @name DataTable.defaults.deferLoading 11153 * 11154 * @example 11155 * // 57 records available in the table, no filtering applied 11156 * $(document).ready( function() { 11157 * $('#example').dataTable( { 11158 * "serverSide": true, 11159 * "ajax": "scripts/server_processing.php", 11160 * "deferLoading": 57 11161 * } ); 11162 * } ); 11163 * 11164 * @example 11165 * // 57 records after filtering, 100 without filtering (an initial filter applied) 11166 * $(document).ready( function() { 11167 * $('#example').dataTable( { 11168 * "serverSide": true, 11169 * "ajax": "scripts/server_processing.php", 11170 * "deferLoading": [ 57, 100 ], 11171 * "search": { 11172 * "search": "my_filter" 11173 * } 11174 * } ); 11175 * } ); 11176 */ 11177 "iDeferLoading": null, 11178 11179 11180 /** 11181 * Number of rows to display on a single page when using pagination. If 11182 * feature enabled (`lengthChange`) then the end user will be able to override 11183 * this to a custom setting using a pop-up menu. 11184 * @type int 11185 * @default 10 11186 * 11187 * @dtopt Options 11188 * @name DataTable.defaults.pageLength 11189 * 11190 * @example 11191 * $(document).ready( function() { 11192 * $('#example').dataTable( { 11193 * "pageLength": 50 11194 * } ); 11195 * } ) 11196 */ 11197 "iDisplayLength": 10, 11198 11199 11200 /** 11201 * Define the starting point for data display when using DataTables with 11202 * pagination. Note that this parameter is the number of records, rather than 11203 * the page number, so if you have 10 records per page and want to start on 11204 * the third page, it should be "20". 11205 * @type int 11206 * @default 0 11207 * 11208 * @dtopt Options 11209 * @name DataTable.defaults.displayStart 11210 * 11211 * @example 11212 * $(document).ready( function() { 11213 * $('#example').dataTable( { 11214 * "displayStart": 20 11215 * } ); 11216 * } ) 11217 */ 11218 "iDisplayStart": 0, 11219 11220 11221 /** 11222 * By default DataTables allows keyboard navigation of the table (sorting, paging, 11223 * and filtering) by adding a `tabindex` attribute to the required elements. This 11224 * allows you to tab through the controls and press the enter key to activate them. 11225 * The tabindex is default 0, meaning that the tab follows the flow of the document. 11226 * You can overrule this using this parameter if you wish. Use a value of -1 to 11227 * disable built-in keyboard navigation. 11228 * @type int 11229 * @default 0 11230 * 11231 * @dtopt Options 11232 * @name DataTable.defaults.tabIndex 11233 * 11234 * @example 11235 * $(document).ready( function() { 11236 * $('#example').dataTable( { 11237 * "tabIndex": 1 11238 * } ); 11239 * } ); 11240 */ 11241 "iTabIndex": 0, 11242 11243 11244 /** 11245 * Classes that DataTables assigns to the various components and features 11246 * that it adds to the HTML table. This allows classes to be configured 11247 * during initialisation in addition to through the static 11248 * {@link DataTable.ext.oStdClasses} object). 11249 * @namespace 11250 * @name DataTable.defaults.classes 11251 */ 11252 "oClasses": {}, 11253 11254 11255 /** 11256 * All strings that DataTables uses in the user interface that it creates 11257 * are defined in this object, allowing you to modified them individually or 11258 * completely replace them all as required. 11259 * @namespace 11260 * @name DataTable.defaults.language 11261 */ 11262 "oLanguage": { 11263 /** 11264 * Strings that are used for WAI-ARIA labels and controls only (these are not 11265 * actually visible on the page, but will be read by screenreaders, and thus 11266 * must be internationalised as well). 11267 * @namespace 11268 * @name DataTable.defaults.language.aria 11269 */ 11270 "oAria": { 11271 /** 11272 * ARIA label that is added to the table headers when the column may be 11273 * sorted ascending by activing the column (click or return when focused). 11274 * Note that the column header is prefixed to this string. 11275 * @type string 11276 * @default : activate to sort column ascending 11277 * 11278 * @dtopt Language 11279 * @name DataTable.defaults.language.aria.sortAscending 11280 * 11281 * @example 11282 * $(document).ready( function() { 11283 * $('#example').dataTable( { 11284 * "language": { 11285 * "aria": { 11286 * "sortAscending": " - click/return to sort ascending" 11287 * } 11288 * } 11289 * } ); 11290 * } ); 11291 */ 11292 "sSortAscending": ": activate to sort column ascending", 11293 11294 /** 11295 * ARIA label that is added to the table headers when the column may be 11296 * sorted descending by activing the column (click or return when focused). 11297 * Note that the column header is prefixed to this string. 11298 * @type string 11299 * @default : activate to sort column ascending 11300 * 11301 * @dtopt Language 11302 * @name DataTable.defaults.language.aria.sortDescending 11303 * 11304 * @example 11305 * $(document).ready( function() { 11306 * $('#example').dataTable( { 11307 * "language": { 11308 * "aria": { 11309 * "sortDescending": " - click/return to sort descending" 11310 * } 11311 * } 11312 * } ); 11313 * } ); 11314 */ 11315 "sSortDescending": ": activate to sort column descending" 11316 }, 11317 11318 /** 11319 * Pagination string used by DataTables for the built-in pagination 11320 * control types. 11321 * @namespace 11322 * @name DataTable.defaults.language.paginate 11323 */ 11324 "oPaginate": { 11325 /** 11326 * Text to use when using the 'full_numbers' type of pagination for the 11327 * button to take the user to the first page. 11328 * @type string 11329 * @default First 11330 * 11331 * @dtopt Language 11332 * @name DataTable.defaults.language.paginate.first 11333 * 11334 * @example 11335 * $(document).ready( function() { 11336 * $('#example').dataTable( { 11337 * "language": { 11338 * "paginate": { 11339 * "first": "First page" 11340 * } 11341 * } 11342 * } ); 11343 * } ); 11344 */ 11345 "sFirst": "First", 11346 11347 11348 /** 11349 * Text to use when using the 'full_numbers' type of pagination for the 11350 * button to take the user to the last page. 11351 * @type string 11352 * @default Last 11353 * 11354 * @dtopt Language 11355 * @name DataTable.defaults.language.paginate.last 11356 * 11357 * @example 11358 * $(document).ready( function() { 11359 * $('#example').dataTable( { 11360 * "language": { 11361 * "paginate": { 11362 * "last": "Last page" 11363 * } 11364 * } 11365 * } ); 11366 * } ); 11367 */ 11368 "sLast": "Last", 11369 11370 11371 /** 11372 * Text to use for the 'next' pagination button (to take the user to the 11373 * next page). 11374 * @type string 11375 * @default Next 11376 * 11377 * @dtopt Language 11378 * @name DataTable.defaults.language.paginate.next 11379 * 11380 * @example 11381 * $(document).ready( function() { 11382 * $('#example').dataTable( { 11383 * "language": { 11384 * "paginate": { 11385 * "next": "Next page" 11386 * } 11387 * } 11388 * } ); 11389 * } ); 11390 */ 11391 "sNext": "Next", 11392 11393 11394 /** 11395 * Text to use for the 'previous' pagination button (to take the user to 11396 * the previous page). 11397 * @type string 11398 * @default Previous 11399 * 11400 * @dtopt Language 11401 * @name DataTable.defaults.language.paginate.previous 11402 * 11403 * @example 11404 * $(document).ready( function() { 11405 * $('#example').dataTable( { 11406 * "language": { 11407 * "paginate": { 11408 * "previous": "Previous page" 11409 * } 11410 * } 11411 * } ); 11412 * } ); 11413 */ 11414 "sPrevious": "Previous" 11415 }, 11416 11417 /** 11418 * This string is shown in preference to `zeroRecords` when the table is 11419 * empty of data (regardless of filtering). Note that this is an optional 11420 * parameter - if it is not given, the value of `zeroRecords` will be used 11421 * instead (either the default or given value). 11422 * @type string 11423 * @default No data available in table 11424 * 11425 * @dtopt Language 11426 * @name DataTable.defaults.language.emptyTable 11427 * 11428 * @example 11429 * $(document).ready( function() { 11430 * $('#example').dataTable( { 11431 * "language": { 11432 * "emptyTable": "No data available in table" 11433 * } 11434 * } ); 11435 * } ); 11436 */ 11437 "sEmptyTable": "No data available in table", 11438 11439 11440 /** 11441 * This string gives information to the end user about the information 11442 * that is current on display on the page. The following tokens can be 11443 * used in the string and will be dynamically replaced as the table 11444 * display updates. This tokens can be placed anywhere in the string, or 11445 * removed as needed by the language requires: 11446 * 11447 * * `\_START\_` - Display index of the first record on the current page 11448 * * `\_END\_` - Display index of the last record on the current page 11449 * * `\_TOTAL\_` - Number of records in the table after filtering 11450 * * `\_MAX\_` - Number of records in the table without filtering 11451 * * `\_PAGE\_` - Current page number 11452 * * `\_PAGES\_` - Total number of pages of data in the table 11453 * 11454 * @type string 11455 * @default Showing _START_ to _END_ of _TOTAL_ entries 11456 * 11457 * @dtopt Language 11458 * @name DataTable.defaults.language.info 11459 * 11460 * @example 11461 * $(document).ready( function() { 11462 * $('#example').dataTable( { 11463 * "language": { 11464 * "info": "Showing page _PAGE_ of _PAGES_" 11465 * } 11466 * } ); 11467 * } ); 11468 */ 11469 "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries", 11470 11471 11472 /** 11473 * Display information string for when the table is empty. Typically the 11474 * format of this string should match `info`. 11475 * @type string 11476 * @default Showing 0 to 0 of 0 entries 11477 * 11478 * @dtopt Language 11479 * @name DataTable.defaults.language.infoEmpty 11480 * 11481 * @example 11482 * $(document).ready( function() { 11483 * $('#example').dataTable( { 11484 * "language": { 11485 * "infoEmpty": "No entries to show" 11486 * } 11487 * } ); 11488 * } ); 11489 */ 11490 "sInfoEmpty": "Showing 0 to 0 of 0 entries", 11491 11492 11493 /** 11494 * When a user filters the information in a table, this string is appended 11495 * to the information (`info`) to give an idea of how strong the filtering 11496 * is. The variable _MAX_ is dynamically updated. 11497 * @type string 11498 * @default (filtered from _MAX_ total entries) 11499 * 11500 * @dtopt Language 11501 * @name DataTable.defaults.language.infoFiltered 11502 * 11503 * @example 11504 * $(document).ready( function() { 11505 * $('#example').dataTable( { 11506 * "language": { 11507 * "infoFiltered": " - filtering from _MAX_ records" 11508 * } 11509 * } ); 11510 * } ); 11511 */ 11512 "sInfoFiltered": "(filtered from _MAX_ total entries)", 11513 11514 11515 /** 11516 * If can be useful to append extra information to the info string at times, 11517 * and this variable does exactly that. This information will be appended to 11518 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are 11519 * being used) at all times. 11520 * @type string 11521 * @default <i>Empty string</i> 11522 * 11523 * @dtopt Language 11524 * @name DataTable.defaults.language.infoPostFix 11525 * 11526 * @example 11527 * $(document).ready( function() { 11528 * $('#example').dataTable( { 11529 * "language": { 11530 * "infoPostFix": "All records shown are derived from real information." 11531 * } 11532 * } ); 11533 * } ); 11534 */ 11535 "sInfoPostFix": "", 11536 11537 11538 /** 11539 * This decimal place operator is a little different from the other 11540 * language options since DataTables doesn't output floating point 11541 * numbers, so it won't ever use this for display of a number. Rather, 11542 * what this parameter does is modify the sort methods of the table so 11543 * that numbers which are in a format which has a character other than 11544 * a period (`.`) as a decimal place will be sorted numerically. 11545 * 11546 * Note that numbers with different decimal places cannot be shown in 11547 * the same table and still be sortable, the table must be consistent. 11548 * However, multiple different tables on the page can use different 11549 * decimal place characters. 11550 * @type string 11551 * @default 11552 * 11553 * @dtopt Language 11554 * @name DataTable.defaults.language.decimal 11555 * 11556 * @example 11557 * $(document).ready( function() { 11558 * $('#example').dataTable( { 11559 * "language": { 11560 * "decimal": "," 11561 * "thousands": "." 11562 * } 11563 * } ); 11564 * } ); 11565 */ 11566 "sDecimal": "", 11567 11568 11569 /** 11570 * DataTables has a build in number formatter (`formatNumber`) which is 11571 * used to format large numbers that are used in the table information. 11572 * By default a comma is used, but this can be trivially changed to any 11573 * character you wish with this parameter. 11574 * @type string 11575 * @default , 11576 * 11577 * @dtopt Language 11578 * @name DataTable.defaults.language.thousands 11579 * 11580 * @example 11581 * $(document).ready( function() { 11582 * $('#example').dataTable( { 11583 * "language": { 11584 * "thousands": "'" 11585 * } 11586 * } ); 11587 * } ); 11588 */ 11589 "sThousands": ",", 11590 11591 11592 /** 11593 * Detail the action that will be taken when the drop down menu for the 11594 * pagination length option is changed. The '_MENU_' variable is replaced 11595 * with a default select list of 10, 25, 50 and 100, and can be replaced 11596 * with a custom select box if required. 11597 * @type string 11598 * @default Show _MENU_ entries 11599 * 11600 * @dtopt Language 11601 * @name DataTable.defaults.language.lengthMenu 11602 * 11603 * @example 11604 * // Language change only 11605 * $(document).ready( function() { 11606 * $('#example').dataTable( { 11607 * "language": { 11608 * "lengthMenu": "Display _MENU_ records" 11609 * } 11610 * } ); 11611 * } ); 11612 * 11613 * @example 11614 * // Language and options change 11615 * $(document).ready( function() { 11616 * $('#example').dataTable( { 11617 * "language": { 11618 * "lengthMenu": 'Display <select>'+ 11619 * '<option value="10">10</option>'+ 11620 * '<option value="20">20</option>'+ 11621 * '<option value="30">30</option>'+ 11622 * '<option value="40">40</option>'+ 11623 * '<option value="50">50</option>'+ 11624 * '<option value="-1">All</option>'+ 11625 * '</select> records' 11626 * } 11627 * } ); 11628 * } ); 11629 */ 11630 "sLengthMenu": "Show _MENU_ entries", 11631 11632 11633 /** 11634 * When using Ajax sourced data and during the first draw when DataTables is 11635 * gathering the data, this message is shown in an empty row in the table to 11636 * indicate to the end user the the data is being loaded. Note that this 11637 * parameter is not used when loading data by server-side processing, just 11638 * Ajax sourced data with client-side processing. 11639 * @type string 11640 * @default Loading... 11641 * 11642 * @dtopt Language 11643 * @name DataTable.defaults.language.loadingRecords 11644 * 11645 * @example 11646 * $(document).ready( function() { 11647 * $('#example').dataTable( { 11648 * "language": { 11649 * "loadingRecords": "Please wait - loading..." 11650 * } 11651 * } ); 11652 * } ); 11653 */ 11654 "sLoadingRecords": "Loading...", 11655 11656 11657 /** 11658 * Text which is displayed when the table is processing a user action 11659 * (usually a sort command or similar). 11660 * @type string 11661 *
11661 @default Processing... 11662 * 11663 * @dtopt Language 11664 * @name DataTable.defaults.language.processing 11665 * 11666 * @example 11667 * $(document).ready( function() { 11668 * $('#example').dataTable( { 11669 * "language": { 11670 * "processing": "DataTables is currently busy" 11671 * } 11672 * } ); 11673 * } ); 11674 */ 11675 "sProcessing": "Processing...
vendor: 42,942 bytes, lines 11675-12969
11675", 11676 11677 11678 /** 11679 * Details the actions that will be taken when the user types into the 11680 * filtering input text box. The variable "_INPUT_", if used in the string, 11681 * is replaced with the HTML text box for the filtering input allowing 11682 * control over where it appears in the string. If "_INPUT_" is not given 11683 * then the input box is appended to the string automatically. 11684 * @type string 11685 * @default Search: 11686 * 11687 * @dtopt Language 11688 * @name DataTable.defaults.language.search 11689 * 11690 * @example 11691 * // Input text box will be appended at the end automatically 11692 * $(document).ready( function() { 11693 * $('#example').dataTable( { 11694 * "language": { 11695 * "search": "Filter records:" 11696 * } 11697 * } ); 11698 * } ); 11699 * 11700 * @example 11701 * // Specify where the filter should appear 11702 * $(document).ready( function() { 11703 * $('#example').dataTable( { 11704 * "language": { 11705 * "search": "Apply filter _INPUT_ to table" 11706 * } 11707 * } ); 11708 * } ); 11709 */ 11710 "sSearch": "Search:", 11711 11712 11713 /** 11714 * Assign a `placeholder` attribute to the search `input` element 11715 * @type string 11716 * @default 11717 * 11718 * @dtopt Language 11719 * @name DataTable.defaults.language.searchPlaceholder 11720 */ 11721 "sSearchPlaceholder": "", 11722 11723 11724 /** 11725 * All of the language information can be stored in a file on the 11726 * server-side, which DataTables will look up if this parameter is passed. 11727 * It must store the URL of the language file, which is in a JSON format, 11728 * and the object has the same properties as the oLanguage object in the 11729 * initialiser object (i.e. the above parameters). Please refer to one of 11730 * the example language files to see how this works in action. 11731 * @type string 11732 * @default <i>Empty string - i.e. disabled</i> 11733 * 11734 * @dtopt Language 11735 * @name DataTable.defaults.language.url 11736 * 11737 * @example 11738 * $(document).ready( function() { 11739 * $('#example').dataTable( { 11740 * "language": { 11741 * "url": "http://www.sprymedia.co.uk/dataTables/lang.txt" 11742 * } 11743 * } ); 11744 * } ); 11745 */ 11746 "sUrl": "", 11747 11748 11749 /** 11750 * Text shown inside the table records when the is no information to be 11751 * displayed after filtering. `emptyTable` is shown when there is simply no 11752 * information in the table at all (regardless of filtering). 11753 * @type string 11754 * @default No matching records found 11755 * 11756 * @dtopt Language 11757 * @name DataTable.defaults.language.zeroRecords 11758 * 11759 * @example 11760 * $(document).ready( function() { 11761 * $('#example').dataTable( { 11762 * "language": { 11763 * "zeroRecords": "No records to display" 11764 * } 11765 * } ); 11766 * } ); 11767 */ 11768 "sZeroRecords": "No matching records found" 11769 }, 11770 11771 11772 /** 11773 * This parameter allows you to have define the global filtering state at 11774 * initialisation time. As an object the `search` parameter must be 11775 * defined, but all other parameters are optional. When `regex` is true, 11776 * the search string will be treated as a regular expression, when false 11777 * (default) it will be treated as a straight string. When `smart` 11778 * DataTables will use it's smart filtering methods (to word match at 11779 * any point in the data), when false this will not be done. 11780 * @namespace 11781 * @extends DataTable.models.oSearch 11782 * 11783 * @dtopt Options 11784 * @name DataTable.defaults.search 11785 * 11786 * @example 11787 * $(document).ready( function() { 11788 * $('#example').dataTable( { 11789 * "search": {"search": "Initial search"} 11790 * } ); 11791 * } ) 11792 */ 11793 "oSearch": $.extend( {}, DataTable.models.oSearch ), 11794 11795 11796 /** 11797 * __Deprecated__ The functionality provided by this parameter has now been 11798 * superseded by that provided through `ajax`, which should be used instead. 11799 * 11800 * By default DataTables will look for the property `data` (or `aaData` for 11801 * compatibility with DataTables 1.9-) when obtaining data from an Ajax 11802 * source or for server-side processing - this parameter allows that 11803 * property to be changed. You can use Javascript dotted object notation to 11804 * get a data source for multiple levels of nesting. 11805 * @type string 11806 * @default data 11807 * 11808 * @dtopt Options 11809 * @dtopt Server-side 11810 * @name DataTable.defaults.ajaxDataProp 11811 * 11812 * @deprecated 1.10. Please use `ajax` for this functionality now. 11813 */ 11814 "sAjaxDataProp": "data", 11815 11816 11817 /** 11818 * __Deprecated__ The functionality provided by this parameter has now been 11819 * superseded by that provided through `ajax`, which should be used instead. 11820 * 11821 * You can instruct DataTables to load data from an external 11822 * source using this parameter (use aData if you want to pass data in you 11823 * already have). Simply provide a url a JSON object can be obtained from. 11824 * @type string 11825 * @default null 11826 * 11827 * @dtopt Options 11828 * @dtopt Server-side 11829 * @name DataTable.defaults.ajaxSource 11830 * 11831 * @deprecated 1.10. Please use `ajax` for this functionality now. 11832 */ 11833 "sAjaxSource": null, 11834 11835 11836 /** 11837 * This initialisation variable allows you to specify exactly where in the 11838 * DOM you want DataTables to inject the various controls it adds to the page 11839 * (for example you might want the pagination controls at the top of the 11840 * table). DIV elements (with or without a custom class) can also be added to 11841 * aid styling. The follow syntax is used: 11842 * <ul> 11843 * <li>The following options are allowed: 11844 * <ul> 11845 * <li>'l' - Length changing</li> 11846 * <li>'f' - Filtering input</li> 11847 * <li>'t' - The table!</li> 11848 * <li>'i' - Information</li> 11849 * <li>'p' - Pagination</li> 11850 * <li>'r' - pRocessing</li> 11851 * </ul> 11852 * </li> 11853 * <li>The following constants are allowed: 11854 * <ul> 11855 * <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li> 11856 * <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li> 11857 * </ul> 11858 * </li> 11859 * <li>The following syntax is expected: 11860 * <ul> 11861 * <li>'<' and '>' - div elements</li> 11862 * <li>'<"class" and '>' - div with a class</li> 11863 * <li>'<"#id" and '>' - div with an ID</li> 11864 * </ul> 11865 * </li> 11866 * <li>Examples: 11867 * <ul> 11868 * <li>'<"wrapper"flipt>'</li> 11869 * <li>'<lf<t>ip>'</li> 11870 * </ul> 11871 * </li> 11872 * </ul> 11873 * @type string 11874 * @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b> 11875 * <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i> 11876 * 11877 * @dtopt Options 11878 * @name DataTable.defaults.dom 11879 * 11880 * @example 11881 * $(document).ready( function() { 11882 * $('#example').dataTable( { 11883 * "dom": '<"top"i>rt<"bottom"flp><"clear">' 11884 * } ); 11885 * } ); 11886 */ 11887 "sDom": "lfrtip", 11888 11889 11890 /** 11891 * Search delay option. This will throttle full table searches that use the 11892 * DataTables provided search input element (it does not effect calls to 11893 * `dt-api search()`, providing a delay before the search is made. 11894 * @type integer 11895 * @default 0 11896 * 11897 * @dtopt Options 11898 * @name DataTable.defaults.searchDelay 11899 * 11900 * @example 11901 * $(document).ready( function() { 11902 * $('#example').dataTable( { 11903 * "searchDelay": 200 11904 * } ); 11905 * } ) 11906 */ 11907 "searchDelay": null, 11908 11909 11910 /** 11911 * DataTables features six different built-in options for the buttons to 11912 * display for pagination control: 11913 * 11914 * * `numbers` - Page number buttons only 11915 * * `simple` - 'Previous' and 'Next' buttons only 11916 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers 11917 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons 11918 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers 11919 * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers 11920 * 11921 * Further methods can be added using {@link DataTable.ext.oPagination}. 11922 * @type string 11923 * @default simple_numbers 11924 * 11925 * @dtopt Options 11926 * @name DataTable.defaults.pagingType 11927 * 11928 * @example 11929 * $(document).ready( function() { 11930 * $('#example').dataTable( { 11931 * "pagingType": "full_numbers" 11932 * } ); 11933 * } ) 11934 */ 11935 "sPaginationType": "simple_numbers", 11936 11937 11938 /** 11939 * Enable horizontal scrolling. When a table is too wide to fit into a 11940 * certain layout, or you have a large number of columns in the table, you 11941 * can enable x-scrolling to show the table in a viewport, which can be 11942 * scrolled. This property can be `true` which will allow the table to 11943 * scroll horizontally when needed, or any CSS unit, or a number (in which 11944 * case it will be treated as a pixel measurement). Setting as simply `true` 11945 * is recommended. 11946 * @type boolean|string 11947 * @default <i>blank string - i.e. disabled</i> 11948 * 11949 * @dtopt Features 11950 * @name DataTable.defaults.scrollX 11951 * 11952 * @example 11953 * $(document).ready( function() { 11954 * $('#example').dataTable( { 11955 * "scrollX": true, 11956 * "scrollCollapse": true 11957 * } ); 11958 * } ); 11959 */ 11960 "sScrollX": "", 11961 11962 11963 /** 11964 * This property can be used to force a DataTable to use more width than it 11965 * might otherwise do when x-scrolling is enabled. For example if you have a 11966 * table which requires to be well spaced, this parameter is useful for 11967 * "over-sizing" the table, and thus forcing scrolling. This property can by 11968 * any CSS unit, or a number (in which case it will be treated as a pixel 11969 * measurement). 11970 * @type string 11971 * @default <i>blank string - i.e. disabled</i> 11972 * 11973 * @dtopt Options 11974 * @name DataTable.defaults.scrollXInner 11975 * 11976 * @example 11977 * $(document).ready( function() { 11978 * $('#example').dataTable( { 11979 * "scrollX": "100%", 11980 * "scrollXInner": "110%" 11981 * } ); 11982 * } ); 11983 */ 11984 "sScrollXInner": "", 11985 11986 11987 /** 11988 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable 11989 * to the given height, and enable scrolling for any data which overflows the 11990 * current viewport. This can be used as an alternative to paging to display 11991 * a lot of data in a small area (although paging and scrolling can both be 11992 * enabled at the same time). This property can be any CSS unit, or a number 11993 * (in which case it will be treated as a pixel measurement). 11994 * @type string 11995 * @default <i>blank string - i.e. disabled</i> 11996 * 11997 * @dtopt Features 11998 * @name DataTable.defaults.scrollY 11999 * 12000 * @example 12001 * $(document).ready( function() { 12002 * $('#example').dataTable( { 12003 * "scrollY": "200px", 12004 * "paginate": false 12005 * } ); 12006 * } ); 12007 */ 12008 "sScrollY": "", 12009 12010 12011 /** 12012 * __Deprecated__ The functionality provided by this parameter has now been 12013 * superseded by that provided through `ajax`, which should be used instead. 12014 * 12015 * Set the HTTP method that is used to make the Ajax call for server-side 12016 * processing or Ajax sourced data. 12017 * @type string 12018 * @default GET 12019 * 12020 * @dtopt Options 12021 * @dtopt Server-side 12022 * @name DataTable.defaults.serverMethod 12023 * 12024 * @deprecated 1.10. Please use `ajax` for this functionality now. 12025 */ 12026 "sServerMethod": "GET", 12027 12028 12029 /** 12030 * DataTables makes use of renderers when displaying HTML elements for 12031 * a table. These renderers can be added or modified by plug-ins to 12032 * generate suitable mark-up for a site. For example the Bootstrap 12033 * integration plug-in for DataTables uses a paging button renderer to 12034 * display pagination buttons in the mark-up required by Bootstrap. 12035 * 12036 * For further information about the renderers available see 12037 * DataTable.ext.renderer 12038 * @type string|object 12039 * @default null 12040 * 12041 * @name DataTable.defaults.renderer 12042 * 12043 */ 12044 "renderer": null, 12045 12046 12047 /** 12048 * Set the data property name that DataTables should use to get a row's id 12049 * to set as the `id` property in the node. 12050 * @type string 12051 * @default DT_RowId 12052 * 12053 * @name DataTable.defaults.rowId 12054 */ 12055 "rowId": "DT_RowId" 12056 }; 12057 12058 _fnHungarianMap( DataTable.defaults ); 12059 12060 12061 12062 /* 12063 * Developer note - See note in model.defaults.js about the use of Hungarian 12064 * notation and camel case. 12065 */ 12066 12067 /** 12068 * Column options that can be given to DataTables at initialisation time. 12069 * @namespace 12070 */ 12071 DataTable.defaults.column = { 12072 /** 12073 * Define which column(s) an order will occur on for this column. This 12074 * allows a column's ordering to take multiple columns into account when 12075 * doing a sort or use the data from a different column. For example first 12076 * name / last name columns make sense to do a multi-column sort over the 12077 * two columns. 12078 * @type array|int 12079 * @default null <i>Takes the value of the column index automatically</i> 12080 * 12081 * @name DataTable.defaults.column.orderData 12082 * @dtopt Columns 12083 * 12084 * @example 12085 * // Using `columnDefs` 12086 * $(document).ready( function() { 12087 * $('#example').dataTable( { 12088 * "columnDefs": [ 12089 * { "orderData": [ 0, 1 ], "targets": [ 0 ] }, 12090 * { "orderData": [ 1, 0 ], "targets": [ 1 ] }, 12091 * { "orderData": 2, "targets": [ 2 ] } 12092 * ] 12093 * } ); 12094 * } ); 12095 * 12096 * @example 12097 * // Using `columns` 12098 * $(document).ready( function() { 12099 * $('#example').dataTable( { 12100 * "columns": [ 12101 * { "orderData": [ 0, 1 ] }, 12102 * { "orderData": [ 1, 0 ] }, 12103 * { "orderData": 2 }, 12104 * null, 12105 * null 12106 * ] 12107 * } ); 12108 * } ); 12109 */ 12110 "aDataSort": null, 12111 "iDataSort": -1, 12112 12113 12114 /** 12115 * You can control the default ordering direction, and even alter the 12116 * behaviour of the sort handler (i.e. only allow ascending ordering etc) 12117 * using this parameter. 12118 * @type array 12119 * @default [ 'asc', 'desc' ] 12120 * 12121 * @name DataTable.defaults.column.orderSequence 12122 * @dtopt Columns 12123 * 12124 * @example 12125 * // Using `columnDefs` 12126 * $(document).ready( function() { 12127 * $('#example').dataTable( { 12128 * "columnDefs": [ 12129 * { "orderSequence": [ "asc" ], "targets": [ 1 ] }, 12130 * { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] }, 12131 * { "orderSequence": [ "desc" ], "targets": [ 3 ] } 12132 * ] 12133 * } ); 12134 * } ); 12135 * 12136 * @example 12137 * // Using `columns` 12138 * $(document).ready( function() { 12139 * $('#example').dataTable( { 12140 * "columns": [ 12141 * null, 12142 * { "orderSequence": [ "asc" ] }, 12143 * { "orderSequence": [ "desc", "asc", "asc" ] }, 12144 * { "orderSequence": [ "desc" ] }, 12145 * null 12146 * ] 12147 * } ); 12148 * } ); 12149 */ 12150 "asSorting": [ 'asc', 'desc' ], 12151 12152 12153 /** 12154 * Enable or disable filtering on the data in this column. 12155 * @type boolean 12156 * @default true 12157 * 12158 * @name DataTable.defaults.column.searchable 12159 * @dtopt Columns 12160 * 12161 * @example 12162 * // Using `columnDefs` 12163 * $(document).ready( function() { 12164 * $('#example').dataTable( { 12165 * "columnDefs": [ 12166 * { "searchable": false, "targets": [ 0 ] } 12167 * ] } ); 12168 * } ); 12169 * 12170 * @example 12171 * // Using `columns` 12172 * $(document).ready( function() { 12173 * $('#example').dataTable( { 12174 * "columns": [ 12175 * { "searchable": false }, 12176 * null, 12177 * null, 12178 * null, 12179 * null 12180 * ] } ); 12181 * } ); 12182 */ 12183 "bSearchable": true, 12184 12185 12186 /** 12187 * Enable or disable ordering on this column. 12188 * @type boolean 12189 * @default true 12190 * 12191 * @name DataTable.defaults.column.orderable 12192 * @dtopt Columns 12193 * 12194 * @example 12195 * // Using `columnDefs` 12196 * $(document).ready( function() { 12197 * $('#example').dataTable( { 12198 * "columnDefs": [ 12199 * { "orderable": false, "targets": [ 0 ] } 12200 * ] } ); 12201 * } ); 12202 * 12203 * @example 12204 * // Using `columns` 12205 * $(document).ready( function() { 12206 * $('#example').dataTable( { 12207 * "columns": [ 12208 * { "orderable": false }, 12209 * null, 12210 * null, 12211 * null, 12212 * null 12213 * ] } ); 12214 * } ); 12215 */ 12216 "bSortable": true, 12217 12218 12219 /** 12220 * Enable or disable the display of this column. 12221 * @type boolean 12222 * @default true 12223 * 12224 * @name DataTable.defaults.column.visible 12225 * @dtopt Columns 12226 * 12227 * @example 12228 * // Using `columnDefs` 12229 * $(document).ready( function() { 12230 * $('#example').dataTable( { 12231 * "columnDefs": [ 12232 * { "visible": false, "targets": [ 0 ] } 12233 * ] } ); 12234 * } ); 12235 * 12236 * @example 12237 * // Using `columns` 12238 * $(document).ready( function() { 12239 * $('#example').dataTable( { 12240 * "columns": [ 12241 * { "visible": false }, 12242 * null, 12243 * null, 12244 * null, 12245 * null 12246 * ] } ); 12247 * } ); 12248 */ 12249 "bVisible": true, 12250 12251 12252 /** 12253 * Developer definable function that is called whenever a cell is created (Ajax source, 12254 * etc) or processed for input (DOM source). This can be used as a compliment to mRender 12255 * allowing you to modify the DOM element (add background colour for example) when the 12256 * element is available. 12257 * @type function 12258 * @param {element} td The TD node that has been created 12259 * @param {*} cellData The Data for the cell 12260 * @param {array|object} rowData The data for the whole row 12261 * @param {int} row The row index for the aoData data store 12262 * @param {int} col The column index for aoColumns 12263 * 12264 * @name DataTable.defaults.column.createdCell 12265 * @dtopt Columns 12266 * 12267 * @example 12268 * $(document).ready( function() { 12269 * $('#example').dataTable( { 12270 * "columnDefs": [ { 12271 * "targets": [3], 12272 * "createdCell": function (td, cellData, rowData, row, col) { 12273 * if ( cellData == "1.7" ) { 12274 * $(td).css('color', 'blue') 12275 * } 12276 * } 12277 * } ] 12278 * }); 12279 * } ); 12280 */ 12281 "fnCreatedCell": null, 12282 12283 12284 /** 12285 * This parameter has been replaced by `data` in DataTables to ensure naming 12286 * consistency. `dataProp` can still be used, as there is backwards 12287 * compatibility in DataTables for this option, but it is strongly 12288 * recommended that you use `data` in preference to `dataProp`. 12289 * @name DataTable.defaults.column.dataProp 12290 */ 12291 12292 12293 /** 12294 * This property can be used to read data from any data source property, 12295 * including deeply nested objects / properties. `data` can be given in a 12296 * number of different ways which effect its behaviour: 12297 * 12298 * * `integer` - treated as an array index for the data source. This is the 12299 * default that DataTables uses (incrementally increased for each column). 12300 * * `string` - read an object property from the data source. There are 12301 * three 'special' options that can be used in the string to alter how 12302 * DataTables reads the data from the source object: 12303 * * `.` - Dotted Javascript notation. Just as you use a `.` in 12304 * Javascript to read from nested objects, so to can the options 12305 * specified in `data`. For example: `browser.version` or 12306 * `browser.name`. If your object parameter name contains a period, use 12307 * `\\` to escape it - i.e. `first\\.name`. 12308 * * `[]` - Array notation. DataTables can automatically combine data 12309 * from and array source, joining the data with the characters provided 12310 * between the two brackets. For example: `name[, ]` would provide a 12311 * comma-space separated list from the source array. If no characters 12312 * are provided between the brackets, the original array source is 12313 * returned. 12314 * * `()` - Function notation. Adding `()` to the end of a parameter will 12315 * execute a function of the name given. For example: `browser()` for a 12316 * simple function on the data source, `browser.version()` for a 12317 * function in a nested property or even `browser().version` to get an 12318 * object property if the function called returns an object. Note that 12319 * function notation is recommended for use in `render` rather than 12320 * `data` as it is much simpler to use as a renderer. 12321 * * `null` - use the original data source for the row rather than plucking 12322 * data directly from it. This action has effects on two other 12323 * initialisation options: 12324 * * `defaultContent` - When null is given as the `data` option and 12325 * `defaultContent` is specified for the column, the value defined by 12326 * `defaultContent` will be used for the cell. 12327 * * `render` - When null is used for the `data` option and the `render` 12328 * option is specified for the column, the whole data source for the 12329 * row is used for the renderer. 12330 * * `function` - the function given will be executed whenever DataTables 12331 * needs to set or get the data for a cell in the column. The function 12332 * takes three parameters: 12333 * * Parameters: 12334 * * `{array|object}` The data source for the row 12335 * * `{string}` The type call data requested - this will be 'set' when 12336 * setting data or 'filter', 'display', 'type', 'sort' or undefined 12337 * when gathering data. Note that when `undefined` is given for the 12338 * type DataTables expects to get the raw data for the object back< 12339 * * `{*}` Data to set when the second parameter is 'set'. 12340 * * Return: 12341 * * The return value from the function is not required when 'set' is 12342 * the type of call, but otherwise the return is what will be used 12343 * for the data requested. 12344 * 12345 * Note that `data` is a getter and setter option. If you just require 12346 * formatting of data for output, you will likely want to use `render` which 12347 * is simply a getter and thus simpler to use. 12348 * 12349 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The 12350 * name change reflects the flexibility of this property and is consistent 12351 * with the naming of mRender. If 'mDataProp' is given, then it will still 12352 * be used by DataTables, as it automatically maps the old name to the new 12353 * if required. 12354 * 12355 * @type string|int|function|null 12356 * @default null <i>Use automatically calculated column index</i> 12357 * 12358 * @name DataTable.defaults.column.data 12359 * @dtopt Columns 12360 * 12361 * @example 12362 * // Read table data from objects 12363 * // JSON structure for each row: 12364 * // { 12365 * // "engine": {value}, 12366 * // "browser": {value}, 12367 * // "platform": {value}, 12368 * // "version": {value}, 12369 * // "grade": {value} 12370 * // } 12371 * $(document).ready( function() { 12372 * $('#example').dataTable( { 12373 * "ajaxSource": "sources/objects.txt", 12374 * "columns": [ 12375 * { "data": "engine" }, 12376 * { "data": "browser" }, 12377 * { "data": "platform" }, 12378 * { "data": "version" }, 12379 * { "data": "grade" } 12380 * ] 12381 * } ); 12382 * } ); 12383 * 12384 * @example 12385 * // Read information from deeply nested objects 12386 * // JSON structure for each row: 12387 * // { 12388 * // "engine": {value}, 12389 * // "browser": {value}, 12390 * // "platform": { 12391 * // "inner": {value} 12392 * // }, 12393 * // "details": [ 12394 * // {value}, {value} 12395 * // ] 12396 * // } 12397 * $(document).ready( function() { 12398 * $('#example').dataTable( { 12399 * "ajaxSource": "sources/deep.txt", 12400 * "columns": [ 12401 * { "data": "engine" }, 12402 * { "data": "browser" }, 12403 * { "data": "platform.inner" }, 12404 * { "data": "details.0" }, 12405 * { "data": "details.1" } 12406 * ] 12407 * } ); 12408 * } ); 12409 * 12410 * @example 12411 * // Using `data` as a function to provide different information for 12412 * // sorting, filtering and display. In this case, currency (price) 12413 * $(document).ready( function() { 12414 * $('#example').dataTable( { 12415 * "columnDefs": [ { 12416 * "targets": [ 0 ], 12417 * "data": function ( source, type, val ) { 12418 * if (type === 'set') { 12419 * source.price = val; 12420 * // Store the computed dislay and filter values for efficiency 12421 * source.price_display = val=="" ? "" : "$"+numberFormat(val); 12422 * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val; 12423 * return; 12424 * } 12425 * else if (type === 'display') { 12426 * return source.price_display; 12427 * } 12428 * else if (type === 'filter') { 12429 * return source.price_filter; 12430 * } 12431 * // 'sort', 'type' and undefined all just use the integer 12432 * return source.price; 12433 * } 12434 * } ] 12435 * } ); 12436 * } ); 12437 * 12438 * @example 12439 * // Using default content 12440 * $(document).ready( function() { 12441 * $('#example').dataTable( { 12442 * "columnDefs": [ { 12443 * "targets": [ 0 ], 12444 * "data": null, 12445 * "defaultContent": "Click to edit" 12446 * } ] 12447 * } ); 12448 * } ); 12449 * 12450 * @example 12451 * // Using array notation - outputting a list from an array 12452 * $(document).ready( function() { 12453 * $('#example').dataTable( { 12454 * "columnDefs": [ { 12455 * "targets": [ 0 ], 12456 * "data": "name[, ]" 12457 * } ] 12458 * } ); 12459 * } ); 12460 * 12461 */ 12462 "mData": null, 12463 12464 12465 /** 12466 * This property is the rendering partner to `data` and it is suggested that 12467 * when you want to manipulate data for display (including filtering, 12468 * sorting etc) without altering the underlying data for the table, use this 12469 * property. `render` can be considered to be the the read only companion to 12470 * `data` which is read / write (then as such more complex). Like `data` 12471 * this option can be given in a number of different ways to effect its 12472 * behaviour: 12473 * 12474 * * `integer` - treated as an array index for the data source. This is the 12475 * default that DataTables uses (incrementally increased for each column). 12476 * * `string` - read an object property from the data source. There are 12477 * three 'special' options that can be used in the string to alter how 12478 * DataTables reads the data from the source object: 12479 * * `.` - Dotted Javascript notation. Just as you use a `.` in 12480 * Javascript to read from nested objects, so to can the options 12481 * specified in `data`. For example: `browser.version` or 12482 * `browser.name`. If your object parameter name contains a period, use 12483 * `\\` to escape it - i.e. `first\\.name`. 12484 * * `[]` - Array notation. DataTables can automatically combine data 12485 * from and array source, joining the data with the characters provided 12486 * between the two brackets. For example: `name[, ]` would provide a 12487 * comma-space separated list from the source array. If no characters 12488 * are provided between the brackets, the original array source is 12489 * returned. 12490 * * `()` - Function notation. Adding `()` to the end of a parameter will 12491 * execute a function of the name given. For example: `browser()` for a 12492 * simple function on the data source, `browser.version()` for a 12493 * function in a nested property or even `browser().version` to get an 12494 * object property if the function called returns an object. 12495 * * `object` - use different data for the different data types requested by 12496 * DataTables ('filter', 'display', 'type' or 'sort'). The property names 12497 * of the object is the data type the property refers to and the value can 12498 * defined using an integer, string or function using the same rules as 12499 * `render` normally does. Note that an `_` option _must_ be specified. 12500 * This is the default value to use if you haven't specified a value for 12501 * the data type requested by DataTables. 12502 * * `function` - the function given will be executed whenever DataTables 12503 * needs to set or get the data for a cell in the column. The function 12504 * takes three parameters: 12505 * * Parameters: 12506 * * {array|object} The data source for the row (based on `data`) 12507 * * {string} The type call data requested - this will be 'filter', 12508 * 'display', 'type' or 'sort'. 12509 * * {array|object} The full data source for the row (not based on 12510 * `data`) 12511 * * Return: 12512 * * The return value from the function is what will be used for the 12513 * data requested. 12514 * 12515 * @type string|int|function|object|null 12516 * @default null Use the data source value. 12517 * 12518 * @name DataTable.defaults.column.render 12519 * @dtopt Columns 12520 * 12521 * @example 12522 * // Create a comma separated list from an array of objects 12523 * $(document).ready( function() { 12524 * $('#example').dataTable( { 12525 * "ajaxSource": "sources/deep.txt", 12526 * "columns": [ 12527 * { "data": "engine" }, 12528 * { "data": "browser" }, 12529 * { 12530 * "data": "platform", 12531 * "render": "[, ].name" 12532 * } 12533 * ] 12534 * } ); 12535 * } ); 12536 * 12537 * @example 12538 * // Execute a function to obtain data 12539 * $(document).ready( function() { 12540 * $('#example').dataTable( { 12541 * "columnDefs": [ { 12542 * "targets": [ 0 ], 12543 * "data": null, // Use the full data source object for the renderer's source 12544 * "render": "browserName()" 12545 * } ] 12546 * } ); 12547 * } ); 12548 * 12549 * @example 12550 * // As an object, extracting different data for the different types 12551 * // This would be used with a data source such as: 12552 * // { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" } 12553 * // Here the `phone` integer is used for sorting and type detection, while `phone_filter` 12554 * // (which has both forms) is used for filtering for if a user inputs either format, while 12555 * // the formatted phone number is the one that is shown in the table. 12556 * $(document).ready( function() { 12557 * $('#example').dataTable( { 12558 * "columnDefs": [ { 12559 * "targets": [ 0 ], 12560 * "data": null, // Use the full data source object for the renderer's source 12561 * "render": { 12562 * "_": "phone", 12563 * "filter": "phone_filter", 12564 * "display": "phone_display" 12565 * } 12566 * } ] 12567 * } ); 12568 * } ); 12569 * 12570 * @example 12571 * // Use as a function to create a link from the data source 12572 * $(document).ready( function() { 12573 * $('#example').dataTable( { 12574 * "columnDefs": [ { 12575 * "targets": [ 0 ], 12576 * "data": "download_link", 12577 * "render": function ( data, type, full ) { 12578 * return '<a href="'+data+'">Download</a>'; 12579 * } 12580 * } ] 12581 * } ); 12582 * } ); 12583 */ 12584 "mRender": null, 12585 12586 12587 /** 12588 * Change the cell type created for the column - either TD cells or TH cells. This 12589 * can be useful as TH cells have semantic meaning in the table body, allowing them 12590 * to act as a header for a row (you may wish to add scope='row' to the TH elements). 12591 * @type string 12592 * @default td 12593 * 12594 * @name DataTable.defaults.column.cellType 12595 * @dtopt Columns 12596 * 12597 * @example 12598 * // Make the first column use TH cells 12599 * $(document).ready( function() { 12600 * $('#example').dataTable( { 12601 * "columnDefs": [ { 12602 * "targets": [ 0 ], 12603 * "cellType": "th" 12604 * } ] 12605 * } ); 12606 * } ); 12607 */ 12608 "sCellType": "td", 12609 12610 12611 /** 12612 * Class to give to each cell in this column. 12613 * @type string 12614 * @default <i>Empty string</i> 12615 * 12616 * @name DataTable.defaults.column.class 12617 * @dtopt Columns 12618 * 12619 * @example 12620 * // Using `columnDefs` 12621 * $(document).ready( function() { 12622 * $('#example').dataTable( { 12623 * "columnDefs": [ 12624 * { "class": "my_class", "targets": [ 0 ] } 12625 * ] 12626 * } ); 12627 * } ); 12628 * 12629 * @example 12630 * // Using `columns` 12631 * $(document).ready( function() { 12632 * $('#example').dataTable( { 12633 * "columns": [ 12634 * { "class": "my_class" }, 12635 * null, 12636 * null, 12637 * null, 12638 * null 12639 * ] 12640 * } ); 12641 * } ); 12642 */ 12643 "sClass": "", 12644 12645 /** 12646 * When DataTables calculates the column widths to assign to each column, 12647 * it finds the longest string in each column and then constructs a 12648 * temporary table and reads the widths from that. The problem with this 12649 * is that "mmm" is much wider then "iiii", but the latter is a longer 12650 * string - thus the calculation can go wrong (doing it properly and putting 12651 * it into an DOM object and measuring that is horribly(!) slow). Thus as 12652 * a "work around" we provide this option. It will append its value to the 12653 * text that is found to be the longest string for the column - i.e. padding. 12654 * Generally you shouldn't need this! 12655 * @type string 12656 * @default <i>Empty string<i> 12657 * 12658 * @name DataTable.defaults.column.contentPadding 12659 * @dtopt Columns 12660 * 12661 * @example 12662 * // Using `columns` 12663 * $(document).ready( function() { 12664 * $('#example').dataTable( { 12665 * "columns": [ 12666 * null, 12667 * null, 12668 * null, 12669 * { 12670 * "contentPadding": "mmm" 12671 * } 12672 * ] 12673 * } ); 12674 * } ); 12675 */ 12676 "sContentPadding": "", 12677 12678 12679 /** 12680 * Allows a default value to be given for a column's data, and will be used 12681 * whenever a null data source is encountered (this can be because `data` 12682 * is set to null, or because the data source itself is null). 12683 * @type string 12684 * @default null 12685 * 12686 * @name DataTable.defaults.column.defaultContent 12687 * @dtopt Columns 12688 * 12689 * @example 12690 * // Using `columnDefs` 12691 * $(document).ready( function() { 12692 * $('#example').dataTable( { 12693 * "columnDefs": [ 12694 * { 12695 * "data": null, 12696 * "defaultContent": "Edit", 12697 * "targets": [ -1 ] 12698 * } 12699 * ] 12700 * } ); 12701 * } ); 12702 * 12703 * @example 12704 * // Using `columns` 12705 * $(document).ready( function() { 12706 * $('#example').dataTable( { 12707 * "columns": [ 12708 * null, 12709 * null, 12710 * null, 12711 * { 12712 * "data": null, 12713 * "defaultContent": "Edit" 12714 * } 12715 * ] 12716 * } ); 12717 * } ); 12718 */ 12719 "sDefaultContent": null, 12720 12721 12722 /** 12723 * This parameter is only used in DataTables' server-side processing. It can 12724 * be exceptionally useful to know what columns are being displayed on the 12725 * client side, and to map these to database fields. When defined, the names 12726 * also allow DataTables to reorder information from the server if it comes 12727 * back in an unexpected order (i.e. if you switch your columns around on the 12728 * client-side, your server-side code does not also need updating). 12729 * @type string 12730 * @default <i>Empty string</i> 12731 * 12732 * @name DataTable.defaults.column.name 12733 * @dtopt Columns 12734 * 12735 * @example 12736 * // Using `columnDefs` 12737 * $(document).ready( function() { 12738 * $('#example').dataTable( { 12739 * "columnDefs": [ 12740 * { "name": "engine", "targets": [ 0 ] }, 12741 * { "name": "browser", "targets": [ 1 ] }, 12742 * { "name": "platform", "targets": [ 2 ] }, 12743 * { "name": "version", "targets": [ 3 ] }, 12744 * { "name": "grade", "targets": [ 4 ] } 12745 * ] 12746 * } ); 12747 * } ); 12748 * 12749 * @example 12750 * // Using `columns` 12751 * $(document).ready( function() { 12752 * $('#example').dataTable( { 12753 * "columns": [ 12754 * { "name": "engine" }, 12755 * { "name": "browser" }, 12756 * { "name": "platform" }, 12757 * { "name": "version" }, 12758 * { "name": "grade" } 12759 * ] 12760 * } ); 12761 * } ); 12762 */ 12763 "sName": "", 12764 12765 12766 /** 12767 * Defines a data source type for the ordering which can be used to read 12768 * real-time information from the table (updating the internally cached 12769 * version) prior to ordering. This allows ordering to occur on user 12770 * editable elements such as form inputs. 12771 * @type string 12772 * @default std 12773 * 12774 * @name DataTable.defaults.column.orderDataType 12775 * @dtopt Columns 12776 * 12777 * @example 12778 * // Using `columnDefs` 12779 * $(document).ready( function() { 12780 * $('#example').dataTable( { 12781 * "columnDefs": [ 12782 * { "orderDataType": "dom-text", "targets": [ 2, 3 ] }, 12783 * { "type": "numeric", "targets": [ 3 ] }, 12784 * { "orderDataType": "dom-select", "targets": [ 4 ] }, 12785 * { "orderDataType": "dom-checkbox", "targets": [ 5 ] } 12786 * ] 12787 * } ); 12788 * } ); 12789 * 12790 * @example 12791 * // Using `columns` 12792 * $(document).ready( function() { 12793 * $('#example').dataTable( { 12794 * "columns": [ 12795 * null, 12796 * null, 12797 * { "orderDataType": "dom-text" }, 12798 * { "orderDataType": "dom-text", "type": "numeric" }, 12799 * { "orderDataType": "dom-select" }, 12800 * { "orderDataType": "dom-checkbox" } 12801 * ] 12802 * } ); 12803 * } ); 12804 */ 12805 "sSortDataType": "std", 12806 12807 12808 /** 12809 * The title of this column. 12810 * @type string 12811 * @default null <i>Derived from the 'TH' value for this column in the 12812 * original HTML table.</i> 12813 * 12814 * @name DataTable.defaults.column.title 12815 * @dtopt Columns 12816 * 12817 * @example 12818 * // Using `columnDefs` 12819 * $(document).ready( function() { 12820 * $('#example').dataTable( { 12821 * "columnDefs": [ 12822 * { "title": "My column title", "targets": [ 0 ] } 12823 * ] 12824 * } ); 12825 * } ); 12826 * 12827 * @example 12828 * // Using `columns` 12829 * $(document).ready( function() { 12830 * $('#example').dataTable( { 12831 * "columns": [ 12832 * { "title": "My column title" }, 12833 * null, 12834 * null, 12835 * null, 12836 * null 12837 * ] 12838 * } ); 12839 * } ); 12840 */ 12841 "sTitle": null, 12842 12843 12844 /** 12845 * The type allows you to specify how the data for this column will be 12846 * ordered. Four types (string, numeric, date and html (which will strip 12847 * HTML tags before ordering)) are currently available. Note that only date 12848 * formats understood by Javascript's Date() object will be accepted as type 12849 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string', 12850 * 'numeric', 'date' or 'html' (by default). Further types can be adding 12851 * through plug-ins. 12852 * @type string 12853 * @default null <i>Auto-detected from raw data</i> 12854 * 12855 * @name DataTable.defaults.column.type 12856 * @dtopt Columns 12857 * 12858 * @example 12859 * // Using `columnDefs` 12860 * $(document).ready( function() { 12861 * $('#example').dataTable( { 12862 * "columnDefs": [ 12863 * { "type": "html", "targets": [ 0 ] } 12864 * ] 12865 * } ); 12866 * } ); 12867 * 12868 * @example 12869 * // Using `columns` 12870 * $(document).ready( function() { 12871 * $('#example').dataTable( { 12872 * "columns": [ 12873 * { "type": "html" }, 12874 * null, 12875 * null, 12876 * null, 12877 * null 12878 * ] 12879 * } ); 12880 * } ); 12881 */ 12882 "sType": null, 12883 12884 12885 /** 12886 * Defining the width of the column, this parameter may take any CSS value 12887 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not 12888 * been given a specific width through this interface ensuring that the table 12889 * remains readable. 12890 * @type string 12891 * @default null <i>Automatic</i> 12892 * 12893 * @name DataTable.defaults.column.width 12894 * @dtopt Columns 12895 * 12896 * @example 12897 * // Using `columnDefs` 12898 * $(document).ready( function() { 12899 * $('#example').dataTable( { 12900 * "columnDefs": [ 12901 * { "width": "20%", "targets": [ 0 ] } 12902 * ] 12903 * } ); 12904 * } ); 12905 * 12906 * @example 12907 * // Using `columns` 12908 * $(document).ready( function() { 12909 * $('#example').dataTable( { 12910 * "columns": [ 12911 * { "width": "20%" }, 12912 * null, 12913 * null, 12914 * null, 12915 * null 12916 * ] 12917 * } ); 12918 * } ); 12919 */ 12920 "sWidth": null 12921 }; 12922 12923 _fnHungarianMap( DataTable.defaults.column ); 12924 12925 12926 12927 /** 12928 * DataTables settings object - this holds all the information needed for a 12929 * given table, including configuration, data and current application of the 12930 * table options. DataTables does not have a single instance for each DataTable 12931 * with the settings attached to that instance, but rather instances of the 12932 * DataTable "class" are created on-the-fly as needed (typically by a 12933 * $().dataTable() call) and the settings object is then applied to that 12934 * instance. 12935 * 12936 * Note that this object is related to {@link DataTable.defaults} but this 12937 * one is the internal data store for DataTables's cache of columns. It should 12938 * NOT be manipulated outside of DataTables. Any configuration should be done 12939 * through the initialisation options. 12940 * @namespace 12941 * @todo Really should attach the settings object to individual instances so we 12942 * don't need to create new instances on each $().dataTable() call (if the 12943 * table already exists). It would also save passing oSettings around and 12944 * into every single function. However, this is a very significant 12945 * architecture change for DataTables and will almost certainly break 12946 * backwards compatibility with older installations. This is something that 12947 * will be done in 2.0. 12948 */ 12949 DataTable.models.oSettings = { 12950 /** 12951 * Primary features of DataTables and their enablement state. 12952 * @namespace 12953 */ 12954 "oFeatures": { 12955 12956 /** 12957 * Flag to say if DataTables should automatically try to calculate the 12958 * optimum table and columns widths (true) or not (false). 12959 * Note that this parameter will be set by the initialisation routine. To 12960 * set a default use {@link DataTable.defaults}. 12961 * @type boolean 12962 */ 12963 "bAutoWidth": null, 12964 12965 /** 12966 * Delay the creation of TR and TD elements until they are actually 12967 * needed by a driven page draw. This can give a significant speed 12968 * increase for Ajax source and Javascript source data, but makes no 12969 * difference at all f
12969ro
vendor: 14,836 bytes, lines 12969-13546
12969 DOM and server-side processing tables. 12970 * Note that this parameter will be set by the initialisation routine. To 12971 * set a default use {@link DataTable.defaults}. 12972 * @type boolean 12973 */ 12974 "bDeferRender": null, 12975 12976 /** 12977 * Enable filtering on the table or not. Note that if this is disabled 12978 * then there is no filtering at all on the table, including fnFilter. 12979 * To just remove the filtering input use sDom and remove the 'f' option. 12980 * Note that this parameter will be set by the initialisation routine. To 12981 * set a default use {@link DataTable.defaults}. 12982 * @type boolean 12983 */ 12984 "bFilter": null, 12985 12986 /** 12987 * Table information element (the 'Showing x of y records' div) enable 12988 * flag. 12989 * Note that this parameter will be set by the initialisation routine. To 12990 * set a default use {@link DataTable.defaults}. 12991 * @type boolean 12992 */ 12993 "bInfo": null, 12994 12995 /** 12996 * Present a user control allowing the end user to change the page size 12997 * when pagination is enabled. 12998 * Note that this parameter will be set by the initialisation routine. To 12999 * set a default use {@link DataTable.defaults}. 13000 * @type boolean 13001 */ 13002 "bLengthChange": null, 13003 13004 /** 13005 * Pagination enabled or not. Note that if this is disabled then length 13006 * changing must also be disabled. 13007 * Note that this parameter will be set by the initialisation routine. To 13008 * set a default use {@link DataTable.defaults}. 13009 * @type boolean 13010 */ 13011 "bPaginate": null, 13012 13013 /** 13014 * Processing indicator enable flag whenever DataTables is enacting a 13015 * user request - typically an Ajax request for server-side processing. 13016 * Note that this parameter will be set by the initialisation routine. To 13017 * set a default use {@link DataTable.defaults}. 13018 * @type boolean 13019 */ 13020 "bProcessing": null, 13021 13022 /** 13023 * Server-side processing enabled flag - when enabled DataTables will 13024 * get all data from the server for every draw - there is no filtering, 13025 * sorting or paging done on the client-side. 13026 * Note that this parameter will be set by the initialisation routine. To 13027 * set a default use {@link DataTable.defaults}. 13028 * @type boolean 13029 */ 13030 "bServerSide": null, 13031 13032 /** 13033 * Sorting enablement flag. 13034 * Note that this parameter will be set by the initialisation routine. To 13035 * set a default use {@link DataTable.defaults}. 13036 * @type boolean 13037 */ 13038 "bSort": null, 13039 13040 /** 13041 * Multi-column sorting 13042 * Note that this parameter will be set by the initialisation routine. To 13043 * set a default use {@link DataTable.defaults}. 13044 * @type boolean 13045 */ 13046 "bSortMulti": null, 13047 13048 /** 13049 * Apply a class to the columns which are being sorted to provide a 13050 * visual highlight or not. This can slow things down when enabled since 13051 * there is a lot of DOM interaction. 13052 * Note that this parameter will be set by the initialisation routine. To 13053 * set a default use {@link DataTable.defaults}. 13054 * @type boolean 13055 */ 13056 "bSortClasses": null, 13057 13058 /** 13059 * State saving enablement flag. 13060 * Note that this parameter will be set by the initialisation routine. To 13061 * set a default use {@link DataTable.defaults}. 13062 * @type boolean 13063 */ 13064 "bStateSave": null 13065 }, 13066 13067 13068 /** 13069 * Scrolling settings for a table. 13070 * @namespace 13071 */ 13072 "oScroll": { 13073 /** 13074 * When the table is shorter in height than sScrollY, collapse the 13075 * table container down to the height of the table (when true). 13076 * Note that this parameter will be set by the initialisation routine. To 13077 * set a default use {@link DataTable.defaults}. 13078 * @type boolean 13079 */ 13080 "bCollapse": null, 13081 13082 /** 13083 * Width of the scrollbar for the web-browser's platform. Calculated 13084 * during table initialisation. 13085 * @type int 13086 * @default 0 13087 */ 13088 "iBarWidth": 0, 13089 13090 /** 13091 * Viewport width for horizontal scrolling. Horizontal scrolling is 13092 * disabled if an empty string. 13093 * Note that this parameter will be set by the initialisation routine. To 13094 * set a default use {@link DataTable.defaults}. 13095 * @type string 13096 */ 13097 "sX": null, 13098 13099 /** 13100 * Width to expand the table to when using x-scrolling. Typically you 13101 * should not need to use this. 13102 * Note that this parameter will be set by the initialisation routine. To 13103 * set a default use {@link DataTable.defaults}. 13104 * @type string 13105 * @deprecated 13106 */ 13107 "sXInner": null, 13108 13109 /** 13110 * Viewport height for vertical scrolling. Vertical scrolling is disabled 13111 * if an empty string. 13112 * Note that this parameter will be set by the initialisation routine. To 13113 * set a default use {@link DataTable.defaults}. 13114 * @type string 13115 */ 13116 "sY": null 13117 }, 13118 13119 /** 13120 * Language information for the table. 13121 * @namespace 13122 * @extends DataTable.defaults.oLanguage 13123 */ 13124 "oLanguage": { 13125 /** 13126 * Information callback function. See 13127 * {@link DataTable.defaults.fnInfoCallback} 13128 * @type function 13129 * @default null 13130 */ 13131 "fnInfoCallback": null 13132 }, 13133 13134 /** 13135 * Browser support parameters 13136 * @namespace 13137 */ 13138 "oBrowser": { 13139 /** 13140 * Indicate if the browser incorrectly calculates width:100% inside a 13141 * scrolling element (IE6/7) 13142 * @type boolean 13143 * @default false 13144 */ 13145 "bScrollOversize": false, 13146 13147 /** 13148 * Determine if the vertical scrollbar is on the right or left of the 13149 * scrolling container - needed for rtl language layout, although not 13150 * all browsers move the scrollbar (Safari). 13151 * @type boolean 13152 * @default false 13153 */ 13154 "bScrollbarLeft": false, 13155 13156 /** 13157 * Flag for if `getBoundingClientRect` is fully supported or not 13158 * @type boolean 13159 * @default false 13160 */ 13161 "bBounding": false, 13162 13163 /** 13164 * Browser scrollbar width 13165 * @type integer 13166 * @default 0 13167 */ 13168 "barWidth": 0 13169 }, 13170 13171 13172 "ajax": null, 13173 13174 13175 /** 13176 * Array referencing the nodes which are used for the features. The 13177 * parameters of this object match what is allowed by sDom - i.e. 13178 * <ul> 13179 * <li>'l' - Length changing</li> 13180 * <li>'f' - Filtering input</li> 13181 * <li>'t' - The table!</li> 13182 * <li>'i' - Information</li> 13183 * <li>'p' - Pagination</li> 13184 * <li>'r' - pRocessing</li> 13185 * </ul> 13186 * @type array 13187 * @default [] 13188 */ 13189 "aanFeatures": [], 13190 13191 /** 13192 * Store data information - see {@link DataTable.models.oRow} for detailed 13193 * information. 13194 * @type array 13195 * @default [] 13196 */ 13197 "aoData": [], 13198 13199 /** 13200 * Array of indexes which are in the current display (after filtering etc) 13201 * @type array 13202 * @default [] 13203 */ 13204 "aiDisplay": [], 13205 13206 /** 13207 * Array of indexes for display - no filtering 13208 * @type array 13209 * @default [] 13210 */ 13211 "aiDisplayMaster": [], 13212 13213 /** 13214 * Map of row ids to data indexes 13215 * @type object 13216 * @default {} 13217 */ 13218 "aIds": {}, 13219 13220 /** 13221 * Store information about each column that is in use 13222 * @type array 13223 * @default [] 13224 */ 13225 "aoColumns": [], 13226 13227 /** 13228 * Store information about the table's header 13229 * @type array 13230 * @default [] 13231 */ 13232 "aoHeader": [], 13233 13234 /** 13235 * Store information about the table's footer 13236 * @type array 13237 * @default [] 13238 */ 13239 "aoFooter": [], 13240 13241 /** 13242 * Store the applied global search information in case we want to force a 13243 * research or compare the old search to a new one. 13244 * Note that this parameter will be set by the initialisation routine. To 13245 * set a default use {@link DataTable.defaults}. 13246 * @namespace 13247 * @extends DataTable.models.oSearch 13248 */ 13249 "oPreviousSearch": {}, 13250 13251 /** 13252 * Store the applied search for each column - see 13253 * {@link DataTable.models.oSearch} for the format that is used for the 13254 * filtering information for each column. 13255 * @type array 13256 * @default [] 13257 */ 13258 "aoPreSearchCols": [], 13259 13260 /** 13261 * Sorting that is applied to the table. Note that the inner arrays are 13262 * used in the following manner: 13263 * <ul> 13264 * <li>Index 0 - column number</li> 13265 * <li>Index 1 - current sorting direction</li> 13266 * </ul> 13267 * Note that this parameter will be set by the initialisation routine. To 13268 * set a default use {@link DataTable.defaults}. 13269 * @type array 13270 * @todo These inner arrays should really be objects 13271 */ 13272 "aaSorting": null, 13273 13274 /** 13275 * Sorting that is always applied to the table (i.e. prefixed in front of 13276 * aaSorting). 13277 * Note that this parameter will be set by the initialisation routine. To 13278 * set a default use {@link DataTable.defaults}. 13279 * @type array 13280 * @default [] 13281 */ 13282 "aaSortingFixed": [], 13283 13284 /** 13285 * Classes to use for the striping of a table. 13286 * Note that this parameter will be set by the initialisation routine. To 13287 * set a default use {@link DataTable.defaults}. 13288 * @type array 13289 * @default [] 13290 */ 13291 "asStripeClasses": null, 13292 13293 /** 13294 * If restoring a table - we should restore its striping classes as well 13295 * @type array 13296 * @default [] 13297 */ 13298 "asDestroyStripes": [], 13299 13300 /** 13301 * If restoring a table - we should restore its width 13302 * @type int 13303 * @default 0 13304 */ 13305 "sDestroyWidth": 0, 13306 13307 /** 13308 * Callback functions array for every time a row is inserted (i.e. on a draw). 13309 * @type array 13310 * @default [] 13311 */ 13312 "aoRowCallback": [], 13313 13314 /** 13315 * Callback functions for the header on each draw. 13316 * @type array 13317 * @default [] 13318 */ 13319 "aoHeaderCallback": [], 13320 13321 /** 13322 * Callback function for the footer on each draw. 13323 * @type array 13324 * @default [] 13325 */ 13326 "aoFooterCallback": [], 13327 13328 /** 13329 * Array of callback functions for draw callback functions 13330 * @type array 13331 * @default [] 13332 */ 13333 "aoDrawCallback": [], 13334 13335 /** 13336 * Array of callback functions for row created function 13337 * @type array 13338 * @default [] 13339 */ 13340 "aoRowCreatedCallback": [], 13341 13342 /** 13343 * Callback functions for just before the table is redrawn. A return of 13344 * false will be used to cancel the draw. 13345 * @type array 13346 * @default [] 13347 */ 13348 "aoPreDrawCallback": [], 13349 13350 /** 13351 * Callback functions for when the table has been initialised. 13352 * @type array 13353 * @default [] 13354 */ 13355 "aoInitComplete": [], 13356 13357 13358 /** 13359 * Callbacks for modifying the settings to be stored for state saving, prior to 13360 * saving state. 13361 * @type array 13362 * @default [] 13363 */ 13364 "aoStateSaveParams": [], 13365 13366 /** 13367 * Callbacks for modifying the settings that have been stored for state saving 13368 * prior to using the stored values to restore the state. 13369 * @type array 13370 * @default [] 13371 */ 13372 "aoStateLoadParams": [], 13373 13374 /** 13375 * Callbacks for operating on the settings object once the saved state has been 13376 * loaded 13377 * @type array 13378 * @default [] 13379 */ 13380 "aoStateLoaded": [], 13381 13382 /** 13383 * Cache the table ID for quick access 13384 * @type string 13385 * @default <i>Empty string</i> 13386 */ 13387 "sTableId": "", 13388 13389 /** 13390 * The TABLE node for the main table 13391 * @type node 13392 * @default null 13393 */ 13394 "nTable": null, 13395 13396 /** 13397 * Permanent ref to the thead element 13398 * @type node 13399 * @default null 13400 */ 13401 "nTHead": null, 13402 13403 /** 13404 * Permanent ref to the tfoot element - if it exists 13405 * @type node 13406 * @default null 13407 */ 13408 "nTFoot": null, 13409 13410 /** 13411 * Permanent ref to the tbody element 13412 * @type node 13413 * @default null 13414 */ 13415 "nTBody": null, 13416 13417 /** 13418 * Cache the wrapper node (contains all DataTables controlled elements) 13419 * @type node 13420 * @default null 13421 */ 13422 "nTableWrapper": null, 13423 13424 /** 13425 * Indicate if when using server-side processing the loading of data 13426 * should be deferred until the second draw. 13427 * Note that this parameter will be set by the initialisation routine. To 13428 * set a default use {@link DataTable.defaults}. 13429 * @type boolean 13430 * @default false 13431 */ 13432 "bDeferLoading": false, 13433 13434 /** 13435 * Indicate if all required information has been read in 13436 * @type boolean 13437 * @default false 13438 */ 13439 "bInitialised": false, 13440 13441 /** 13442 * Information about open rows. Each object in the array has the parameters 13443 * 'nTr' and 'nParent' 13444 * @type array 13445 * @default [] 13446 */ 13447 "aoOpenRows": [], 13448 13449 /** 13450 * Dictate the positioning of DataTables' control elements - see 13451 * {@link DataTable.model.oInit.sDom}. 13452 * Note that this parameter will be set by the initialisation routine. To 13453 * set a default use {@link DataTable.defaults}. 13454 * @type string 13455 * @default null 13456 */ 13457 "sDom": null, 13458 13459 /** 13460 * Search delay (in mS) 13461 * @type integer 13462 * @default null 13463 */ 13464 "searchDelay": null, 13465 13466 /** 13467 * Which type of pagination should be used. 13468 * Note that this parameter will be set by the initialisation routine. To 13469 * set a default use {@link DataTable.defaults}. 13470 * @type string 13471 * @default two_button 13472 */ 13473 "sPaginationType": "two_button", 13474 13475 /** 13476 * The state duration (for `stateSave`) in seconds. 13477 * Note that this parameter will be set by the initialisation routine. To 13478 * set a default use {@link DataTable.defaults}. 13479 * @type int 13480 * @default 0 13481 */ 13482 "iStateDuration": 0, 13483 13484 /** 13485 * Array of callback functions for state saving. Each array element is an 13486 * object with the following parameters: 13487 * <ul> 13488 * <li>function:fn - function to call. Takes two parameters, oSettings 13489 * and the JSON string to save that has been thus far created. Returns 13490 * a JSON string to be inserted into a json object 13491 * (i.e. '"param": [ 0, 1, 2]')</li> 13492 * <li>string:sName - name of callback</li> 13493 * </ul> 13494 * @type array 13495 * @default [] 13496 */ 13497 "aoStateSave": [], 13498 13499 /** 13500 * Array of callback functions for state loading. Each array element is an 13501 * object with the following parameters: 13502 * <ul> 13503 * <li>function:fn - function to call. Takes two parameters, oSettings 13504 * and the object stored. May return false to cancel state loading</li> 13505 * <li>string:sName - name of callback</li> 13506 * </ul> 13507 * @type array 13508 * @default [] 13509 */ 13510 "aoStateLoad": [], 13511 13512 /** 13513 * State that was saved. Useful for back reference 13514 * @type object 13515 * @default null 13516 */ 13517 "oSavedState": null, 13518 13519 /** 13520 * State that was loaded. Useful for back reference 13521 * @type object 13522 * @default null 13523 */ 13524 "oLoadedState": null, 13525 13526 /** 13527 * Source url for AJAX data for the table. 13528 * Note that this parameter will be set by the initialisation routine. To 13529 * set a default use {@link DataTable.defaults}. 13530 * @type string 13531 * @default null 13532 */ 13533 "sAjaxSource": null, 13534 13535 /** 13536 * Property from a given object from which to read the table data from. This 13537 * can be an empty string (when not server-side processing), in which case 13538 * it is assumed an an array is given directly. 13539 * Note that this parameter will be set by the initialisation routine. To 13540 * set a default use {@link DataTable.defaults}. 13541 * @type string 13542 */ 13543 "sAjaxDataProp": null, 13544 13545 /** 13546 *
13546Note if draw should be blocked while getting data 13547 * @type boolean 13548 * @default true 13549 */ 13550 "bAjaxDataGet": true, 13551 13552 /** 13553 * The last jQuery XHR object that was used for server-side data gathering. 13554 * This can be used for working with the XHR information in one of the 13555 * callbacks 13556 * @type object 13557 * @default null 13558 */ 13559 "jqXHR": null, 13560 13561 /** 13562 * JSON returned from the server in the last Ajax request 13563 * @type object 13564 * @default undefined 13565 */ 13566 "json": undefined, 13567 13568 /** 13569 * Data submitted as part of the last Ajax request 13570 * @type object 13571 * @default undefined 13572 */ 13573 "oAjaxData": undefined, 13574 13575 /** 13576 * Function to get the server-side data. 13577 * Note that this parameter will be set by the initialisation routine. To 13578 * set a default use {@link DataTable.defaults}. 13579 * @type function 13580 */ 13581 "fnServerData": null, 13582 13583 /** 13584 * Functions which are called prior to sending an Ajax request so extra 13585 * parameters can easily be sent to the server 13586 * @type array 13587 * @default [] 13588 */ 13589 "aoServerParams": [], 13590 13591 /** 13592 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if 13593 * required). 13594 * Note that this parameter will be set by the initialisation routine. To 13595 * set a default use {@link DataTable.defaults}. 13596 * @type string 13597 */ 13598 "sServerMethod": null, 13599 13600 /** 13601 * Format numbers for display. 13602 * Note that this parameter will be set by the initialisation routine. To 13603 * set a default use {@link DataTable.defaults}. 13604 * @type function 13605 */ 13606 "fnFormatNumber": null, 13607 13608 /** 13609 * List of options that can be used for the user selectable length menu. 13610 * Note that this parameter will be set by the initialisation routine. To 13611 * set a default use {@link DataTable.defaults}. 13612 * @type array 13613 * @default [] 13614 */ 13615 "aLengthMenu": null, 13616 13617 /** 13618 * Counter for the draws that the table does. Also used as a tracker for 13619 * server-side processing 13620 * @type int 13621 * @default 0 13622 */ 13623 "iDraw": 0, 13624 13625 /** 13626 * Indicate if a redraw is being done - useful for Ajax 13627 * @type boolean 13628 * @default false 13629 */ 13630 "bDrawing": false, 13631 13632 /** 13633 * Draw index (iDraw) of the last error when parsing the returned data 13634 * @type int 13635 * @default -1 13636 */ 13637 "iDrawError": -1, 13638 13639 /** 13640 * Paging display length 13641 * @type int 13642 * @default 10 13643 */ 13644 "_iDisplayLength": 10, 13645 13646 /** 13647 * Paging start point - aiDisplay index 13648 * @type int 13649 * @default 0 13650 */ 13651 "_iDisplayStart": 0, 13652 13653 /** 13654 * Server-side processing - number of records in the result set 13655 * (i.e. before filtering), Use fnRecordsTotal rather than 13656 * this property to get the value of the number of records, regardless of 13657 * the server-side processing setting. 13658 * @type int 13659 * @default 0 13660 * @private 13661 */ 13662 "_iRecordsTotal": 0, 13663 13664 /** 13665 * Server-side processing - number of records in the current display set 13666 * (i.e. after filtering). Use fnRecordsDisplay rather than 13667 * this property to get the value of the number of records, regardless of 13668 * the server-side processing setting. 13669 * @type boolean 13670 * @default 0 13671 * @private 13672 */ 13673 "_iRecordsDisplay": 0, 13674 13675 /** 13676 * The classes to use for the table 13677 * @type object 13678 * @default {} 13679 */
vendor: 3,548 bytes, lines 13680-13835
13680 "oClasses": {}, 13681 13682 /** 13683 * Flag attached to the settings object so you can check in the draw 13684 * callback if filtering has been done in the draw. Deprecated in favour of 13685 * events. 13686 * @type boolean 13687 * @default false 13688 * @deprecated 13689 */ 13690 "bFiltered": false, 13691 13692 /** 13693 * Flag attached to the settings object so you can check in the draw 13694 * callback if sorting has been done in the draw. Deprecated in favour of 13695 * events. 13696 * @type boolean 13697 * @default false 13698 * @deprecated 13699 */ 13700 "bSorted": false, 13701 13702 /** 13703 * Indicate that if multiple rows are in the header and there is more than 13704 * one unique cell per column, if the top one (true) or bottom one (false) 13705 * should be used for sorting / title by DataTables. 13706 * Note that this parameter will be set by the initialisation routine. To 13707 * set a default use {@link DataTable.defaults}. 13708 * @type boolean 13709 */ 13710 "bSortCellsTop": null, 13711 13712 /** 13713 * Initialisation object that is used for the table 13714 * @type object 13715 * @default null 13716 */ 13717 "oInit": null, 13718 13719 /** 13720 * Destroy callback functions - for plug-ins to attach themselves to the 13721 * destroy so they can clean up markup and events. 13722 * @type array 13723 * @default [] 13724 */ 13725 "aoDestroyCallback": [], 13726 13727 13728 /** 13729 * Get the number of records in the current record set, before filtering 13730 * @type function 13731 */ 13732 "fnRecordsTotal": function () 13733 { 13734 return _fnDataSource( this ) == 'ssp' ? 13735 this._iRecordsTotal * 1 : 13736 this.aiDisplayMaster.length; 13737 }, 13738 13739 /** 13740 * Get the number of records in the current record set, after filtering 13741 * @type function 13742 */ 13743 "fnRecordsDisplay": function () 13744 { 13745 return _fnDataSource( this ) == 'ssp' ? 13746 this._iRecordsDisplay * 1 : 13747 this.aiDisplay.length; 13748 }, 13749 13750 /** 13751 * Get the display end point - aiDisplay index 13752 * @type function 13753 */ 13754 "fnDisplayEnd": function () 13755 { 13756 var 13757 len = this._iDisplayLength, 13758 start = this._iDisplayStart, 13759 calc = start + len, 13760 records = this.aiDisplay.length, 13761 features = this.oFeatures, 13762 paginate = features.bPaginate; 13763 13764 if ( features.bServerSide ) { 13765 return paginate === false || len === -1 ? 13766 start + records : 13767 Math.min( start+len, this._iRecordsDisplay ); 13768 } 13769 else { 13770 return ! paginate || calc>records || len===-1 ? 13771 records : 13772 calc; 13773 } 13774 }, 13775 13776 /** 13777 * The DataTables object for this table 13778 * @type object 13779 * @default null 13780 */ 13781 "oInstance": null, 13782 13783 /** 13784 * Unique identifier for each instance of the DataTables object. If there 13785 * is an ID on the table node, then it takes that value, otherwise an 13786 * incrementing internal counter is used. 13787 * @type string 13788 * @default null 13789 */ 13790 "sInstance": null, 13791 13792 /** 13793 * tabindex attribute value that is added to DataTables control elements, allowing 13794 * keyboard navigation of the table and its controls. 13795 */ 13796 "iTabIndex": 0, 13797 13798 /** 13799 * DIV container for the footer scrolling table if scrolling 13800 */ 13801 "nScrollHead": null, 13802 13803 /** 13804 * DIV container for the footer scrolling table if scrolling 13805 */ 13806 "nScrollFoot": null, 13807 13808 /** 13809 * Last applied sort 13810 * @type array 13811 * @default [] 13812 */ 13813 "aLastSort": [], 13814 13815 /** 13816 * Stored plug-in instances 13817 * @type object 13818 * @default {} 13819 */ 13820 "oPlugins": {}, 13821 13822 /** 13823 * Function used to get a row's id from the row's data 13824 * @type function 13825 * @default null 13826 */ 13827 "rowIdFn": null, 13828 13829 /** 13830 * Data location where to store a row's id 13831 * @type string 13832 * @default null 13833 */ 13834 "rowId": null 13835 };
vendor: 16,410 bytes, lines 13836-14334
13836 13837 /** 13838 * Extension object for DataTables that is used to provide all extension 13839 * options. 13840 * 13841 * Note that the `DataTable.ext` object is available through 13842 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is 13843 * also aliased to `jQuery.fn.dataTableExt` for historic reasons. 13844 * @namespace 13845 * @extends DataTable.models.ext 13846 */ 13847 13848 13849 /** 13850 * DataTables extensions 13851 * 13852 * This namespace acts as a collection area for plug-ins that can be used to 13853 * extend DataTables capabilities. Indeed many of the build in methods 13854 * use this method to provide their own capabilities (sorting methods for 13855 * example). 13856 * 13857 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy 13858 * reasons 13859 * 13860 * @namespace 13861 */ 13862 DataTable.ext = _ext = { 13863 /** 13864 * Buttons. For use with the Buttons extension for DataTables. This is 13865 * defined here so other extensions can define buttons regardless of load 13866 * order. It is _not_ used by DataTables core. 13867 * 13868 * @type object 13869 * @default {} 13870 */ 13871 buttons: {}, 13872 13873 13874 /** 13875 * Element class names 13876 * 13877 * @type object 13878 * @default {} 13879 */ 13880 classes: {}, 13881 13882 13883 /** 13884 * DataTables build type (expanded by the download builder) 13885 * 13886 * @type string 13887 */ 13888 builder: "-source-", 13889 13890 13891 /** 13892 * Error reporting. 13893 * 13894 * How should DataTables report an error. Can take the value 'alert', 13895 * 'throw', 'none' or a function. 13896 * 13897 * @type string|function 13898 * @default alert 13899 */ 13900 errMode: "alert", 13901 13902 13903 /** 13904 * Feature plug-ins. 13905 * 13906 * This is an array of objects which describe the feature plug-ins that are 13907 * available to DataTables. These feature plug-ins are then available for 13908 * use through the `dom` initialisation option. 13909 * 13910 * Each feature plug-in is described by an object which must have the 13911 * following properties: 13912 * 13913 * * `fnInit` - function that is used to initialise the plug-in, 13914 * * `cFeature` - a character so the feature can be enabled by the `dom` 13915 * instillation option. This is case sensitive. 13916 * 13917 * The `fnInit` function has the following input parameters: 13918 * 13919 * 1. `{object}` DataTables settings object: see 13920 * {@link DataTable.models.oSettings} 13921 * 13922 * And the following return is expected: 13923 * 13924 * * {node|null} The element which contains your feature. Note that the 13925 * return may also be void if your plug-in does not require to inject any 13926 * DOM elements into DataTables control (`dom`) - for example this might 13927 * be useful when developing a plug-in which allows table control via 13928 * keyboard entry 13929 * 13930 * @type array 13931 * 13932 * @example 13933 * $.fn.dataTable.ext.features.push( { 13934 * "fnInit": function( oSettings ) { 13935 * return new TableTools( { "oDTSettings": oSettings } ); 13936 * }, 13937 * "cFeature": "T" 13938 * } ); 13939 */ 13940 feature: [], 13941 13942 13943 /** 13944 * Row searching. 13945 * 13946 * This method of searching is complimentary to the default type based 13947 * searching, and a lot more comprehensive as it allows you complete control 13948 * over the searching logic. Each element in this array is a function 13949 * (parameters described below) that is called for every row in the table, 13950 * and your logic decides if it should be included in the searching data set 13951 * or not. 13952 * 13953 * Searching functions have the following input parameters: 13954 * 13955 * 1. `{object}` DataTables settings object: see 13956 * {@link DataTable.models.oSettings} 13957 * 2. `{array|object}` Data for the row to be processed (same as the 13958 * original format that was passed in as the data source, or an array 13959 * from a DOM data source 13960 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which 13961 * can be useful to retrieve the `TR` element if you need DOM interaction. 13962 * 13963 * And the following return is expected: 13964 * 13965 * * {boolean} Include the row in the searched result set (true) or not 13966 * (false) 13967 * 13968 * Note that as with the main search ability in DataTables, technically this 13969 * is "filtering", since it is subtractive. However, for consistency in 13970 * naming we call it searching here. 13971 * 13972 * @type array 13973 * @default [] 13974 * 13975 * @example 13976 * // The following example shows custom search being applied to the 13977 * // fourth column (i.e. the data[3] index) based on two input values 13978 * // from the end-user, matching the data in a certain range. 13979 * $.fn.dataTable.ext.search.push( 13980 * function( settings, data, dataIndex ) { 13981 * var min = document.getElementById('min').value * 1; 13982 * var max = document.getElementById('max').value * 1; 13983 * var version = data[3] == "-" ? 0 : data[3]*1; 13984 * 13985 * if ( min == "" && max == "" ) { 13986 * return true; 13987 * } 13988 * else if ( min == "" && version < max ) { 13989 * return true; 13990 * } 13991 * else if ( min < version && "" == max ) { 13992 * return true; 13993 * } 13994 * else if ( min < version && version < max ) { 13995 * return true; 13996 * } 13997 * return false; 13998 * } 13999 * ); 14000 */ 14001 search: [], 14002 14003 14004 /** 14005 * Selector extensions 14006 * 14007 * The `selector` option can be used to extend the options available for the 14008 * selector modifier options (`selector-modifier` object data type) that 14009 * each of the three built in selector types offer (row, column and cell + 14010 * their plural counterparts). For example the Select extension uses this 14011 * mechanism to provide an option to select only rows, columns and cells 14012 * that have been marked as selected by the end user (`{selected: true}`), 14013 * which can be used in conjunction with the existing built in selector 14014 * options. 14015 * 14016 * Each property is an array to which functions can be pushed. The functions 14017 * take three attributes: 14018 * 14019 * * Settings object for the host table 14020 * * Options object (`selector-modifier` object type) 14021 * * Array of selected item indexes 14022 * 14023 * The return is an array of the resulting item indexes after the custom 14024 * selector has been applied. 14025 * 14026 * @type object 14027 */ 14028 selector: { 14029 cell: [], 14030 column: [], 14031 row: [] 14032 }, 14033 14034 14035 /** 14036 * Internal functions, exposed for used in plug-ins. 14037 * 14038 * Please note that you should not need to use the internal methods for 14039 * anything other than a plug-in (and even then, try to avoid if possible). 14040 * The internal function may change between releases. 14041 * 14042 * @type object 14043 * @default {} 14044 */ 14045 internal: {}, 14046 14047 14048 /** 14049 * Legacy configuration options. Enable and disable legacy options that 14050 * are available in DataTables. 14051 * 14052 * @type object 14053 */ 14054 legacy: { 14055 /** 14056 * Enable / disable DataTables 1.9 compatible server-side processing 14057 * requests 14058 * 14059 * @type boolean 14060 * @default null 14061 */ 14062 ajax: null 14063 }, 14064 14065 14066 /** 14067 * Pagination plug-in methods. 14068 * 14069 * Each entry in this object is a function and defines which buttons should 14070 * be shown by the pagination rendering method that is used for the table: 14071 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the 14072 * buttons are displayed in the document, while the functions here tell it 14073 * what buttons to display. This is done by returning an array of button 14074 * descriptions (what each button will do). 14075 * 14076 * Pagination types (the four built in options and any additional plug-in 14077 * options defined here) can be used through the `paginationType` 14078 * initialisation parameter. 14079 * 14080 * The functions defined take two parameters: 14081 * 14082 * 1. `{int} page` The current page index 14083 * 2. `{int} pages` The number of pages in the table 14084 * 14085 * Each function is expected to return an array where each element of the 14086 * array can be one of: 14087 * 14088 * * `first` - Jump to first page when activated 14089 * * `last` - Jump to last page when activated 14090 * * `previous` - Show previous page when activated 14091 * * `next` - Show next page when activated 14092 * * `{int}` - Show page of the index given 14093 * * `{array}` - A nested array containing the above elements to add a 14094 * containing 'DIV' element (might be useful for styling). 14095 * 14096 * Note that DataTables v1.9- used this object slightly differently whereby 14097 * an object with two functions would be defined for each plug-in. That 14098 * ability is still supported by DataTables 1.10+ to provide backwards 14099 * compatibility, but this option of use is now decremented and no longer 14100 * documented in DataTables 1.10+. 14101 * 14102 * @type object 14103 * @default {} 14104 * 14105 * @example 14106 * // Show previous, next and current page buttons only 14107 * $.fn.dataTableExt.oPagination.current = function ( page, pages ) { 14108 * return [ 'previous', page, 'next' ]; 14109 * }; 14110 */ 14111 pager: {}, 14112 14113 14114 renderer: { 14115 pageButton: {}, 14116 header: {} 14117 }, 14118 14119 14120 /** 14121 * Ordering plug-ins - custom data source 14122 * 14123 * The extension options for ordering of data available here is complimentary 14124 * to the default type based ordering that DataTables typically uses. It 14125 * allows much greater control over the the data that is being used to 14126 * order a column, but is necessarily therefore more complex. 14127 * 14128 * This type of ordering is useful if you want to do ordering based on data 14129 * live from the DOM (for example the contents of an 'input' element) rather 14130 * than just the static string that DataTables knows of. 14131 * 14132 * The way these plug-ins work is that you create an array of the values you 14133 * wish to be ordering for the column in question and then return that 14134 * array. The data in the array much be in the index order of the rows in 14135 * the table (not the currently ordering order!). Which order data gathering 14136 * function is run here depends on the `dt-init columns.orderDataType` 14137 * parameter that is used for the column (if any). 14138 * 14139 * The functions defined take two parameters: 14140 * 14141 * 1. `{object}` DataTables settings object: see 14142 * {@link DataTable.models.oSettings} 14143 * 2. `{int}` Target column index 14144 * 14145 * Each function is expected to return an array: 14146 * 14147 * * `{array}` Data for the column to be ordering upon 14148 * 14149 * @type array 14150 * 14151 * @example 14152 * // Ordering using `input` node values 14153 * $.fn.dataTable.ext.order['dom-text'] = function ( settings, col ) 14154 * { 14155 * return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) { 14156 * return $('input', td).val(); 14157 * } ); 14158 * } 14159 */ 14160 order: {}, 14161 14162 14163 /** 14164 * Type based plug-ins. 14165 * 14166 * Each column in DataTables has a type assigned to it, either by automatic 14167 * detection or by direct assignment using the `type` option for the column. 14168 * The type of a column will effect how it is ordering and search (plug-ins 14169 * can also make use of the column type if required). 14170 * 14171 * @namespace 14172 */ 14173 type: { 14174 /** 14175 * Type detection functions. 14176 * 14177 * The functions defined in this object are used to automatically detect 14178 * a column's type, making initialisation of DataTables super easy, even 14179 * when complex data is in the table. 14180 * 14181 * The functions defined take two parameters: 14182 * 14183 * 1. `{*}` Data from the column cell to be analysed 14184 * 2. `{settings}` DataTables settings object. This can be used to 14185 * perform context specific type detection - for example detection 14186 * based on language settings such as using a comma for a decimal 14187 * place. Generally speaking the options from the settings will not 14188 * be required 14189 * 14190 * Each function is expected to return: 14191 * 14192 * * `{string|null}` Data type detected, or null if unknown (and thus 14193 * pass it on to the other type detection functions. 14194 * 14195 * @type array 14196 * 14197 * @example 14198 * // Currency type detection plug-in: 14199 * $.fn.dataTable.ext.type.detect.push( 14200 * function ( data, settings ) { 14201 * // Check the numeric part 14202 * if ( ! data.substring(1).match(/[0-9]/) ) { 14203 * return null; 14204 * } 14205 * 14206 * // Check prefixed by currency 14207 * if ( data.charAt(0) == '$' || data.charAt(0) == '£' ) { 14208 * return 'currency'; 14209 * } 14210 * return null; 14211 * } 14212 * ); 14213 */ 14214 detect: [], 14215 14216 14217 /** 14218 * Type based search formatting. 14219 * 14220 * The type based searching functions can be used to pre-format the 14221 * data to be search on. For example, it can be used to strip HTML 14222 * tags or to de-format telephone numbers for numeric only searching. 14223 * 14224 * Note that is a search is not defined for a column of a given type, 14225 * no search formatting will be performed. 14226 * 14227 * Pre-processing of searching data plug-ins - When you assign the sType 14228 * for a column (or have it automatically detected for you by DataTables 14229 * or a type detection plug-in), you will typically be using this for 14230 * custom sorting, but it can also be used to provide custom searching 14231 * by allowing you to pre-processing the data and returning the data in 14232 * the format that should be searched upon. This is done by adding 14233 * functions this object with a parameter name which matches the sType 14234 * for that target column. This is the corollary of <i>afnSortData</i> 14235 * for searching data. 14236 * 14237 * The functions defined take a single parameter: 14238 * 14239 * 1. `{*}` Data from the column cell to be prepared for searching 14240 * 14241 * Each function is expected to return: 14242 * 14243 * * `{string|null}` Formatted string that will be used for the searching. 14244 * 14245 * @type object 14246 * @default {} 14247 * 14248 * @example 14249 * $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) { 14250 * return d.replace(/\n/g," ").replace( /<.*?>/g, "" ); 14251 * } 14252 */ 14253 search: {}, 14254 14255 14256 /** 14257 * Type based ordering. 14258 * 14259 * The column type tells DataTables what ordering to apply to the table 14260 * when a column is sorted upon. The order for each type that is defined, 14261 * is defined by the functions available in this object. 14262 * 14263 * Each ordering option can be described by three properties added to 14264 * this object: 14265 * 14266 * * `{type}-pre` - Pre-formatting function 14267 * * `{type}-asc` - Ascending order function 14268 * * `{type}-desc` - Descending order function 14269 * 14270 * All three can be used together, only `{type}-pre` or only 14271 * `{type}-asc` and `{type}-desc` together. It is generally recommended 14272 * that only `{type}-pre` is used, as this provides the optimal 14273 * implementation in terms of speed, although the others are provided 14274 * for compatibility with existing Javascript sort functions. 14275 * 14276 * `{type}-pre`: Functions defined take a single parameter: 14277 * 14278 * 1. `{*}` Data from the column cell to be prepared for ordering 14279 * 14280 * And return: 14281 * 14282 * * `{*}` Data to be sorted upon 14283 * 14284 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort 14285 * functions, taking two parameters: 14286 * 14287 * 1. `{*}` Data to compare to the second parameter 14288 * 2. `{*}` Data to compare to the first parameter 14289 * 14290 * And returning: 14291 * 14292 * * `{*}` Ordering match: <0 if first parameter should be sorted lower 14293 * than the second parameter, ===0 if the two parameters are equal and 14294 * >0 if the first parameter should be sorted height than the second 14295 * parameter. 14296 * 14297 * @type object 14298 * @default {} 14299 * 14300 * @example 14301 * // Numeric ordering of formatted numbers with a pre-formatter 14302 * $.extend( $.fn.dataTable.ext.type.order, { 14303 * "string-pre": function(x) { 14304 * a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" ); 14305 * return parseFloat( a ); 14306 * } 14307 * } ); 14308 * 14309 * @example 14310 * // Case-sensitive string ordering, with no pre-formatting method 14311 * $.extend( $.fn.dataTable.ext.order, { 14312 * "string-case-asc": function(x,y) { 14313 * return ((x < y) ? -1 : ((x > y) ? 1 : 0)); 14314 * }, 14315 * "string-case-desc": function(x,y) { 14316 * return ((x < y) ? 1 : ((x > y) ? -1 : 0)); 14317 * } 14318 * } ); 14319 */ 14320 order: {} 14321 }, 14322 14323 /** 14324 * Unique DataTables instance counter 14325 * 14326 * @type int 14327 * @private 14328 */ 14329 _unique: 0, 14330 14331 14332 // 14333 // Depreciated 14334 // The following properties are retained for backwards compatib
vendor: 3,168 bytes, lines 14334-14471
14334lity only. 14335 // The should not be used in new projects and will be removed in a future 14336 // version 14337 // 14338 14339 /** 14340 * Version check function. 14341 * @type function 14342 * @depreciated Since 1.10 14343 */ 14344 fnVersionCheck: DataTable.fnVersionCheck, 14345 14346 14347 /** 14348 * Index for what 'this' index API functions should use 14349 * @type int 14350 * @deprecated Since v1.10 14351 */ 14352 iApiIndex: 0, 14353 14354 14355 /** 14356 * jQuery UI class container 14357 * @type object 14358 * @deprecated Since v1.10 14359 */ 14360 oJUIClasses: {}, 14361 14362 14363 /** 14364 * Software version 14365 * @type string 14366 * @deprecated Since v1.10 14367 */ 14368 sVersion: DataTable.version 14369 }; 14370 14371 14372 // 14373 // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts 14374 // 14375 $.extend( _ext, { 14376 afnFiltering: _ext.search, 14377 aTypes: _ext.type.detect, 14378 ofnSearch: _ext.type.search, 14379 oSort: _ext.type.order, 14380 afnSortData: _ext.order, 14381 aoFeatures: _ext.feature, 14382 oApi: _ext.internal, 14383 oStdClasses: _ext.classes, 14384 oPagination: _ext.pager 14385 } ); 14386 14387 14388 $.extend( DataTable.ext.classes, { 14389 "sTable": "dataTable", 14390 "sNoFooter": "no-footer", 14391 14392 /* Paging buttons */ 14393 "sPageButton": "paginate_button", 14394 "sPageButtonActive": "current", 14395 "sPageButtonDisabled": "disabled", 14396 14397 /* Striping classes */ 14398 "sStripeOdd": "odd", 14399 "sStripeEven": "even", 14400 14401 /* Empty row */ 14402 "sRowEmpty": "dataTables_empty", 14403 14404 /* Features */ 14405 "sWrapper": "dataTables_wrapper", 14406 "sFilter": "dataTables_filter", 14407 "sInfo": "dataTables_info", 14408 "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */ 14409 "sLength": "dataTables_length", 14410 "sProcessing": "dataTables_processing", 14411 14412 /* Sorting */ 14413 "sSortAsc": "sorting_asc", 14414 "sSortDesc": "sorting_desc", 14415 "sSortable": "sorting", /* Sortable in both directions */ 14416 "sSortableAsc": "sorting_asc_disabled", 14417 "sSortableDesc": "sorting_desc_disabled", 14418 "sSortableNone": "sorting_disabled", 14419 "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */ 14420 14421 /* Filtering */ 14422 "sFilterInput": "", 14423 14424 /* Page length */ 14425 "sLengthSelect": "", 14426 14427 /* Scrolling */ 14428 "sScrollWrapper": "dataTables_scroll", 14429 "sScrollHead": "dataTables_scrollHead", 14430 "sScrollHeadInner": "dataTables_scrollHeadInner", 14431 "sScrollBody": "dataTables_scrollBody", 14432 "sScrollFoot": "dataTables_scrollFoot", 14433 "sScrollFootInner": "dataTables_scrollFootInner", 14434 14435 /* Misc */ 14436 "sHeaderTH": "", 14437 "sFooterTH": "", 14438 14439 // Deprecated 14440 "sSortJUIAsc": "", 14441 "sSortJUIDesc": "", 14442 "sSortJUI": "", 14443 "sSortJUIAscAllowed": "", 14444 "sSortJUIDescAllowed": "", 14445 "sSortJUIWrapper": "", 14446 "sSortIcon": "", 14447 "sJUIHeader": "", 14448 "sJUIFooter": "" 14449 } ); 14450 14451 14452 var extPagination = DataTable.ext.pager; 14453 14454 function _numbers ( page, pages ) { 14455 var 14456 numbers = [], 14457 buttons = extPagination.numbers_length, 14458 half = Math.floor( buttons / 2 ), 14459 i = 1; 14460 14461 if ( pages <= buttons ) { 14462 numbers = _range( 0, pages ); 14463 } 14464 else if ( page <= half ) { 14465 numbers = _range( 0, buttons-2 ); 14466 numbers.push( 'ellipsis' ); 14467 numbers.push( pages-1 ); 14468 } 14469 else if ( page >= pages - 1 - half ) { 14470 numbers = _range( pages-(buttons-2), pages ); 14471 numbers.splice( 0, 0, 'ellipsis' );
14471 // no unshift in ie6 14472 numbers.splice( 0, 0, 0 ); 14473 } 14474 else { 14475 numbers = _range( page-half+2, page+half-1 ); 14476 numbers.push( 'ellipsis' ); 14477 numbers.push( pages-1 ); 14478 numbers.splice( 0, 0, 'ellipsis' ); 14479 numbers.splice( 0, 0, 0 ); 14480 } 14481 14482 numbers.DT_el = 'span'; 14483 return numbers; 14484 } 14485 14486 14487 $.extend( extPagination, { 14488 simple: function ( page, pages ) { 14489 return [ 'previous', 'next' ]; 14490 }, 14491 14492 full: function ( page, pages ) { 14493 return [ 'first', 'previous', 'next', 'last' ]; 14494 }, 14495 14496 numbers: function ( page, pages ) { 14497 return [ _numbers(page, pages) ]; 14498 }, 14499 14500 simple_numbers: function ( page, pages ) { 14501 return [ 'previous', _numbers(page, pages), 'next' ]; 14502 }, 14503 14504 full_numbers: function ( page, pages ) { 14505 return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ]; 14506 }, 14507 14508 first_last_numbers: function (page, pages) { 14509 return ['first', _numbers(page, pages), 'last']; 14510 }, 14511 14512 // For testing and plug-ins to use 14513 _numbers: _numbers, 14514 14515 // Number of number buttons (including ellipsis) to show. _Must be odd!_ 14516 numbers_length: 7 14517 } ); 14518 14519 14520 $.extend( true, DataTable.ext.renderer, { 14521 pageButton: { 14522 _: function ( settings, host, idx, buttons, page, pages ) { 14523 var classes = settings.oClasses; 14524 var lang = settings.oLanguage.oPaginate; 14525 var aria = settings.oLanguage.oAria.paginate || {}; 14526 var btnDisplay, btnClass, counter=0; 14527 14528 var attach = function( container, buttons ) { 14529 var i, ien, node, button; 14530 var clickHandler = function ( e ) { 14531 _fnPageChange( settings, e.data.action, true ); 14532 }; 14533 14534 for ( i=0, ien=buttons.length ; i<ien ; i++ ) { 14535 button = buttons[i]; 14536 14537 if ( $.isArray( button ) ) { 14538 var inner = $( '<'+(button.DT_el || 'div')+'/>' ) 14539 .appendTo( container ); 14540 attach( inner, button ); 14541 } 14542 else { 14543 btnDisplay = null; 14544 btnClass = ''; 14545 14546 switch ( button ) { 14547 case 'ellipsis': 14548 container.append('<span class="ellipsis">…</span>'); 14549 break; 14550 14551 case 'first': 14552 btnDisplay = lang.sFirst; 14553 btnClass = button + (page > 0 ? 14554 '' : ' '+classes.sPageButtonDisabled); 14555 break; 14556 14557 case 'previous': 14558 btnDisplay = lang.sPrevious; 14559 btnClass = button + (page > 0 ? 14560 '' : ' '+classes.sPageButtonDisabled); 14561 break; 14562 14563 case 'next': 14564 btnDisplay = lang.sNext; 14565 btnClass = button + (page < pages-1 ? 14566 '' : ' '+classes.sPageButtonDisabled); 14567 break; 14568 14569 case 'last': 14570 btnDisplay = lang.sLast; 14571 btnClass = button + (page < pages-1 ? 14572 '' : ' '+classes.sPageButtonDisabled); 14573 break; 14574 14575 default: 14576 btnDisplay = button + 1; 14577 btnClass = page === button ? 14578 classes.sPageButtonActive : ''; 14579 break; 14580 } 14581 14582 if ( btnDisplay !== null ) { 14583 node = $('<a>', { 14584 'class': classes.sPageButton+' '+btnClass, 14585 'aria-controls': settings.sTableId, 14586 'aria-label': aria[ button ], 14587 'data-dt-idx': counter, 14588 'tabindex': settings.iTabIndex, 14589 'id': idx === 0 && typeof button === 'string' ? 14590 settings.sTableId +'_'+ button : 14591 null 14592 } ) 14593 .html( btnDisplay ) 14594 .appendTo( container ); 14595 14596 _fnBindAction( 14597 node, {action: button}, clickHandler 14598 ); 14599 14600 counter++; 14601 } 14602 } 14603 } 14604 }; 14605 14606 // IE9 throws an 'unknown error' if document.activeElement is used 14607 // inside an iframe or frame. Try / catch the error. Not good for 14608 // accessibility, but neither are frames. 14609 var activeEl; 14610 14611 try { 14612 // Because this approach is destroying and recreating the paging 14613 // elements, focus is lost on the select button which is bad for 14614 // accessibility. So we want to restore focus once the draw has 14615 // completed 14616 activeEl = $(host).find(document.activeElement).data('dt-idx'); 14617 } 14618 catch (e) {} 14619 14620 attach( $(host).empty(), buttons ); 14621 14622 if ( activeEl !== undefined ) { 14623 $(host).find( '[data-dt-idx='+activeEl+']' ).focus(); 14624 } 14625 } 14626 } 14627 } ); 14628 14629 14630 14631 // Built in type detection. See model.ext.aTypes for information about 14632 // what is required from this methods. 14633 $.extend( DataTable.ext.type.detect, [
vendor: 18,244 bytes, lines 14634-15231
14634 // Plain numbers - first since V8 detects some plain numbers as dates 14635 // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...). 14636 function ( d, settings ) 14637 { 14638 var decimal = settings.oLanguage.sDecimal; 14639 return _isNumber( d, decimal ) ? 'num'+decimal : null; 14640 }, 14641 14642 // Dates (only those recognised by the browser's Date.parse) 14643 function ( d, settings ) 14644 { 14645 // V8 tries _very_ hard to make a string passed into `Date.parse()` 14646 // valid, so we need to use a regex to restrict date formats. Use a 14647 // plug-in for anything other than ISO8601 style strings 14648 if ( d && !(d instanceof Date) && ! _re_date.test(d) ) { 14649 return null; 14650 } 14651 var parsed = Date.parse(d); 14652 return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null; 14653 }, 14654 14655 // Formatted numbers 14656 function ( d, settings ) 14657 { 14658 var decimal = settings.oLanguage.sDecimal; 14659 return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null; 14660 }, 14661 14662 // HTML numeric 14663 function ( d, settings ) 14664 { 14665 var decimal = settings.oLanguage.sDecimal; 14666 return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null; 14667 }, 14668 14669 // HTML numeric, formatted 14670 function ( d, settings ) 14671 { 14672 var decimal = settings.oLanguage.sDecimal; 14673 return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null; 14674 }, 14675 14676 // HTML (this is strict checking - there must be html) 14677 function ( d, settings ) 14678 { 14679 return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ? 14680 'html' : null; 14681 } 14682 ] ); 14683 14684 14685 14686 // Filter formatting functions. See model.ext.ofnSearch for information about 14687 // what is required from these methods. 14688 // 14689 // Note that additional search methods are added for the html numbers and 14690 // html formatted numbers by `_addNumericSort()` when we know what the decimal 14691 // place is 14692 14693 14694 $.extend( DataTable.ext.type.search, { 14695 html: function ( data ) { 14696 return _empty(data) ? 14697 data : 14698 typeof data === 'string' ? 14699 data 14700 .replace( _re_new_lines, " " ) 14701 .replace( _re_html, "" ) : 14702 ''; 14703 }, 14704 14705 string: function ( data ) { 14706 return _empty(data) ? 14707 data : 14708 typeof data === 'string' ? 14709 data.replace( _re_new_lines, " " ) : 14710 data; 14711 } 14712 } ); 14713 14714 14715 14716 var __numericReplace = function ( d, decimalPlace, re1, re2 ) { 14717 if ( d !== 0 && (!d || d === '-') ) { 14718 return -Infinity; 14719 } 14720 14721 // If a decimal place other than `.` is used, it needs to be given to the 14722 // function so we can detect it and replace with a `.` which is the only 14723 // decimal place Javascript recognises - it is not locale aware. 14724 if ( decimalPlace ) { 14725 d = _numToDecimal( d, decimalPlace ); 14726 } 14727 14728 if ( d.replace ) { 14729 if ( re1 ) { 14730 d = d.replace( re1, '' ); 14731 } 14732 14733 if ( re2 ) { 14734 d = d.replace( re2, '' ); 14735 } 14736 } 14737 14738 return d * 1; 14739 }; 14740 14741 14742 // Add the numeric 'deformatting' functions for sorting and search. This is done 14743 // in a function to provide an easy ability for the language options to add 14744 // additional methods if a non-period decimal place is used. 14745 function _addNumericSort ( decimalPlace ) { 14746 $.each( 14747 { 14748 // Plain numbers 14749 "num": function ( d ) { 14750 return __numericReplace( d, decimalPlace ); 14751 }, 14752 14753 // Formatted numbers 14754 "num-fmt": function ( d ) { 14755 return __numericReplace( d, decimalPlace, _re_formatted_numeric ); 14756 }, 14757 14758 // HTML numeric 14759 "html-num": function ( d ) { 14760 return __numericReplace( d, decimalPlace, _re_html ); 14761 }, 14762 14763 // HTML numeric, formatted 14764 "html-num-fmt": function ( d ) { 14765 return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric ); 14766 } 14767 }, 14768 function ( key, fn ) { 14769 // Add the ordering method 14770 _ext.type.order[ key+decimalPlace+'-pre' ] = fn; 14771 14772 // For HTML types add a search formatter that will strip the HTML 14773 if ( key.match(/^html\-/) ) { 14774 _ext.type.search[ key+decimalPlace ] = _ext.type.search.html; 14775 } 14776 } 14777 ); 14778 } 14779 14780 14781 // Default sort methods 14782 $.extend( _ext.type.order, { 14783 // Dates 14784 "date-pre": function ( d ) { 14785 var ts = Date.parse( d ); 14786 return isNaN(ts) ? -Infinity : ts; 14787 }, 14788 14789 // html 14790 "html-pre": function ( a ) { 14791 return _empty(a) ? 14792 '' : 14793 a.replace ? 14794 a.replace( /<.*?>/g, "" ).toLowerCase() : 14795 a+''; 14796 }, 14797 14798 // string 14799 "string-pre": function ( a ) { 14800 // This is a little complex, but faster than always calling toString, 14801 // http://jsperf.com/tostring-v-check 14802 return _empty(a) ? 14803 '' : 14804 typeof a === 'string' ? 14805 a.toLowerCase() : 14806 ! a.toString ? 14807 '' : 14808 a.toString(); 14809 }, 14810 14811 // string-asc and -desc are retained only for compatibility with the old 14812 // sort methods 14813 "string-asc": function ( x, y ) { 14814 return ((x < y) ? -1 : ((x > y) ? 1 : 0)); 14815 }, 14816 14817 "string-desc": function ( x, y ) { 14818 return ((x < y) ? 1 : ((x > y) ? -1 : 0)); 14819 } 14820 } ); 14821 14822 14823 // Numeric sorting types - order doesn't matter here 14824 _addNumericSort( '' ); 14825 14826 14827 $.extend( true, DataTable.ext.renderer, { 14828 header: { 14829 _: function ( settings, cell, column, classes ) { 14830 // No additional mark-up required 14831 // Attach a sort listener to update on sort - note that using the 14832 // `DT` namespace will allow the event to be removed automatically 14833 // on destroy, while the `dt` namespaced event is the one we are 14834 // listening for 14835 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) { 14836 if ( settings !== ctx ) { // need to check this this is the host 14837 return; // table, not a nested one 14838 } 14839 14840 var colIdx = column.idx; 14841 14842 cell 14843 .removeClass( 14844 column.sSortingClass +' '+ 14845 classes.sSortAsc +' '+ 14846 classes.sSortDesc 14847 ) 14848 .addClass( columns[ colIdx ] == 'asc' ? 14849 classes.sSortAsc : columns[ colIdx ] == 'desc' ? 14850 classes.sSortDesc : 14851 column.sSortingClass 14852 ); 14853 } ); 14854 }, 14855 14856 jqueryui: function ( settings, cell, column, classes ) { 14857 $('<div/>') 14858 .addClass( classes.sSortJUIWrapper ) 14859 .append( cell.contents() ) 14860 .append( $('<span/>') 14861 .addClass( classes.sSortIcon+' '+column.sSortingClassJUI ) 14862 ) 14863 .appendTo( cell ); 14864 14865 // Attach a sort listener to update on sort 14866 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) { 14867 if ( settings !== ctx ) { 14868 return; 14869 } 14870 14871 var colIdx = column.idx; 14872 14873 cell 14874 .removeClass( classes.sSortAsc +" "+classes.sSortDesc ) 14875 .addClass( columns[ colIdx ] == 'asc' ? 14876 classes.sSortAsc : columns[ colIdx ] == 'desc' ? 14877 classes.sSortDesc : 14878 column.sSortingClass 14879 ); 14880 14881 cell 14882 .find( 'span.'+classes.sSortIcon ) 14883 .removeClass( 14884 classes.sSortJUIAsc +" "+ 14885 classes.sSortJUIDesc +" "+ 14886 classes.sSortJUI +" "+ 14887 classes.sSortJUIAscAllowed +" "+ 14888 classes.sSortJUIDescAllowed 14889 ) 14890 .addClass( columns[ colIdx ] == 'asc' ? 14891 classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ? 14892 classes.sSortJUIDesc : 14893 column.sSortingClassJUI 14894 ); 14895 } ); 14896 } 14897 } 14898 } ); 14899 14900 /* 14901 * Public helper functions. These aren't used internally by DataTables, or 14902 * called by any of the options passed into DataTables, but they can be used 14903 * externally by developers working with DataTables. They are helper functions 14904 * to make working with DataTables a little bit easier. 14905 */ 14906 14907 var __htmlEscapeEntities = function ( d ) { 14908 return typeof d === 'string' ? 14909 d.replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"') : 14910 d; 14911 }; 14912 14913 /** 14914 * Helpers for `columns.render`. 14915 * 14916 * The options defined here can be used with the `columns.render` initialisation 14917 * option to provide a display renderer. The following functions are defined: 14918 * 14919 * * `number` - Will format numeric data (defined by `columns.data`) for 14920 * display, retaining the original unformatted data for sorting and filtering. 14921 * It takes 5 parameters: 14922 * * `string` - Thousands grouping separator 14923 * * `string` - Decimal point indicator 14924 * * `integer` - Number of decimal points to show 14925 * * `string` (optional) - Prefix. 14926 * * `string` (optional) - Postfix (/suffix). 14927 * * `text` - Escape HTML to help prevent XSS attacks. It has no optional 14928 * parameters. 14929 * 14930 * @example 14931 * // Column definition using the number renderer 14932 * { 14933 * data: "salary", 14934 * render: $.fn.dataTable.render.number( '\'', '.', 0, '$' ) 14935 * } 14936 * 14937 * @namespace 14938 */ 14939 DataTable.render = { 14940 number: function ( thousands, decimal, precision, prefix, postfix ) { 14941 return { 14942 display: function ( d ) { 14943 if ( typeof d !== 'number' && typeof d !== 'string' ) { 14944 return d; 14945 } 14946 14947 var negative = d < 0 ? '-' : ''; 14948 var flo = parseFloat( d ); 14949 14950 // If NaN then there isn't much formatting that we can do - just 14951 // return immediately, escaping any HTML (this was supposed to 14952 // be a number after all) 14953 if ( isNaN( flo ) ) { 14954 return __htmlEscapeEntities( d ); 14955 } 14956 14957 flo = flo.toFixed( precision ); 14958 d = Math.abs( flo ); 14959 14960 var intPart = parseInt( d, 10 ); 14961 var floatPart = precision ? 14962 decimal+(d - intPart).toFixed( precision ).substring( 2 ): 14963 ''; 14964 14965 return negative + (prefix||'') + 14966 intPart.toString().replace( 14967 /\B(?=(\d{3})+(?!\d))/g, thousands 14968 ) + 14969 floatPart + 14970 (postfix||''); 14971 } 14972 }; 14973 }, 14974 14975 text: function () { 14976 return { 14977 display: __htmlEscapeEntities, 14978 filter: __htmlEscapeEntities 14979 }; 14980 } 14981 }; 14982 14983 14984 /* 14985 * This is really a good bit rubbish this method of exposing the internal methods 14986 * publicly... - To be fixed in 2.0 using methods on the prototype 14987 */ 14988 14989 14990 /** 14991 * Create a wrapper function for exporting an internal functions to an external API. 14992 * @param {string} fn API function name 14993 * @returns {function} wrapped function 14994 * @memberof DataTable#internal 14995 */ 14996 function _fnExternApiFunc (fn) 14997 { 14998 return function() { 14999 var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat( 15000 Array.prototype.slice.call(arguments) 15001 ); 15002 return DataTable.ext.internal[fn].apply( this, args ); 15003 }; 15004 } 15005 15006 15007 /** 15008 * Reference to internal functions for use by plug-in developers. Note that 15009 * these methods are references to internal functions and are considered to be 15010 * private. If you use these methods, be aware that they are liable to change 15011 * between versions. 15012 * @namespace 15013 */ 15014 $.extend( DataTable.ext.internal, { 15015 _fnExternApiFunc: _fnExternApiFunc, 15016 _fnBuildAjax: _fnBuildAjax, 15017 _fnAjaxUpdate: _fnAjaxUpdate, 15018 _fnAjaxParameters: _fnAjaxParameters, 15019 _fnAjaxUpdateDraw: _fnAjaxUpdateDraw, 15020 _fnAjaxDataSrc: _fnAjaxDataSrc, 15021 _fnAddColumn: _fnAddColumn, 15022 _fnColumnOptions: _fnColumnOptions, 15023 _fnAdjustColumnSizing: _fnAdjustColumnSizing, 15024 _fnVisibleToColumnIndex: _fnVisibleToColumnIndex, 15025 _fnColumnIndexToVisible: _fnColumnIndexToVisible, 15026 _fnVisbleColumns: _fnVisbleColumns, 15027 _fnGetColumns: _fnGetColumns, 15028 _fnColumnTypes: _fnColumnTypes, 15029 _fnApplyColumnDefs: _fnApplyColumnDefs, 15030 _fnHungarianMap: _fnHungarianMap, 15031 _fnCamelToHungarian: _fnCamelToHungarian, 15032 _fnLanguageCompat: _fnLanguageCompat, 15033 _fnBrowserDetect: _fnBrowserDetect, 15034 _fnAddData: _fnAddData, 15035 _fnAddTr: _fnAddTr, 15036 _fnNodeToDataIndex: _fnNodeToDataIndex, 15037 _fnNodeToColumnIndex: _fnNodeToColumnIndex, 15038 _fnGetCellData: _fnGetCellData, 15039 _fnSetCellData: _fnSetCellData, 15040 _fnSplitObjNotation: _fnSplitObjNotation, 15041 _fnGetObjectDataFn: _fnGetObjectDataFn, 15042 _fnSetObjectDataFn: _fnSetObjectDataFn, 15043 _fnGetDataMaster: _fnGetDataMaster, 15044 _fnClearTable: _fnClearTable, 15045 _fnDeleteIndex: _fnDeleteIndex, 15046 _fnInvalidate: _fnInvalidate, 15047 _fnGetRowElements: _fnGetRowElements, 15048 _fnCreateTr: _fnCreateTr, 15049 _fnBuildHead: _fnBuildHead, 15050 _fnDrawHead: _fnDrawHead, 15051 _fnDraw: _fnDraw, 15052 _fnReDraw: _fnReDraw, 15053 _fnAddOptionsHtml: _fnAddOptionsHtml, 15054 _fnDetectHeader: _fnDetectHeader, 15055 _fnGetUniqueThs: _fnGetUniqueThs, 15056 _fnFeatureHtmlFilter: _fnFeatureHtmlFilter, 15057 _fnFilterComplete: _fnFilterComplete, 15058 _fnFilterCustom: _fnFilterCustom, 15059 _fnFilterColumn: _fnFilterColumn, 15060 _fnFilter: _fnFilter, 15061 _fnFilterCreateSearch: _fnFilterCreateSearch, 15062 _fnEscapeRegex: _fnEscapeRegex, 15063 _fnFilterData: _fnFilterData, 15064 _fnFeatureHtmlInfo: _fnFeatureHtmlInfo, 15065 _fnUpdateInfo: _fnUpdateInfo, 15066 _fnInfoMacros: _fnInfoMacros, 15067 _fnInitialise: _fnInitialise, 15068 _fnInitComplete: _fnInitComplete, 15069 _fnLengthChange: _fnLengthChange, 15070 _fnFeatureHtmlLength: _fnFeatureHtmlLength, 15071 _fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate, 15072 _fnPageChange: _fnPageChange, 15073 _fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing, 15074 _fnProcessingDisplay: _fnProcessingDisplay, 15075 _fnFeatureHtmlTable: _fnFeatureHtmlTable, 15076 _fnScrollDraw: _fnScrollDraw, 15077 _fnApplyToChildren: _fnApplyToChildren, 15078 _fnCalculateColumnWidths: _fnCalculateColumnWidths, 15079 _fnThrottle: _fnThrottle, 15080 _fnConvertToWidth: _fnConvertToWidth, 15081 _fnGetWidestNode: _fnGetWidestNode, 15082 _fnGetMaxLenString: _fnGetMaxLenString, 15083 _fnStringToCss: _fnStringToCss, 15084 _fnSortFlatten: _fnSortFlatten, 15085 _fnSort: _fnSort, 15086 _fnSortAria: _fnSortAria, 15087 _fnSortListener: _fnSortListener, 15088 _fnSortAttachListener: _fnSortAttachListener, 15089 _fnSortingClasses: _fnSortingClasses, 15090 _fnSortData: _fnSortData, 15091 _fnSaveState: _fnSaveState, 15092 _fnLoadState: _fnLoadState, 15093 _fnSettingsFromNode: _fnSettingsFromNode, 15094 _fnLog: _fnLog, 15095 _fnMap: _fnMap, 15096 _fnBindAction: _fnBindAction, 15097 _fnCallbackReg: _fnCallbackReg, 15098 _fnCallbackFire: _fnCallbackFire, 15099 _fnLengthOverflow: _fnLengthOverflow, 15100 _fnRenderer: _fnRenderer, 15101 _fnDataSource: _fnDataSource, 15102 _fnRowAttributes: _fnRowAttributes, 15103 _fnExtend: _fnExtend, 15104 _fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant 15105 // in 1.10, so this dead-end function is 15106 // added to prevent errors 15107 } ); 15108 15109 15110 // jQuery access 15111 $.fn.dataTable = DataTable; 15112 15113 // Provide access to the host jQuery object (circular reference) 15114 DataTable.$ = $; 15115 15116 // Legacy aliases 15117 $.fn.dataTableSettings = DataTable.settings; 15118 $.fn.dataTableExt = DataTable.ext; 15119 15120 // With a capital `D` we return a DataTables API instance rather than a 15121 // jQuery object 15122 $.fn.DataTable = function ( opts ) { 15123 return $(this).dataTable( opts ).api(); 15124 }; 15125 15126 // All properties that are available to $.fn.dataTable should also be 15127 // available on $.fn.DataTable 15128 $.each( DataTable, function ( prop, val ) { 15129 $.fn.DataTable[ prop ] = val; 15130 } ); 15131 15132 15133 // Information about events fired by DataTables - for documentation. 15134 /** 15135 * Draw event, fired whenever the table is redrawn on the page, at the same 15136 * point as fnDrawCallback. This may be useful for binding events or 15137 * performing calculations when the table is altered at all. 15138 * @name DataTable#draw.dt 15139 * @event 15140 * @param {event} e jQuery event object 15141 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15142 */ 15143 15144 /** 15145 * Search event, fired when the searching applied to the table (using the 15146 * built-in global search, or column filters) is altered. 15147 * @name DataTable#search.dt 15148 * @event 15149 * @param {event} e jQuery event object 15150 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15151 */ 15152 15153 /** 15154 * Page change event, fired when the paging of the table is altered. 15155 * @name DataTable#page.dt 15156 * @event 15157 * @param {event} e jQuery event object 15158 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15159 */ 15160 15161 /** 15162 * Order event, fired when the ordering applied to the table is altered. 15163 * @name DataTable#order.dt 15164 * @event 15165 * @param {event} e jQuery event object 15166 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15167 */ 15168 15169 /** 15170 * DataTables initialisation complete event, fired when the table is fully 15171 * drawn, including Ajax data loaded, if Ajax data is required. 15172 * @name DataTable#init.dt 15173 * @event 15174 * @param {event} e jQuery event object 15175 * @param {object} oSettings DataTables settings object 15176 * @param {object} json The JSON object request from the server - only 15177 * present if client-side Ajax sourced data is used</li></ol> 15178 */ 15179 15180 /** 15181 * State save event, fired when the table has changed state a new state save 15182 * is required. This event allows modification of the state saving object 15183 * prior to actually doing the save, including addition or other state 15184 * properties (for plug-ins) or modification of a DataTables core property. 15185 * @name DataTable#stateSaveParams.dt 15186 * @event 15187 * @param {event} e jQuery event object 15188 * @param {object} oSettings DataTables settings object 15189 * @param {object} json The state information to be saved 15190 */ 15191 15192 /** 15193 * State load event, fired when the table is loading state from the stored 15194 * data, but prior to the settings object being modified by the saved state 15195 * - allowing modification of the saved state is required or loading of 15196 * state for a plug-in. 15197 * @name DataTable#stateLoadParams.dt 15198 * @event 15199 * @param {event} e jQuery event object 15200 * @param {object} oSettings DataTables settings object 15201 * @param {object} json The saved state information 15202 */ 15203 15204 /** 15205 * State loaded event, fired when state has been loaded from stored data and 15206 * the settings object has been modified by the loaded data. 15207 * @name DataTable#stateLoaded.dt 15208 * @event 15209 * @param {event} e jQuery event object 15210 * @param {object} oSettings DataTables settings object 15211 * @param {object} json The saved state information 15212 */ 15213 15214 /** 15215 * Processing event, fired when DataTables is doing some kind of processing 15216 * (be it, order, searcg or anything else). It can be used to indicate to 15217 * the end user that there is something happening, or that something has 15218 * finished. 15219 * @name DataTable#processing.dt 15220 * @event 15221 * @param {event} e jQuery event object 15222 * @param {object} oSettings DataTables settings object 15223 * @param {boolean} bShow Flag for if DataTables is doing processing or not 15224 */ 15225 15226 /** 15227 * Ajax (XHR) event, fired whenever an Ajax request is completed from a 15228 * request to made to the server for new data. This event is called before 15229 * DataTables processed the returned data, so it can also be used to pre- 15230 * process the data returned from the server, if needed. 15231 *
15232 * Note that this trigger is called in `fnServerData`, if you override 15233 * `fnServerData` and which to use this event, you need to trigger it in you 15234 * success function. 15235 * @name DataTable#xhr.dt 15236 * @event 15237 * @param {event} e jQuery event object 15238 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15239 * @param {object} json JSON returned from the server 15240 * 15241 * @example 15242 * // Use a custom property returned from the server in another DOM element 15243 * $('#table').dataTable().on('xhr.dt', function (e, settings, json) { 15244 * $('#status').html( json.status ); 15245 * } ); 15246 * 15247 * @example 15248 * // Pre-process the data returned from the server 15249 * $('#table').dataTable().on('xhr.dt', function (e, settings, json) { 15250 * for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) { 15251 * json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two; 15252 * } 15253 * // Note no return - manipulate the data directly in the JSON object. 15254 * } ); 15255 */ 15256 15257 /** 15258 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy 15259 * or passing the bDestroy:true parameter in the initialisation object. This 15260 * can be used to remove bound events, added DOM nodes, etc. 15261 * @name DataTable#destroy.dt 15262 * @event 15263 * @param {event} e jQuery event object 15264 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15265 */ 15266 15267 /** 15268 * Page length change event, fired when number of records to show on each 15269 * page (the length) is changed. 15270 * @name DataTable#length.dt 15271 * @event 15272 * @param {event} e jQuery event object 15273 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15274 * @param {integer} len New length 15275 */ 15276 15277 /** 15278 * Column sizing has changed. 15279 * @name DataTable#column-sizing.dt 15280 * @event 15281 * @param {event} e jQuery event object 15282 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15283 */ 15284 15285 /** 15286 * Column visibility has changed. 15287 * @name DataTable#column-visibility.dt 15288 * @event 15289 * @param {event} e jQuery event object 15290 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15291 * @param {int} column Column index 15292 * @param {bool} vis `false` if column now hidden, or `true` if visible 15293 */ 15294 15295 return $.fn.dataTable; 15296}));
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.