1/* 2 * This combined file was created by the DataTables downloader builder: 3 * https://datatables.net/download 4 * 5 * To rebuild or modify this file with the latest versions of the included 6 * software please visit: 7 * https://datatables.net/download/#dt/dt-1.10.18 8 * 9 * Included libraries: 10 * DataTables 1.10.18 11 */ 12 13/*! DataTables 1.10.18 14 * ©2008-2018 SpryMedia Ltd - datatables.net/license 15 */ 16 17/** 18 * @summary DataTables 19 * @description Paginate, search and order HTML tables 20 * @version 1.10.18 21 * @file jquery.dataTables.js 22 * @author SpryMedia Ltd 23 * @contact www.datatables.net 24 * @copyright Copyright 2008-2018 SpryMedia Ltd. 25 * 26 * This source file is free software, available under the following license: 27 * MIT license - http://datatables.net/license 28 * 29 * This source file is distributed in the hope that it will be useful, but 30 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 31 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. 32 * 33 * For details please refer to: http://www.datatables.net 34 */ 35 36/*jslint evil: true, undef: true, browser: true */ 37/*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*/ 38 39(function( factory ) { 40 "use strict"; 41 42 if ( typeof define === 'function' && define.amd ) { 43 // AMD 44 define( ['jquery'], function ( $ ) { 45 return factory( $, window, document ); 46 } ); 47 } 48 else if ( typeof exports === 'object' ) { 49 // CommonJS 50 module.exports = function (root, $) { 51 if ( ! root ) { 52 // CommonJS environments without a window global must pass a 53 // root. This will give an error otherwise 54 root = window; 55 } 56 57 if ( ! $ ) { 58 $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window 59 require('jquery') : 60 require('jquery')( root ); 61 } 62 63 return factory( $, root, root.document ); 64 }; 65 } 66 else { 67 // Browser 68 factory( jQuery, window, document ); 69 } 70} 71(function( $, window, document, undefined ) { 72 "use strict"; 73 74 /** 75 * DataTables is a plug-in for the jQuery Javascript library. It is a highly 76 * flexible tool, based upon the foundations of progressive enhancement, 77 * which will add advanced interaction controls to any HTML table. For a 78 * full list of features please refer to 79 * [DataTables.net](href="http://datatables.net). 80 * 81 * Note that the `DataTable` object is not a global variable but is aliased 82 * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may 83 * be accessed. 84 * 85 * @class 86 * @param {object} [init={}] Configuration object for DataTables. Options 87 * are defined by {@link DataTable.defaults} 88 * @requires jQuery 1.7+ 89 * 90 * @example 91 * // Basic initialisation 92 * $(document).ready( function { 93 * $('#example').dataTable(); 94 * } ); 95 * 96 * @example 97 * // Initialisation with configuration options - in this case, disable 98 * // pagination and sorting. 99 * $(document).ready( function { 100 * $('#example').dataTable( { 101 * "paginate": false, 102 * "sort": false 103 * } ); 104 * } ); 105 */ 106 var DataTable = function ( options ) 107 {
vendor: 6,636 bytes, lines 107-266
107 108 /** 109 * Perform a jQuery selector action on the table's TR elements (from the tbody) and 110 * return the resulting jQuery object. 111 * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on 112 * @param {object} [oOpts] Optional parameters for modifying the rows to be included 113 * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter 114 * criterion ("applied") or all TR elements (i.e. no filter). 115 * @param {string} [oOpts.order=current] Order of the TR elements in the processed array. 116 * Can be either 'current', whereby the current sorting of the table is used, or 117 * 'original' whereby the original order the data was read into the table is used. 118 * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page 119 * ("current") or not ("all"). If 'current' is given, then order is assumed to be 120 * 'current' and filter is 'applied', regardless of what they might be given as. 121 * @returns {object} jQuery object, filtered by the given selector. 122 * @dtopt API 123 * @deprecated Since v1.10 124 * 125 * @example 126 * $(document).ready(function() { 127 * var oTable = $('#example').dataTable(); 128 * 129 * // Highlight every second row 130 * oTable.$('tr:odd').css('backgroundColor', 'blue'); 131 * } ); 132 * 133 * @example 134 * $(document).ready(function() { 135 * var oTable = $('#example').dataTable(); 136 * 137 * // Filter to rows with 'Webkit' in them, add a background colour and then 138 * // remove the filter, thus highlighting the 'Webkit' rows only. 139 * oTable.fnFilter('Webkit'); 140 * oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue'); 141 * oTable.fnFilter(''); 142 * } ); 143 */ 144 this.$ = function ( sSelector, oOpts ) 145 { 146 return this.api(true).$( sSelector, oOpts ); 147 }; 148 149 150 /** 151 * Almost identical to $ in operation, but in this case returns the data for the matched 152 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes 153 * rather than any descendants, so the data can be obtained for the row/cell. If matching 154 * rows are found, the data returned is the original data array/object that was used to 155 * create the row (or a generated array if from a DOM source). 156 * 157 * This method is often useful in-combination with $ where both functions are given the 158 * same parameters and the array indexes will match identically. 159 * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on 160 * @param {object} [oOpts] Optional parameters for modifying the rows to be included 161 * @param {string} [oOpts.filter=none] Select elements that meet the current filter 162 * criterion ("applied") or all elements (i.e. no filter). 163 * @param {string} [oOpts.order=current] Order of the data in the processed array. 164 * Can be either 'current', whereby the current sorting of the table is used, or 165 * 'original' whereby the original order the data was read into the table is used. 166 * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page 167 * ("current") or not ("all"). If 'current' is given, then order is assumed to be 168 * 'current' and filter is 'applied', regardless of what they might be given as. 169 * @returns {array} Data for the matched elements. If any elements, as a result of the 170 * selector, were not TR, TD or TH elements in the DataTable, they will have a null 171 * entry in the array. 172 * @dtopt API 173 * @deprecated Since v1.10 174 * 175 * @example 176 * $(document).ready(function() { 177 * var oTable = $('#example').dataTable(); 178 * 179 * // Get the data from the first row in the table 180 * var data = oTable._('tr:first'); 181 * 182 * // Do something useful with the data 183 * alert( "First cell is: "+data[0] ); 184 * } ); 185 * 186 * @example 187 * $(document).ready(function() { 188 * var oTable = $('#example').dataTable(); 189 * 190 * // Filter to 'Webkit' and get all data for 191 * oTable.fnFilter('Webkit'); 192 * var data = oTable._('tr', {"search": "applied"}); 193 * 194 * // Do something with the data 195 * alert( data.length+" rows matched the search" ); 196 * } ); 197 */ 198 this._ = function ( sSelector, oOpts ) 199 { 200 return this.api(true).rows( sSelector, oOpts ).data(); 201 }; 202 203 204 /** 205 * Create a DataTables Api instance, with the currently selected tables for 206 * the Api's context. 207 * @param {boolean} [traditional=false] Set the API instance's context to be 208 * only the table referred to by the `DataTable.ext.iApiIndex` option, as was 209 * used in the API presented by DataTables 1.9- (i.e. the traditional mode), 210 * or if all tables captured in the jQuery object should be used. 211 * @return {DataTables.Api} 212 */ 213 this.api = function ( traditional ) 214 { 215 return traditional ? 216 new _Api( 217 _fnSettingsFromNode( this[ _ext.iApiIndex ] ) 218 ) : 219 new _Api( this ); 220 }; 221 222 223 /** 224 * Add a single new row or multiple rows of data to the table. Please note 225 * that this is suitable for client-side processing only - if you are using 226 * server-side processing (i.e. "bServerSide": true), then to add data, you 227 * must add it to the data source, i.e. the server-side, through an Ajax call. 228 * @param {array|object} data The data to be added to the table. This can be: 229 * <ul> 230 * <li>1D array of data - add a single row with the data provided</li> 231 * <li>2D array of arrays - add multiple rows in a single call</li> 232 * <li>object - data object when using <i>mData</i></li> 233 * <li>array of objects - multiple data objects when using <i>mData</i></li> 234 * </ul> 235 * @param {bool} [redraw=true] redraw the table or not 236 * @returns {array} An array of integers, representing the list of indexes in 237 * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to 238 * the table. 239 * @dtopt API 240 * @deprecated Since v1.10 241 * 242 * @example 243 * // Global var for counter 244 * var giCount = 2; 245 * 246 * $(document).ready(function() { 247 * $('#example').dataTable(); 248 * } ); 249 * 250 * function fnClickAddRow() { 251 * $('#example').dataTable().fnAddData( [ 252 * giCount+".1", 253 * giCount+".2", 254 * giCount+".3", 255 * giCount+".4" ] 256 * ); 257 * 258 * giCount++; 259 * } 260 */ 261 this.fnAddData = function( data, redraw ) 262 { 263 var api = this.api( true ); 264 265 /* Check if we want to add multiple rows or not */ 266 var rows =
266$.isArray(data) && ( $
vendor: 18,409 bytes, lines 266-862
266.isArray(data[0]) || $.isPlainObject(data[0]) ) ? 267 api.rows.add( data ) : 268 api.row.add( data ); 269 270 if ( redraw === undefined || redraw ) { 271 api.draw(); 272 } 273 274 return rows.flatten().toArray(); 275 }; 276 277 278 /** 279 * This function will make DataTables recalculate the column sizes, based on the data 280 * contained in the table and the sizes applied to the columns (in the DOM, CSS or 281 * through the sWidth parameter). This can be useful when the width of the table's 282 * parent element changes (for example a window resize). 283 * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to 284 * @dtopt API 285 * @deprecated Since v1.10 286 * 287 * @example 288 * $(document).ready(function() { 289 * var oTable = $('#example').dataTable( { 290 * "sScrollY": "200px", 291 * "bPaginate": false 292 * } ); 293 * 294 * $(window).on('resize', function () { 295 * oTable.fnAdjustColumnSizing(); 296 * } ); 297 * } ); 298 */ 299 this.fnAdjustColumnSizing = function ( bRedraw ) 300 { 301 var api = this.api( true ).columns.adjust(); 302 var settings = api.settings()[0]; 303 var scroll = settings.oScroll; 304 305 if ( bRedraw === undefined || bRedraw ) { 306 api.draw( false ); 307 } 308 else if ( scroll.sX !== "" || scroll.sY !== "" ) { 309 /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */ 310 _fnScrollDraw( settings ); 311 } 312 }; 313 314 315 /** 316 * Quickly and simply clear a table 317 * @param {bool} [bRedraw=true] redraw the table or not 318 * @dtopt API 319 * @deprecated Since v1.10 320 * 321 * @example 322 * $(document).ready(function() { 323 * var oTable = $('#example').dataTable(); 324 * 325 * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...) 326 * oTable.fnClearTable(); 327 * } ); 328 */ 329 this.fnClearTable = function( bRedraw ) 330 { 331 var api = this.api( true ).clear(); 332 333 if ( bRedraw === undefined || bRedraw ) { 334 api.draw(); 335 } 336 }; 337 338 339 /** 340 * The exact opposite of 'opening' a row, this function will close any rows which 341 * are currently 'open'. 342 * @param {node} nTr the table row to 'close' 343 * @returns {int} 0 on success, or 1 if failed (can't find the row) 344 * @dtopt API 345 * @deprecated Since v1.10 346 * 347 * @example 348 * $(document).ready(function() { 349 * var oTable; 350 * 351 * // 'open' an information row when a row is clicked on 352 * $('#example tbody tr').click( function () { 353 * if ( oTable.fnIsOpen(this) ) { 354 * oTable.fnClose( this ); 355 * } else { 356 * oTable.fnOpen( this, "Temporary row opened", "info_row" ); 357 * } 358 * } ); 359 * 360 * oTable = $('#example').dataTable(); 361 * } ); 362 */ 363 this.fnClose = function( nTr ) 364 { 365 this.api( true ).row( nTr ).child.hide(); 366 }; 367 368 369 /** 370 * Remove a row for the table 371 * @param {mixed} target The index of the row from aoData to be deleted, or 372 * the TR element you want to delete 373 * @param {function|null} [callBack] Callback function 374 * @param {bool} [redraw=true] Redraw the table or not 375 * @returns {array} The row that was deleted 376 * @dtopt API 377 * @deprecated Since v1.10 378 * 379 * @example 380 * $(document).ready(function() { 381 * var oTable = $('#example').dataTable(); 382 * 383 * // Immediately remove the first row 384 * oTable.fnDeleteRow( 0 ); 385 * } ); 386 */ 387 this.fnDeleteRow = function( target, callback, redraw ) 388 { 389 var api = this.api( true ); 390 var rows = api.rows( target ); 391 var settings = rows.settings()[0]; 392 var data = settings.aoData[ rows[0][0] ]; 393 394 rows.remove(); 395 396 if ( callback ) { 397 callback.call( this, settings, data ); 398 } 399 400 if ( redraw === undefined || redraw ) { 401 api.draw(); 402 } 403 404 return data; 405 }; 406 407 408 /** 409 * Restore the table to it's original state in the DOM by removing all of DataTables 410 * enhancements, alterations to the DOM structure of the table and event listeners. 411 * @param {boolean} [remove=false] Completely remove the table from the DOM 412 * @dtopt API 413 * @deprecated Since v1.10 414 * 415 * @example 416 * $(document).ready(function() { 417 * // This example is fairly pointless in reality, but shows how fnDestroy can be used 418 * var oTable = $('#example').dataTable(); 419 * oTable.fnDestroy(); 420 * } ); 421 */ 422 this.fnDestroy = function ( remove ) 423 { 424 this.api( true ).destroy( remove ); 425 }; 426 427 428 /** 429 * Redraw the table 430 * @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw. 431 * @dtopt API 432 * @deprecated Since v1.10 433 * 434 * @example 435 * $(document).ready(function() { 436 * var oTable = $('#example').dataTable(); 437 * 438 * // Re-draw the table - you wouldn't want to do it here, but it's an example :-) 439 * oTable.fnDraw(); 440 * } ); 441 */ 442 this.fnDraw = function( complete ) 443 { 444 // Note that this isn't an exact match to the old call to _fnDraw - it takes 445 // into account the new data, but can hold position. 446 this.api( true ).draw( complete ); 447 }; 448 449 450 /** 451 * Filter the input based on data 452 * @param {string} sInput String to filter the table on 453 * @param {int|null} [iColumn] Column to limit filtering to 454 * @param {bool} [bRegex=false] Treat as regular expression or not 455 * @param {bool} [bSmart=true] Perform smart filtering or not 456 * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es) 457 * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false) 458 * @dtopt API 459 * @deprecated Since v1.10 460 * 461 * @example 462 * $(document).ready(function() { 463 * var oTable = $('#example').dataTable(); 464 * 465 * // Sometime later - filter... 466 * oTable.fnFilter( 'test string' ); 467 * } ); 468 */ 469 this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive ) 470 { 471 var api = this.api( true ); 472 473 if ( iColumn === null || iColumn === undefined ) { 474 api.search( sInput, bRegex, bSmart, bCaseInsensitive ); 475 } 476 else { 477 api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive ); 478 } 479 480 api.draw(); 481 }; 482 483 484 /** 485 * Get the data for the whole table, an individual row or an individual cell based on the 486 * provided parameters. 487 * @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as 488 * a TR node then the data source for the whole row will be returned. If given as a 489 * TD/TH cell node then iCol will be automatically calculated and the data for the 490 * cell returned. If given as an integer, then this is treated as the aoData internal 491 * data index for the row (see fnGetPosition) and the data for that row used. 492 * @param {int} [col] Optional column index that you want the data of. 493 * @returns {array|object|string} If mRow is undefined, then the data for all rows is 494 * returned. If mRow is defined, just data for that row, and is iCol is 495 * defined, only data for the designated cell is returned. 496 * @dtopt API 497 * @deprecated Since v1.10 498 * 499 * @example 500 * // Row data 501 * $(document).ready(function() { 502 * oTable = $('#example').dataTable(); 503 * 504 * oTable.$('tr').click( function () { 505 * var data = oTable.fnGetData( this ); 506 * // ... do something with the array / object of data for the row 507 * } ); 508 * } ); 509 * 510 * @example 511 * // Individual cell data 512 * $(document).ready(function() { 513 * oTable = $('#example').dataTable(); 514 * 515 * oTable.$('td').click( function () { 516 * var sData = oTable.fnGetData( this ); 517 * alert( 'The cell clicked on had the value of '+sData ); 518 * } ); 519 * } ); 520 */ 521 this.fnGetData = function( src, col ) 522 { 523 var api = this.api( true ); 524 525 if ( src !== undefined ) { 526 var type = src.nodeName ? src.nodeName.toLowerCase() : ''; 527 528 return col !== undefined || type == 'td' || type == 'th' ? 529 api.cell( src, col ).data() : 530 api.row( src ).data() || null; 531 } 532 533 return api.data().toArray(); 534 }; 535 536 537 /** 538 * Get an array of the TR nodes that are used in the table's body. Note that you will 539 * typically want to use the '$' API method in preference to this as it is more 540 * flexible. 541 * @param {int} [iRow] Optional row index for the TR element you want 542 * @returns {array|node} If iRow is undefined, returns an array of all TR elements 543 * in the table's body, or iRow is defined, just the TR element requested. 544 * @dtopt API 545 * @deprecated Since v1.10 546 * 547 * @example 548 * $(document).ready(function() { 549 * var oTable = $('#example').dataTable(); 550 * 551 * // Get the nodes from the table 552 * var nNodes = oTable.fnGetNodes( ); 553 * } ); 554 */ 555 this.fnGetNodes = function( iRow ) 556 { 557 var api = this.api( true ); 558 559 return iRow !== undefined ? 560 api.row( iRow ).node() : 561 api.rows().nodes().flatten().toArray(); 562 }; 563 564 565 /** 566 * Get the array indexes of a particular cell from it's DOM element 567 * and column index including hidden columns 568 * @param {node} node this can either be a TR, TD or TH in the table's body 569 * @returns {int} If nNode is given as a TR, then a single index is returned, or 570 * if given as a cell, an array of [row index, column index (visible), 571 * column index (all)] is given. 572 * @dtopt API 573 * @deprecated Since v1.10 574 * 575 * @example 576 * $(document).ready(function() { 577 * $('#example tbody td').click( function () { 578 * // Get the position of the current data from the node 579 * var aPos = oTable.fnGetPosition( this ); 580 * 581 * // Get the data array for this row 582 * var aData = oTable.fnGetData( aPos[0] ); 583 * 584 * // Update the data array and return the value 585 * aData[ aPos[1] ] = 'clicked'; 586 * this.innerHTML = 'clicked'; 587 * } ); 588 * 589 * // Init DataTables 590 * oTable = $('#example').dataTable(); 591 * } ); 592 */ 593 this.fnGetPosition = function( node ) 594 { 595 var api = this.api( true ); 596 var nodeName = node.nodeName.toUpperCase(); 597 598 if ( nodeName == 'TR' ) { 599 return api.row( node ).index(); 600 } 601 else if ( nodeName == 'TD' || nodeName == 'TH' ) { 602 var cell = api.cell( node ).index(); 603 604 return [ 605 cell.row, 606 cell.columnVisible, 607 cell.column 608 ]; 609 } 610 return null; 611 }; 612 613 614 /** 615 * Check to see if a row is 'open' or not. 616 * @param {node} nTr the table row to check 617 * @returns {boolean} true if the row is currently open, false otherwise 618 * @dtopt API 619 * @deprecated Since v1.10 620 * 621 * @example 622 * $(document).ready(function() { 623 * var oTable; 624 * 625 * // 'open' an information row when a row is clicked on 626 * $('#example tbody tr').click( function () { 627 * if ( oTable.fnIsOpen(this) ) { 628 * oTable.fnClose( this ); 629 * } else { 630 * oTable.fnOpen( this, "Temporary row opened", "info_row" ); 631 * } 632 * } ); 633 * 634 * oTable = $('#example').dataTable(); 635 * } ); 636 */ 637 this.fnIsOpen = function( nTr ) 638 { 639 return this.api( true ).row( nTr ).child.isShown(); 640 }; 641 642 643 /** 644 * This function will place a new row directly after a row which is currently 645 * on display on the page, with the HTML contents that is passed into the 646 * function. This can be used, for example, to ask for confirmation that a 647 * particular record should be deleted. 648 * @param {node} nTr The table row to 'open' 649 * @param {string|node|jQuery} mHtml The HTML to put into the row 650 * @param {string} sClass Class to give the new TD cell 651 * @returns {node} The row opened. Note that if the table row passed in as the 652 * first parameter, is not found in the table, this method will silently 653 * return. 654 * @dtopt API 655 * @deprecated Since v1.10 656 * 657 * @example 658 * $(document).ready(function() { 659 * var oTable; 660 * 661 * // 'open' an information row when a row is clicked on 662 * $('#example tbody tr').click( function () { 663 * if ( oTable.fnIsOpen(this) ) { 664 * oTable.fnClose( this ); 665 * } else { 666 * oTable.fnOpen( this, "Temporary row opened", "info_row" ); 667 * } 668 * } ); 669 * 670 * oTable = $('#example').dataTable(); 671 * } ); 672 */ 673 this.fnOpen = function( nTr, mHtml, sClass ) 674 { 675 return this.api( true ) 676 .row( nTr ) 677 .child( mHtml, sClass ) 678 .show() 679 .child()[0]; 680 }; 681 682 683 /** 684 * Change the pagination - provides the internal logic for pagination in a simple API 685 * function. With this function you can have a DataTables table go to the next, 686 * previous, first or last pages. 687 * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last" 688 * or page number to jump to (integer), note that page 0 is the first page. 689 * @param {bool} [bRedraw=true] Redraw the table or not 690 * @dtopt API 691 * @deprecated Since v1.10 692 * 693 * @example 694 * $(document).ready(function() { 695 * var oTable = $('#example').dataTable(); 696 * oTable.fnPageChange( 'next' ); 697 * } ); 698 */ 699 this.fnPageChange = function ( mAction, bRedraw ) 700 { 701 var api = this.api( true ).page( mAction ); 702 703 if ( bRedraw === undefined || bRedraw ) { 704 api.draw(false); 705 } 706 }; 707 708 709 /** 710 * Show a particular column 711 * @param {int} iCol The column whose display should be changed 712 * @param {bool} bShow Show (true) or hide (false) the column 713 * @param {bool} [bRedraw=true] Redraw the table or not 714 * @dtopt API 715 * @deprecated Since v1.10 716 * 717 * @example 718 * $(document).ready(function() { 719 * var oTable = $('#example').dataTable(); 720 * 721 * // Hide the second column after initialisation 722 * oTable.fnSetColumnVis( 1, false ); 723 * } ); 724 */ 725 this.fnSetColumnVis = function ( iCol, bShow, bRedraw ) 726 { 727 var api = this.api( true ).column( iCol ).visible( bShow ); 728 729 if ( bRedraw === undefined || bRedraw ) { 730 api.columns.adjust().draw(); 731 } 732 }; 733 734 735 /** 736 * Get the settings for a particular table for external manipulation 737 * @returns {object} DataTables settings object. See 738 * {@link DataTable.models.oSettings} 739 * @dtopt API 740 * @deprecated Since v1.10 741 * 742 * @example 743 * $(document).ready(function() { 744 * var oTable = $('#example').dataTable(); 745 * var oSettings = oTable.fnSettings(); 746 * 747 * // Show an example parameter from the settings 748 * alert( oSettings._iDisplayStart ); 749 * } ); 750 */ 751 this.fnSettings = function() 752 { 753 return _fnSettingsFromNode( this[_ext.iApiIndex] ); 754 }; 755 756 757 /** 758 * Sort the table by a particular column 759 * @param {int} iCol the data index to sort on. Note that this will not match the 760 * 'display index' if you have hidden data entries 761 * @dtopt API 762 * @deprecated Since v1.10 763 * 764 * @example 765 * $(document).ready(function() { 766 * var oTable = $('#example').dataTable(); 767 * 768 * // Sort immediately with columns 0 and 1 769 * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] ); 770 * } ); 771 */ 772 this.fnSort = function( aaSort ) 773 { 774 this.api( true ).order( aaSort ).draw(); 775 }; 776 777 778 /** 779 * Attach a sort listener to an element for a given column 780 * @param {node} nNode the element to attach the sort listener to 781 * @param {int} iColumn the column that a click on this node will sort on 782 * @param {function} [fnCallback] callback function when sort is run 783 * @dtopt API 784 * @deprecated Since v1.10 785 * 786 * @example 787 * $(document).ready(function() { 788 * var oTable = $('#example').dataTable(); 789 * 790 * // Sort on column 1, when 'sorter' is clicked on 791 * oTable.fnSortListener( document.getElementById('sorter'), 1 ); 792 * } ); 793 */ 794 this.fnSortListener = function( nNode, iColumn, fnCallback ) 795 { 796 this.api( true ).order.listener( nNode, iColumn, fnCallback ); 797 }; 798 799 800 /** 801 * Update a table cell or row - this method will accept either a single value to 802 * update the cell with, an array of values with one element for each column or 803 * an object in the same format as the original data source. The function is 804 * self-referencing in order to make the multi column updates easier. 805 * @param {object|array|string} mData Data to update the cell/row with 806 * @param {node|int} mRow TR element you want to update or the aoData index 807 * @param {int} [iColumn] The column to update, give as null or undefined to 808 * update a whole row. 809 * @param {bool} [bRedraw=true] Redraw the table or not 810 * @param {bool} [bAction=true] Perform pre-draw actions or not 811 * @returns {int} 0 on success, 1 on error 812 * @dtopt API 813 * @deprecated Since v1.10 814 * 815 * @example 816 * $(document).ready(function() { 817 * var oTable = $('#example').dataTable(); 818 * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell 819 * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row 820 * } ); 821 */ 822 this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction ) 823 { 824 var api = this.api( true ); 825 826 if ( iColumn === undefined || iColumn === null ) { 827 api.row( mRow ).data( mData ); 828 } 829 else { 830 api.cell( mRow, iColumn ).data( mData ); 831 } 832 833 if ( bAction === undefined || bAction ) { 834 api.columns.adjust(); 835 } 836 837 if ( bRedraw === undefined || bRedraw ) { 838 api.draw(); 839 } 840 return 0; 841 }; 842 843 844 /** 845 * Provide a common method for plug-ins to check the version of DataTables being used, in order 846 * to ensure compatibility. 847 * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the 848 * formats "X" and "X.Y" are also acceptable. 849 * @returns {boolean} true if this version of DataTables is greater or equal to the required 850 * version, or false if this version of DataTales is not suitable 851 * @method 852 * @dtopt API 853 * @deprecated Since v1.10 854 * 855 * @example 856 * $(document).ready(function() { 857 * var oTable = $('#example').dataTable(); 858 * alert( oTable.fnVersionCheck( '1.9.0' ) ); 859 * } ); 860 */ 861 this.fnVersionCheck = _ext.fnVersionCheck; 862
vendor: 57,803 bytes, lines 863-2883
863 864 var _that = this; 865 var emptyInit = options === undefined; 866 var len = this.length; 867 868 if ( emptyInit ) { 869 options = {}; 870 } 871 872 this.oApi = this.internal = _ext.internal; 873 874 // Extend with old style plug-in API methods 875 for ( var fn in DataTable.ext.internal ) { 876 if ( fn ) { 877 this[fn] = _fnExternApiFunc(fn); 878 } 879 } 880 881 this.each(function() { 882 // For each initialisation we want to give it a clean initialisation 883 // object that can be bashed around 884 var o = {}; 885 var oInit = len > 1 ? // optimisation for single table case 886 _fnExtend( o, options, true ) : 887 options; 888 889 /*global oInit,_that,emptyInit*/ 890 var i=0, iLen, j, jLen, k, kLen; 891 var sId = this.getAttribute( 'id' ); 892 var bInitHandedOff = false; 893 var defaults = DataTable.defaults; 894 var $this = $(this); 895 896 897 /* Sanity check */ 898 if ( this.nodeName.toLowerCase() != 'table' ) 899 { 900 _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 ); 901 return; 902 } 903 904 /* Backwards compatibility for the defaults */ 905 _fnCompatOpts( defaults ); 906 _fnCompatCols( defaults.column ); 907 908 /* Convert the camel-case defaults to Hungarian */ 909 _fnCamelToHungarian( defaults, defaults, true ); 910 _fnCamelToHungarian( defaults.column, defaults.column, true ); 911 912 /* Setting up the initialisation object */ 913 _fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) ); 914 915 916 917 /* Check to see if we are re-initialising a table */ 918 var allSettings = DataTable.settings; 919 for ( i=0, iLen=allSettings.length ; i<iLen ; i++ ) 920 { 921 var s = allSettings[i]; 922 923 /* Base check on table node */ 924 if ( 925 s.nTable == this || 926 (s.nTHead && s.nTHead.parentNode == this) || 927 (s.nTFoot && s.nTFoot.parentNode == this) 928 ) { 929 var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve; 930 var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy; 931 932 if ( emptyInit || bRetrieve ) 933 { 934 return s.oInstance; 935 } 936 else if ( bDestroy ) 937 { 938 s.oInstance.fnDestroy(); 939 break; 940 } 941 else 942 { 943 _fnLog( s, 0, 'Cannot reinitialise DataTable', 3 ); 944 return; 945 } 946 } 947 948 /* If the element we are initialising has the same ID as a table which was previously 949 * initialised, but the table nodes don't match (from before) then we destroy the old 950 * instance by simply deleting it. This is under the assumption that the table has been 951 * destroyed by other methods. Anyone using non-id selectors will need to do this manually 952 */ 953 if ( s.sTableId == this.id ) 954 { 955 allSettings.splice( i, 1 ); 956 break; 957 } 958 } 959 960 /* Ensure the table has an ID - required for accessibility */ 961 if ( sId === null || sId === "" ) 962 { 963 sId = "DataTables_Table_"+(DataTable.ext._unique++); 964 this.id = sId; 965 } 966 967 /* Create the settings object for this table and set some of the default parameters */ 968 var oSettings = $.extend( true, {}, DataTable.models.oSettings, { 969 "sDestroyWidth": $this[0].style.width, 970 "sInstance": sId, 971 "sTableId": sId 972 } ); 973 oSettings.nTable = this; 974 oSettings.oApi = _that.internal; 975 oSettings.oInit = oInit; 976 977 allSettings.push( oSettings ); 978 979 // Need to add the instance after the instance after the settings object has been added 980 // to the settings array, so we can self reference the table instance if more than one 981 oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable(); 982 983 // Backwards compatibility, before we apply all the defaults 984 _fnCompatOpts( oInit ); 985 _fnLanguageCompat( oInit.oLanguage ); 986 987 // If the length menu is given, but the init display length is not, use the length menu 988 if ( oInit.aLengthMenu && ! oInit.iDisplayLength ) 989 { 990 oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ? 991 oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0]; 992 } 993 994 // Apply the defaults and init options to make a single init object will all 995 // options defined from defaults and instance options. 996 oInit = _fnExtend( $.extend( true, {}, defaults ), oInit ); 997 998 999 // Map the initialisation options onto the settings object 1000 _fnMap( oSettings.oFeatures, oInit, [ 1001 "bPaginate", 1002 "bLengthChange", 1003 "bFilter", 1004 "bSort", 1005 "bSortMulti", 1006 "bInfo", 1007 "bProcessing", 1008 "bAutoWidth", 1009 "bSortClasses", 1010 "bServerSide", 1011 "bDeferRender" 1012 ] ); 1013 _fnMap( oSettings, oInit, [ 1014 "asStripeClasses", 1015 "ajax", 1016 "fnServerData", 1017 "fnFormatNumber", 1018 "sServerMethod", 1019 "aaSorting", 1020 "aaSortingFixed", 1021 "aLengthMenu", 1022 "sPaginationType", 1023 "sAjaxSource", 1024 "sAjaxDataProp", 1025 "iStateDuration", 1026 "sDom", 1027 "bSortCellsTop", 1028 "iTabIndex", 1029 "fnStateLoadCallback", 1030 "fnStateSaveCallback", 1031 "renderer", 1032 "searchDelay", 1033 "rowId", 1034 [ "iCookieDuration", "iStateDuration" ], // backwards compat 1035 [ "oSearch", "oPreviousSearch" ], 1036 [ "aoSearchCols", "aoPreSearchCols" ], 1037 [ "iDisplayLength", "_iDisplayLength" ] 1038 ] ); 1039 _fnMap( oSettings.oScroll, oInit, [ 1040 [ "sScrollX", "sX" ], 1041 [ "sScrollXInner", "sXInner" ], 1042 [ "sScrollY", "sY" ], 1043 [ "bScrollCollapse", "bCollapse" ] 1044 ] ); 1045 _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" ); 1046 1047 /* Callback functions which are array driven */ 1048 _fnCallbackReg( oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user' ); 1049 _fnCallbackReg( oSettings, 'aoServerParams', oInit.fnServerParams, 'user' ); 1050 _fnCallbackReg( oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user' ); 1051 _fnCallbackReg( oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user' ); 1052 _fnCallbackReg( oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user' ); 1053 _fnCallbackReg( oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user' ); 1054 _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user' ); 1055 _fnCallbackReg( oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user' ); 1056 _fnCallbackReg( oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user' ); 1057 _fnCallbackReg( oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user' ); 1058 _fnCallbackReg( oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user' ); 1059 1060 oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId ); 1061 1062 /* Browser support detection */ 1063 _fnBrowserDetect( oSettings ); 1064 1065 var oClasses = oSettings.oClasses; 1066 1067 $.extend( oClasses, DataTable.ext.classes, oInit.oClasses ); 1068 $this.addClass( oClasses.sTable ); 1069 1070 1071 if ( oSettings.iInitDisplayStart === undefined ) 1072 { 1073 /* Display start point, taking into account the save saving */ 1074 oSettings.iInitDisplayStart = oInit.iDisplayStart; 1075 oSettings._iDisplayStart = oInit.iDisplayStart; 1076 } 1077 1078 if ( oInit.iDeferLoading !== null ) 1079 { 1080 oSettings.bDeferLoading = true; 1081 var tmp = $.isArray( oInit.iDeferLoading ); 1082 oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading; 1083 oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading; 1084 } 1085 1086 /* Language definitions */ 1087 var oLanguage = oSettings.oLanguage; 1088 $.extend( true, oLanguage, oInit.oLanguage ); 1089 1090 if ( oLanguage.sUrl ) 1091 { 1092 /* Get the language definitions from a file - because this Ajax call makes the language 1093 * get async to the remainder of this function we use bInitHandedOff to indicate that 1094 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor 1095 */ 1096 $.ajax( { 1097 dataType: 'json', 1098 url: oLanguage.sUrl, 1099 success: function ( json ) { 1100 _fnLanguageCompat( json ); 1101 _fnCamelToHungarian( defaults.oLanguage, json ); 1102 $.extend( true, oLanguage, json ); 1103 _fnInitialise( oSettings ); 1104 }, 1105 error: function () { 1106 // Error occurred loading language file, continue on as best we can 1107 _fnInitialise( oSettings ); 1108 } 1109 } ); 1110 bInitHandedOff = true; 1111 } 1112 1113 /* 1114 * Stripes 1115 */ 1116 if ( oInit.asStripeClasses === null ) 1117 { 1118 oSettings.asStripeClasses =[ 1119 oClasses.sStripeOdd, 1120 oClasses.sStripeEven 1121 ]; 1122 } 1123 1124 /* Remove row stripe classes if they are already on the table row */ 1125 var stripeClasses = oSettings.asStripeClasses; 1126 var rowOne = $this.children('tbody').find('tr').eq(0); 1127 if ( $.inArray( true, $.map( stripeClasses, function(el, i) { 1128 return rowOne.hasClass(el); 1129 } ) ) !== -1 ) { 1130 $('tbody tr', this).removeClass( stripeClasses.join(' ') ); 1131 oSettings.asDestroyStripes = stripeClasses.slice(); 1132 } 1133 1134 /* 1135 * Columns 1136 * See if we should load columns automatically or use defined ones 1137 */ 1138 var anThs = []; 1139 var aoColumnsInit; 1140 var nThead = this.getElementsByTagName('thead'); 1141 if ( nThead.length !== 0 ) 1142 { 1143 _fnDetectHeader( oSettings.aoHeader, nThead[0] ); 1144 anThs = _fnGetUniqueThs( oSettings ); 1145 } 1146 1147 /* If not given a column array, generate one with nulls */ 1148 if ( oInit.aoColumns === null ) 1149 { 1150 aoColumnsInit = []; 1151 for ( i=0, iLen=anThs.length ; i<iLen ; i++ ) 1152 { 1153 aoColumnsInit.push( null ); 1154 } 1155 } 1156 else 1157 { 1158 aoColumnsInit = oInit.aoColumns; 1159 } 1160 1161 /* Add the columns */ 1162 for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ ) 1163 { 1164 _fnAddColumn( oSettings, anThs ? anThs[i] : null ); 1165 } 1166 1167 /* Apply the column definitions */ 1168 _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) { 1169 _fnColumnOptions( oSettings, iCol, oDef ); 1170 } ); 1171 1172 /* HTML5 attribute detection - build an mData object automatically if the 1173 * attributes are found 1174 */ 1175 if ( rowOne.length ) { 1176 var a = function ( cell, name ) { 1177 return cell.getAttribute( 'data-'+name ) !== null ? name : null; 1178 }; 1179 1180 $( rowOne[0] ).children('th, td').each( function (i, cell) { 1181 var col = oSettings.aoColumns[i]; 1182 1183 if ( col.mData === i ) { 1184 var sort = a( cell, 'sort' ) || a( cell, 'order' ); 1185 var filter = a( cell, 'filter' ) || a( cell, 'search' ); 1186 1187 if ( sort !== null || filter !== null ) { 1188 col.mData = { 1189 _: i+'.display', 1190 sort: sort !== null ? i+'.@data-'+sort : undefined, 1191 type: sort !== null ? i+'.@data-'+sort : undefined, 1192 filter: filter !== null ? i+'.@data-'+filter : undefined 1193 }; 1194 1195 _fnColumnOptions( oSettings, i ); 1196 } 1197 } 1198 } ); 1199 } 1200 1201 var features = oSettings.oFeatures; 1202 var loadedInit = function () { 1203 /* 1204 * Sorting 1205 * @todo For modularisation (1.11) this needs to do into a sort start up handler 1206 */ 1207 1208 // If aaSorting is not defined, then we use the first indicator in asSorting 1209 // in case that has been altered, so the default sort reflects that option 1210 if ( oInit.aaSorting === undefined ) { 1211 var sorting = oSettings.aaSorting; 1212 for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) { 1213 sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0]; 1214 } 1215 } 1216 1217 /* Do a first pass on the sorting classes (allows any size changes to be taken into 1218 * account, and also will apply sorting disabled classes if disabled 1219 */ 1220 _fnSortingClasses( oSettings ); 1221 1222 if ( features.bSort ) { 1223 _fnCallbackReg( oSettings, 'aoDrawCallback', function () { 1224 if ( oSettings.bSorted ) { 1225 var aSort = _fnSortFlatten( oSettings ); 1226 var sortedColumns = {}; 1227 1228 $.each( aSort, function (i, val) { 1229 sortedColumns[ val.src ] = val.dir; 1230 } ); 1231 1232 _fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] ); 1233 _fnSortAria( oSettings ); 1234 } 1235 } ); 1236 } 1237 1238 _fnCallbackReg( oSettings, 'aoDrawCallback', function () { 1239 if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) { 1240 _fnSortingClasses( oSettings ); 1241 } 1242 }, 'sc' ); 1243 1244 1245 /* 1246 * Final init 1247 * Cache the header, body and footer as required, creating them if needed 1248 */ 1249 1250 // Work around for Webkit bug 83867 - store the caption-side before removing from doc 1251 var captions = $this.children('caption').each( function () { 1252 this._captionSide = $(this).css('caption-side'); 1253 } ); 1254 1255 var thead = $this.children('thead'); 1256 if ( thead.length === 0 ) { 1257 thead = $('<thead/>').appendTo($this); 1258 } 1259 oSettings.nTHead = thead[0]; 1260 1261 var tbody = $this.children('tbody'); 1262 if ( tbody.length === 0 ) { 1263 tbody = $('<tbody/>').appendTo($this); 1264 } 1265 oSettings.nTBody = tbody[0]; 1266 1267 var tfoot = $this.children('tfoot'); 1268 if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) { 1269 // If we are a scrolling table, and no footer has been given, then we need to create 1270 // a tfoot element for the caption element to be appended to 1271 tfoot = $('<tfoot/>').appendTo($this); 1272 } 1273 1274 if ( tfoot.length === 0 || tfoot.children().length === 0 ) { 1275 $this.addClass( oClasses.sNoFooter ); 1276 } 1277 else if ( tfoot.length > 0 ) { 1278 oSettings.nTFoot = tfoot[0]; 1279 _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot ); 1280 } 1281 1282 /* Check if there is data passing into the constructor */ 1283 if ( oInit.aaData ) { 1284 for ( i=0 ; i<oInit.aaData.length ; i++ ) { 1285 _fnAddData( oSettings, oInit.aaData[ i ] ); 1286 } 1287 } 1288 else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) { 1289 /* Grab the data from the page - only do this when deferred loading or no Ajax 1290 * source since there is no point in reading the DOM data if we are then going 1291 * to replace it with Ajax data 1292 */ 1293 _fnAddTr( oSettings, $(oSettings.nTBody).children('tr') ); 1294 } 1295 1296 /* Copy the data index array */ 1297 oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); 1298 1299 /* Initialisation complete - table can be drawn */ 1300 oSettings.bInitialised = true; 1301 1302 /* Check if we need to initialise the table (it might not have been handed off to the 1303 * language processor) 1304 */ 1305 if ( bInitHandedOff === false ) { 1306 _fnInitialise( oSettings ); 1307 } 1308 }; 1309 1310 /* Must be done after everything which can be overridden by the state saving! */ 1311 if ( oInit.bStateSave ) 1312 { 1313 features.bStateSave = true; 1314 _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' ); 1315 _fnLoadState( oSettings, oInit, loadedInit ); 1316 } 1317 else { 1318 loadedInit(); 1319 } 1320 1321 } ); 1322 _that = null; 1323 return this; 1324 }; 1325 1326 1327 /* 1328 * It is useful to have variables which are scoped locally so only the 1329 * DataTables functions can access them and they don't leak into global space. 1330 * At the same time these functions are often useful over multiple files in the 1331 * core and API, so we list, or at least document, all variables which are used 1332 * by DataTables as private variables here. This also ensures that there is no 1333 * clashing of variable names and that they can easily referenced for reuse. 1334 */ 1335 1336 1337 // Defined else where 1338 // _selector_run 1339 // _selector_opts 1340 // _selector_first 1341 // _selector_row_indexes 1342 1343 var _ext; // DataTable.ext 1344 var _Api; // DataTable.Api 1345 var _api_register; // DataTable.Api.register 1346 var _api_registerPlural; // DataTable.Api.registerPlural 1347 1348 var _re_dic = {}; 1349 var _re_new_lines = /[\r\n]/g; 1350 var _re_html = /<.*?>/g; 1351 1352 // This is not strict ISO8601 - Date.parse() is quite lax, although 1353 // implementations differ between browsers. 1354 var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/; 1355 1356 // Escape regular expression special characters 1357 var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' ); 1358 1359 // http://en.wikipedia.org/wiki/Foreign_exchange_market 1360 // - \u20BD - Russian ruble. 1361 // - \u20a9 - South Korean Won 1362 // - \u20BA - Turkish Lira 1363 // - \u20B9 - Indian Rupee 1364 // - R - Brazil (R$) and South Africa 1365 // - fr - Swiss Franc 1366 // - kr - Swedish krona, Norwegian krone and Danish krone 1367 // - \u2009 is thin space and \u202F is narrow no-break space, both used in many 1368 // - É - Bitcoin 1369 // - Î - Ethereum 1370 // standards as thousands separators. 1371 var _re_formatted_numeric = /[',$£â¬Â¥%\u2009\u202F\u20BD\u20a9\u20BArfkÉÎ]/gi; 1372 1373 1374 var _empty = function ( d ) { 1375 return !d || d === true || d === '-' ? true : false; 1376 }; 1377 1378 1379 var _intVal = function ( s ) { 1380 var integer = parseInt( s, 10 ); 1381 return !isNaN(integer) && isFinite(s) ? integer : null; 1382 }; 1383 1384 // Convert from a formatted number with characters other than `.` as the 1385 // decimal place, to a Javascript number 1386 var _numToDecimal = function ( num, decimalPoint ) { 1387 // Cache created regular expressions for speed as this function is called often 1388 if ( ! _re_dic[ decimalPoint ] ) { 1389 _re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' ); 1390 } 1391 return typeof num === 'string' && decimalPoint !== '.' ? 1392 num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) : 1393 num; 1394 }; 1395 1396 1397 var _isNumber = function ( d, decimalPoint, formatted ) { 1398 var strType = typeof d === 'string'; 1399 1400 // If empty return immediately so there must be a number if it is a 1401 // formatted string (this stops the string "k", or "kr", etc being detected 1402 // as a formatted number for currency 1403 if ( _empty( d ) ) { 1404 return true; 1405 } 1406 1407 if ( decimalPoint && strType ) { 1408 d = _numToDecimal( d, decimalPoint ); 1409 } 1410 1411 if ( formatted && strType ) { 1412 d = d.replace( _re_formatted_numeric, '' ); 1413 } 1414 1415 return !isNaN( parseFloat(d) ) && isFinite( d ); 1416 }; 1417 1418 1419 // A string without HTML in it can be considered to be HTML still 1420 var _isHtml = function ( d ) { 1421 return _empty( d ) || typeof d === 'string'; 1422 }; 1423 1424 1425 var _htmlNumeric = function ( d, decimalPoint, formatted ) { 1426 if ( _empty( d ) ) { 1427 return true; 1428 } 1429 1430 var html = _isHtml( d ); 1431 return ! html ? 1432 null : 1433 _isNumber( _stripHtml( d ), decimalPoint, formatted ) ? 1434 true : 1435 null; 1436 }; 1437 1438 1439 var _pluck = function ( a, prop, prop2 ) { 1440 var out = []; 1441 var i=0, ien=a.length; 1442 1443 // Could have the test in the loop for slightly smaller code, but speed 1444 // is essential here 1445 if ( prop2 !== undefined ) { 1446 for ( ; i<ien ; i++ ) { 1447 if ( a[i] && a[i][ prop ] ) { 1448 out.push( a[i][ prop ][ prop2 ] ); 1449 } 1450 } 1451 } 1452 else { 1453 for ( ; i<ien ; i++ ) { 1454 if ( a[i] ) { 1455 out.push( a[i][ prop ] ); 1456 } 1457 } 1458 } 1459 1460 return out; 1461 }; 1462 1463 1464 // Basically the same as _pluck, but rather than looping over `a` we use `order` 1465 // as the indexes to pick from `a` 1466 var _pluck_order = function ( a, order, prop, prop2 ) 1467 { 1468 var out = []; 1469 var i=0, ien=order.length; 1470 1471 // Could have the test in the loop for slightly smaller code, but speed 1472 // is essential here 1473 if ( prop2 !== undefined ) { 1474 for ( ; i<ien ; i++ ) { 1475 if ( a[ order[i] ][ prop ] ) { 1476 out.push( a[ order[i] ][ prop ][ prop2 ] ); 1477 } 1478 } 1479 } 1480 else { 1481 for ( ; i<ien ; i++ ) { 1482 out.push( a[ order[i] ][ prop ] ); 1483 } 1484 } 1485 1486 return out; 1487 }; 1488 1489 1490 var _range = function ( len, start ) 1491 { 1492 var out = []; 1493 var end; 1494 1495 if ( start === undefined ) { 1496 start = 0; 1497 end = len; 1498 } 1499 else { 1500 end = start; 1501 start = len; 1502 } 1503 1504 for ( var i=start ; i<end ; i++ ) { 1505 out.push( i ); 1506 } 1507 1508 return out; 1509 }; 1510 1511 1512 var _removeEmpty = function ( a ) 1513 { 1514 var out = []; 1515 1516 for ( var i=0, ien=a.length ; i<ien ; i++ ) { 1517 if ( a[i] ) { // careful - will remove all falsy values! 1518 out.push( a[i] ); 1519 } 1520 } 1521 1522 return out; 1523 }; 1524 1525 1526 var _stripHtml = function ( d ) { 1527 return d.replace( _re_html, '' ); 1528 }; 1529 1530 1531 /** 1532 * Determine if all values in the array are unique. This means we can short 1533 * cut the _unique method at the cost of a single loop. A sorted array is used 1534 * to easily check the values. 1535 * 1536 * @param {array} src Source array 1537 * @return {boolean} true if all unique, false otherwise 1538 * @ignore 1539 */ 1540 var _areAllUnique = function ( src ) { 1541 if ( src.length < 2 ) { 1542 return true; 1543 } 1544 1545 var sorted = src.slice().sort(); 1546 var last = sorted[0]; 1547 1548 for ( var i=1, ien=sorted.length ; i<ien ; i++ ) { 1549 if ( sorted[i] === last ) { 1550 return false; 1551 } 1552 1553 last = sorted[i]; 1554 } 1555 1556 return true; 1557 }; 1558 1559 1560 /** 1561 * Find the unique elements in a source array. 1562 * 1563 * @param {array} src Source array 1564 * @return {array} Array of unique items 1565 * @ignore 1566 */ 1567 var _unique = function ( src ) 1568 { 1569 if ( _areAllUnique( src ) ) { 1570 return src.slice(); 1571 } 1572 1573 // A faster unique method is to use object keys to identify used values, 1574 // but this doesn't work with arrays or objects, which we must also 1575 // consider. See jsperf.com/compare-array-unique-versions/4 for more 1576 // information. 1577 var 1578 out = [], 1579 val, 1580 i, ien=src.length, 1581 j, k=0; 1582 1583 again: for ( i=0 ; i<ien ; i++ ) { 1584 val = src[i]; 1585 1586 for ( j=0 ; j<k ; j++ ) { 1587 if ( out[j] === val ) { 1588 continue again; 1589 } 1590 } 1591 1592 out.push( val ); 1593 k++; 1594 } 1595 1596 return out; 1597 }; 1598 1599 1600 /** 1601 * DataTables utility methods 1602 * 1603 * This namespace provides helper methods that DataTables uses internally to 1604 * create a DataTable, but which are not exclusively used only for DataTables. 1605 * These methods can be used by extension authors to save the duplication of 1606 * code. 1607 * 1608 * @namespace 1609 */ 1610 DataTable.util = { 1611 /** 1612 * Throttle the calls to a function. Arguments and context are maintained 1613 * for the throttled function. 1614 * 1615 * @param {function} fn Function to be called 1616 * @param {integer} freq Call frequency in mS 1617 * @return {function} Wrapped function 1618 */ 1619 throttle: function ( fn, freq ) { 1620 var 1621 frequency = freq !== undefined ? freq : 200, 1622 last, 1623 timer; 1624 1625 return function () { 1626 var 1627 that = this, 1628 now = +new Date(), 1629 args = arguments; 1630 1631 if ( last && now < last + frequency ) { 1632 clearTimeout( timer ); 1633 1634 timer = setTimeout( function () { 1635 last = undefined; 1636 fn.apply( that, args ); 1637 }, frequency ); 1638 } 1639 else { 1640 last = now; 1641 fn.apply( that, args ); 1642 } 1643 }; 1644 }, 1645 1646 1647 /** 1648 * Escape a string such that it can be used in a regular expression 1649 * 1650 * @param {string} val string to escape 1651 * @returns {string} escaped string 1652 */ 1653 escapeRegex: function ( val ) { 1654 return val.replace( _re_escape_regex, '\\$1' ); 1655 } 1656 }; 1657 1658 1659 1660 /** 1661 * Create a mapping object that allows camel case parameters to be looked up 1662 * for their Hungarian counterparts. The mapping is stored in a private 1663 * parameter called `_hungarianMap` which can be accessed on the source object. 1664 * @param {object} o 1665 * @memberof DataTable#oApi 1666 */ 1667 function _fnHungarianMap ( o ) 1668 { 1669 var 1670 hungarian = 'a aa ai ao as b fn i m o s ', 1671 match, 1672 newKey, 1673 map = {}; 1674 1675 $.each( o, function (key, val) { 1676 match = key.match(/^([^A-Z]+?)([A-Z])/); 1677 1678 if ( match && hungarian.indexOf(match[1]+' ') !== -1 ) 1679 { 1680 newKey = key.replace( match[0], match[2].toLowerCase() ); 1681 map[ newKey ] = key; 1682 1683 if ( match[1] === 'o' ) 1684 { 1685 _fnHungarianMap( o[key] ); 1686 } 1687 } 1688 } ); 1689 1690 o._hungarianMap = map; 1691 } 1692 1693 1694 /** 1695 * Convert from camel case parameters to Hungarian, based on a Hungarian map 1696 * created by _fnHungarianMap. 1697 * @param {object} src The model object which holds all parameters that can be 1698 * mapped. 1699 * @param {object} user The object to convert from camel case to Hungarian. 1700 * @param {boolean} force When set to `true`, properties which already have a 1701 * Hungarian value in the `user` object will be overwritten. Otherwise they 1702 * won't be. 1703 * @memberof DataTable#oApi 1704 */ 1705 function _fnCamelToHungarian ( src, user, force ) 1706 { 1707 if ( ! src._hungarianMap ) { 1708 _fnHungarianMap( src ); 1709 } 1710 1711 var hungarianKey; 1712 1713 $.each( user, function (key, val) { 1714 hungarianKey = src._hungarianMap[ key ]; 1715 1716 if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) ) 1717 { 1718 // For objects, we need to buzz down into the object to copy parameters 1719 if ( hungarianKey.charAt(0) === 'o' ) 1720 { 1721 // Copy the camelCase options over to the hungarian 1722 if ( ! user[ hungarianKey ] ) { 1723 user[ hungarianKey ] = {}; 1724 } 1725 $.extend( true, user[hungarianKey], user[key] ); 1726 1727 _fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force ); 1728 } 1729 else { 1730 user[hungarianKey] = user[ key ]; 1731 } 1732 } 1733 } ); 1734 } 1735 1736 1737 /** 1738 * Language compatibility - when certain options are given, and others aren't, we 1739 * need to duplicate the values over, in order to provide backwards compatibility 1740 * with older language files. 1741 * @param {object} oSettings dataTables settings object 1742 * @memberof DataTable#oApi 1743 */ 1744 function _fnLanguageCompat( lang ) 1745 { 1746 // Note the use of the Hungarian notation for the parameters in this method as 1747 // this is called after the mapping of camelCase to Hungarian 1748 var defaults = DataTable.defaults.oLanguage; 1749 1750 // Default mapping 1751 var defaultDecimal = defaults.sDecimal; 1752 if ( defaultDecimal ) { 1753 _addNumericSort( defaultDecimal ); 1754 } 1755 1756 if ( lang ) { 1757 var zeroRecords = lang.sZeroRecords; 1758 1759 // Backwards compatibility - if there is no sEmptyTable given, then use the same as 1760 // sZeroRecords - assuming that is given. 1761 if ( ! lang.sEmptyTable && zeroRecords && 1762 defaults.sEmptyTable === "No data available in table" ) 1763 { 1764 _fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' ); 1765 } 1766 1767 // Likewise with loading records 1768 if ( ! lang.sLoadingRecords && zeroRecords && 1769 defaults.sLoadingRecords === "Loading..." ) 1770 { 1771 _fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' ); 1772 } 1773 1774 // Old parameter name of the thousands separator mapped onto the new 1775 if ( lang.sInfoThousands ) { 1776 lang.sThousands = lang.sInfoThousands; 1777 } 1778 1779 var decimal = lang.sDecimal; 1780 if ( decimal && defaultDecimal !== decimal ) { 1781 _addNumericSort( decimal ); 1782 } 1783 } 1784 } 1785 1786 1787 /** 1788 * Map one parameter onto another 1789 * @param {object} o Object to map 1790 * @param {*} knew The new parameter name 1791 * @param {*} old The old parameter name 1792 */ 1793 var _fnCompatMap = function ( o, knew, old ) { 1794 if ( o[ knew ] !== undefined ) { 1795 o[ old ] = o[ knew ]; 1796 } 1797 }; 1798 1799 1800 /** 1801 * Provide backwards compatibility for the main DT options. Note that the new 1802 * options are mapped onto the old parameters, so this is an external interface 1803 * change only. 1804 * @param {object} init Object to map 1805 */ 1806 function _fnCompatOpts ( init ) 1807 { 1808 _fnCompatMap( init, 'ordering', 'bSort' ); 1809 _fnCompatMap( init, 'orderMulti', 'bSortMulti' ); 1810 _fnCompatMap( init, 'orderClasses', 'bSortClasses' ); 1811 _fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' ); 1812 _fnCompatMap( init, 'order', 'aaSorting' ); 1813 _fnCompatMap( init, 'orderFixed', 'aaSortingFixed' ); 1814 _fnCompatMap( init, 'paging', 'bPaginate' ); 1815 _fnCompatMap( init, 'pagingType', 'sPaginationType' ); 1816 _fnCompatMap( init, 'pageLength', 'iDisplayLength' ); 1817 _fnCompatMap( init, 'searching', 'bFilter' ); 1818 1819 // Boolean initialisation of x-scrolling 1820 if ( typeof init.sScrollX === 'boolean' ) { 1821 init.sScrollX = init.sScrollX ? '100%' : ''; 1822 } 1823 if ( typeof init.scrollX === 'boolean' ) { 1824 init.scrollX = init.scrollX ? '100%' : ''; 1825 } 1826 1827 // Column search objects are in an array, so it needs to be converted 1828 // element by element 1829 var searchCols = init.aoSearchCols; 1830 1831 if ( searchCols ) { 1832 for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) { 1833 if ( searchCols[i] ) { 1834 _fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] ); 1835 } 1836 } 1837 } 1838 } 1839 1840 1841 /** 1842 * Provide backwards compatibility for column options. Note that the new options 1843 * are mapped onto the old parameters, so this is an external interface change 1844 * only. 1845 * @param {object} init Object to map 1846 */ 1847 function _fnCompatCols ( init ) 1848 { 1849 _fnCompatMap( init, 'orderable', 'bSortable' ); 1850 _fnCompatMap( init, 'orderData', 'aDataSort' ); 1851 _fnCompatMap( init, 'orderSequence', 'asSorting' ); 1852 _fnCompatMap( init, 'orderDataType', 'sortDataType' ); 1853 1854 // orderData can be given as an integer 1855 var dataSort = init.aDataSort; 1856 if ( typeof dataSort === 'number' && ! $.isArray( dataSort ) ) { 1857 init.aDataSort = [ dataSort ]; 1858 } 1859 } 1860 1861 1862 /** 1863 * Browser feature detection for capabilities, quirks 1864 * @param {object} settings dataTables settings object 1865 * @memberof DataTable#oApi 1866 */ 1867 function _fnBrowserDetect( settings ) 1868 { 1869 // We don't need to do this every time DataTables is constructed, the values 1870 // calculated are specific to the browser and OS configuration which we 1871 // don't expect to change between initialisations 1872 if ( ! DataTable.__browser ) { 1873 var browser = {}; 1874 DataTable.__browser = browser; 1875 1876 // Scrolling feature / quirks detection 1877 var n = $('<div/>') 1878 .css( { 1879 position: 'fixed', 1880 top: 0, 1881 left: $(window).scrollLeft()*-1, // allow for scrolling 1882 height: 1, 1883 width: 1, 1884 overflow: 'hidden' 1885 } ) 1886 .append( 1887 $('<div/>') 1888 .css( { 1889 position: 'absolute', 1890 top: 1, 1891 left: 1, 1892 width: 100, 1893 overflow: 'scroll' 1894 } ) 1895 .append( 1896 $('<div/>') 1897 .css( { 1898 width: '100%', 1899 height: 10 1900 } ) 1901 ) 1902 ) 1903 .appendTo( 'body' ); 1904 1905 var outer = n.children(); 1906 var inner = outer.children(); 1907 1908 // Numbers below, in order, are: 1909 // inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth 1910 // 1911 // IE6 XP: 100 100 100 83 1912 // IE7 Vista: 100 100 100 83 1913 // IE 8+ Windows: 83 83 100 83 1914 // Evergreen Windows: 83 83 100 83 1915 // Evergreen Mac with scrollbars: 85 85 100 85 1916 // Evergreen Mac without scrollbars: 100 100 100 100 1917 1918 // Get scrollbar width 1919 browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth; 1920 1921 // IE6/7 will oversize a width 100% element inside a scrolling element, to 1922 // include the width of the scrollbar, while other browsers ensure the inner 1923 // element is contained without forcing scrolling 1924 browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100; 1925 1926 // In rtl text layout, some browsers (most, but not all) will place the 1927 // scrollbar on the left, rather than the right. 1928 browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1; 1929 1930 // IE8- don't provide height and width for getBoundingClientRect 1931 browser.bBounding = n[0].getBoundingClientRect().width ? true : false; 1932 1933 n.remove(); 1934 } 1935 1936 $.extend( settings.oBrowser, DataTable.__browser ); 1937 settings.oScroll.iBarWidth = DataTable.__browser.barWidth; 1938 } 1939 1940 1941 /** 1942 * Array.prototype reduce[Right] method, used for browsers which don't support 1943 * JS 1.6. Done this way to reduce code size, since we iterate either way 1944 * @param {object} settings dataTables settings object 1945 * @memberof DataTable#oApi 1946 */ 1947 function _fnReduce ( that, fn, init, start, end, inc ) 1948 { 1949 var 1950 i = start, 1951 value, 1952 isSet = false; 1953 1954 if ( init !== undefined ) { 1955 value = init; 1956 isSet = true; 1957 } 1958 1959 while ( i !== end ) { 1960 if ( ! that.hasOwnProperty(i) ) { 1961 continue; 1962 } 1963 1964 value = isSet ? 1965 fn( value, that[i], i, that ) : 1966 that[i]; 1967 1968 isSet = true; 1969 i += inc; 1970 } 1971 1972 return value; 1973 } 1974 1975 /** 1976 * Add a column to the list used for the table with default values 1977 * @param {object} oSettings dataTables settings object 1978 * @param {node} nTh The th element for this column 1979 * @memberof DataTable#oApi 1980 */ 1981 function _fnAddColumn( oSettings, nTh ) 1982 { 1983 // Add column to aoColumns array 1984 var oDefaults = DataTable.defaults.column; 1985 var iCol = oSettings.aoColumns.length; 1986 var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, { 1987 "nTh": nTh ? nTh : document.createElement('th'), 1988 "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '', 1989 "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol], 1990 "mData": oDefaults.mData ? oDefaults.mData : iCol, 1991 idx: iCol 1992 } ); 1993 oSettings.aoColumns.push( oCol ); 1994 1995 // Add search object for column specific search. Note that the `searchCols[ iCol ]` 1996 // passed into extend can be undefined. This allows the user to give a default 1997 // with only some of the parameters defined, and also not give a default 1998 var searchCols = oSettings.aoPreSearchCols; 1999 searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] ); 2000 2001 // Use the default column options function to initialise classes etc 2002 _fnColumnOptions( oSettings, iCol, $(nTh).data() ); 2003 } 2004 2005 2006 /** 2007 * Apply options for a column 2008 * @param {object} oSettings dataTables settings object 2009 * @param {int} iCol column index to consider 2010 * @param {object} oOptions object with sType, bVisible and bSearchable etc 2011 * @memberof DataTable#oApi 2012 */ 2013 function _fnColumnOptions( oSettings, iCol, oOptions ) 2014 { 2015 var oCol = oSettings.aoColumns[ iCol ]; 2016 var oClasses = oSettings.oClasses; 2017 var th = $(oCol.nTh); 2018 2019 // Try to get width information from the DOM. We can't get it from CSS 2020 // as we'd need to parse the CSS stylesheet. `width` option can override 2021 if ( ! oCol.sWidthOrig ) { 2022 // Width attribute 2023 oCol.sWidthOrig = th.attr('width') || null; 2024 2025 // Style attribute 2026 var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/); 2027 if ( t ) { 2028 oCol.sWidthOrig = t[1]; 2029 } 2030 } 2031 2032 /* User specified column options */ 2033 if ( oOptions !== undefined && oOptions !== null ) 2034 { 2035 // Backwards compatibility 2036 _fnCompatCols( oOptions ); 2037 2038 // Map camel case parameters to their Hungarian counterparts 2039 _fnCamelToHungarian( DataTable.defaults.column, oOptions ); 2040 2041 /* Backwards compatibility for mDataProp */ 2042 if ( oOptions.mDataProp !== undefined && !oOptions.mData ) 2043 { 2044 oOptions.mData = oOptions.mDataProp; 2045 } 2046 2047 if ( oOptions.sType ) 2048 { 2049 oCol._sManualType = oOptions.sType; 2050 } 2051 2052 // `class` is a reserved word in Javascript, so we need to provide 2053 // the ability to use a valid name for the camel case input 2054 if ( oOptions.className && ! oOptions.sClass ) 2055 { 2056 oOptions.sClass = oOptions.className; 2057 } 2058 if ( oOptions.sClass ) { 2059 th.addClass( oOptions.sClass ); 2060 } 2061 2062 $.extend( oCol, oOptions ); 2063 _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" ); 2064 2065 /* iDataSort to be applied (backwards compatibility), but aDataSort will take 2066 * priority if defined 2067 */ 2068 if ( oOptions.iDataSort !== undefined ) 2069 { 2070 oCol.aDataSort = [ oOptions.iDataSort ]; 2071 } 2072 _fnMap( oCol, oOptions, "aDataSort" ); 2073 } 2074 2075 /* Cache the data get and set functions for speed */ 2076 var mDataSrc = oCol.mData; 2077 var mData = _fnGetObjectDataFn( mDataSrc ); 2078 var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null; 2079 2080 var attrTest = function( src ) { 2081 return typeof src === 'string' && src.indexOf('@') !== -1; 2082 }; 2083 oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && ( 2084 attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter) 2085 ); 2086 oCol._setter = null; 2087 2088 oCol.fnGetData = function (rowData, type, meta) { 2089 var innerData = mData( rowData, type, undefined, meta ); 2090 2091 return mRender && type ? 2092 mRender( innerData, type, rowData, meta ) : 2093 innerData; 2094 }; 2095 oCol.fnSetData = function ( rowData, val, meta ) { 2096 return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta ); 2097 }; 2098 2099 // Indicate if DataTables should read DOM data as an object or array 2100 // Used in _fnGetRowElements 2101 if ( typeof mDataSrc !== 'number' ) { 2102 oSettings._rowReadObject = true; 2103 } 2104 2105 /* Feature sorting overrides column specific when off */ 2106 if ( !oSettings.oFeatures.bSort ) 2107 { 2108 oCol.bSortable = false; 2109 th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called 2110 } 2111 2112 /* Check that the class assignment is correct for sorting */ 2113 var bAsc = $.inArray('asc', oCol.asSorting) !== -1; 2114 var bDesc = $.inArray('desc', oCol.asSorting) !== -1; 2115 if ( !oCol.bSortable || (!bAsc && !bDesc) ) 2116 { 2117 oCol.sSortingClass = oClasses.sSortableNone; 2118 oCol.sSortingClassJUI = ""; 2119 } 2120 else if ( bAsc && !bDesc ) 2121 { 2122 oCol.sSortingClass = oClasses.sSortableAsc; 2123 oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed; 2124 } 2125 else if ( !bAsc && bDesc ) 2126 { 2127 oCol.sSortingClass = oClasses.sSortableDesc; 2128 oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed; 2129 } 2130 else 2131 { 2132 oCol.sSortingClass = oClasses.sSortable; 2133 oCol.sSortingClassJUI = oClasses.sSortJUI; 2134 } 2135 } 2136 2137 2138 /** 2139 * Adjust the table column widths for new data. Note: you would probably want to 2140 * do a redraw after calling this function! 2141 * @param {object} settings dataTables settings object 2142 * @memberof DataTable#oApi 2143 */ 2144 function _fnAdjustColumnSizing ( settings ) 2145 { 2146 /* Not interested in doing column width calculation if auto-width is disabled */ 2147 if ( settings.oFeatures.bAutoWidth !== false ) 2148 { 2149 var columns = settings.aoColumns; 2150 2151 _fnCalculateColumnWidths( settings ); 2152 for ( var i=0 , iLen=columns.length ; i<iLen ; i++ ) 2153 { 2154 columns[i].nTh.style.width = columns[i].sWidth; 2155 } 2156 } 2157 2158 var scroll = settings.oScroll; 2159 if ( scroll.sY !== '' || scroll.sX !== '') 2160 { 2161 _fnScrollDraw( settings ); 2162 } 2163 2164 _fnCallbackFire( settings, null, 'column-sizing', [settings] ); 2165 } 2166 2167 2168 /** 2169 * Covert the index of a visible column to the index in the data array (take account 2170 * of hidden columns) 2171 * @param {object} oSettings dataTables settings object 2172 * @param {int} iMatch Visible column index to lookup 2173 * @returns {int} i the data index 2174 * @memberof DataTable#oApi 2175 */ 2176 function _fnVisibleToColumnIndex( oSettings, iMatch ) 2177 { 2178 var aiVis = _fnGetColumns( oSettings, 'bVisible' ); 2179 2180 return typeof aiVis[iMatch] === 'number' ? 2181 aiVis[iMatch] : 2182 null; 2183 } 2184 2185 2186 /** 2187 * Covert the index of an index in the data array and convert it to the visible 2188 * column index (take account of hidden columns) 2189 * @param {int} iMatch Column index to lookup 2190 * @param {object} oSettings dataTables settings object 2191 * @returns {int} i the data index 2192 * @memberof DataTable#oApi 2193 */ 2194 function _fnColumnIndexToVisible( oSettings, iMatch ) 2195 { 2196 var aiVis = _fnGetColumns( oSettings, 'bVisible' ); 2197 var iPos = $.inArray( iMatch, aiVis ); 2198 2199 return iPos !== -1 ? iPos : null; 2200 } 2201 2202 2203 /** 2204 * Get the number of visible columns 2205 * @param {object} oSettings dataTables settings object 2206 * @returns {int} i the number of visible columns 2207 * @memberof DataTable#oApi 2208 */ 2209 function _fnVisbleColumns( oSettings ) 2210 { 2211 var vis = 0; 2212 2213 // No reduce in IE8, use a loop for now 2214 $.each( oSettings.aoColumns, function ( i, col ) { 2215 if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) { 2216 vis++; 2217 } 2218 } ); 2219 2220 return vis; 2221 } 2222 2223 2224 /** 2225 * Get an array of column indexes that match a given property 2226 * @param {object} oSettings dataTables settings object 2227 * @param {string} sParam Parameter in aoColumns to look for - typically 2228 * bVisible or bSearchable 2229 * @returns {array} Array of indexes with matched properties 2230 * @memberof DataTable#oApi 2231 */ 2232 function _fnGetColumns( oSettings, sParam ) 2233 { 2234 var a = []; 2235 2236 $.map( oSettings.aoColumns, function(val, i) { 2237 if ( val[sParam] ) { 2238 a.push( i ); 2239 } 2240 } ); 2241 2242 return a; 2243 } 2244 2245 2246 /** 2247 * Calculate the 'type' of a column 2248 * @param {object} settings dataTables settings object 2249 * @memberof DataTable#oApi 2250 */ 2251 function _fnColumnTypes ( settings ) 2252 { 2253 var columns = settings.aoColumns; 2254 var data = settings.aoData; 2255 var types = DataTable.ext.type.detect; 2256 var i, ien, j, jen, k, ken; 2257 var col, cell, detectedType, cache; 2258 2259 // For each column, spin over the 2260 for ( i=0, ien=columns.length ; i<ien ; i++ ) { 2261 col = columns[i]; 2262 cache = []; 2263 2264 if ( ! col.sType && col._sManualType ) { 2265 col.sType = col._sManualType; 2266 } 2267 else if ( ! col.sType ) { 2268 for ( j=0, jen=types.length ; j<jen ; j++ ) { 2269 for ( k=0, ken=data.length ; k<ken ; k++ ) { 2270 // Use a cache array so we only need to get the type data 2271 // from the formatter once (when using multiple detectors) 2272 if ( cache[k] === undefined ) { 2273 cache[k] = _fnGetCellData( settings, k, i, 'type' ); 2274 } 2275 2276 detectedType = types[j]( cache[k], settings ); 2277 2278 // If null, then this type can't apply to this column, so 2279 // rather than testing all cells, break out. There is an 2280 // exception for the last type which is `html`. We need to 2281 // scan all rows since it is possible to mix string and HTML 2282 // types 2283 if ( ! detectedType && j !== types.length-1 ) { 2284 break; 2285 } 2286 2287 // Only a single match is needed for html type since it is 2288 // bottom of the pile and very similar to string 2289 if ( detectedType === 'html' ) { 2290 break; 2291 } 2292 } 2293 2294 // Type is valid for all data points in the column - use this 2295 // type 2296 if ( detectedType ) { 2297 col.sType = detectedType; 2298 break; 2299 } 2300 } 2301 2302 // Fall back - if no type was detected, always use string 2303 if ( ! col.sType ) { 2304 col.sType = 'string'; 2305 } 2306 } 2307 } 2308 } 2309 2310 2311 /** 2312 * Take the column definitions and static columns arrays and calculate how 2313 * they relate to column indexes. The callback function will then apply the 2314 * definition found for a column to a suitable configuration object. 2315 * @param {object} oSettings dataTables settings object 2316 * @param {array} aoColDefs The aoColumnDefs array that is to be applied 2317 * @param {array} aoCols The aoColumns array that defines columns individually 2318 * @param {function} fn Callback function - takes two parameters, the calculated 2319 * column index and the definition for that column. 2320 * @memberof DataTable#oApi 2321 */ 2322 function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn ) 2323 { 2324 var i, iLen, j, jLen, k, kLen, def; 2325 var columns = oSettings.aoColumns; 2326 2327 // Column definitions with aTargets 2328 if ( aoColDefs ) 2329 { 2330 /* Loop over the definitions array - loop in reverse so first instance has priority */ 2331 for ( i=aoColDefs.length-1 ; i>=0 ; i-- ) 2332 { 2333 def = aoColDefs[i]; 2334 2335 /* Each definition can target multiple columns, as it is an array */ 2336 var aTargets = def.targets !== undefined ? 2337 def.targets : 2338 def.aTargets; 2339 2340 if ( ! $.isArray( aTargets ) ) 2341 { 2342 aTargets = [ aTargets ]; 2343 } 2344 2345 for ( j=0, jLen=aTargets.length ; j<jLen ; j++ ) 2346 { 2347 if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 ) 2348 { 2349 /* Add columns that we don't yet know about */ 2350 while( columns.length <= aTargets[j] ) 2351 { 2352 _fnAddColumn( oSettings ); 2353 } 2354 2355 /* Integer, basic index */ 2356 fn( aTargets[j], def ); 2357 } 2358 else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 ) 2359 { 2360 /* Negative integer, right to left column counting */ 2361 fn( columns.length+aTargets[j], def ); 2362 } 2363 else if ( typeof aTargets[j] === 'string' ) 2364 { 2365 /* Class name matching on TH element */ 2366 for ( k=0, kLen=columns.length ; k<kLen ; k++ ) 2367 { 2368 if ( aTargets[j] == "_all" || 2369 $(columns[k].nTh).hasClass( aTargets[j] ) ) 2370 { 2371 fn( k, def ); 2372 } 2373 } 2374 } 2375 } 2376 } 2377 } 2378 2379 // Statically defined columns array 2380 if ( aoCols ) 2381 { 2382 for ( i=0, iLen=aoCols.length ; i<iLen ; i++ ) 2383 { 2384 fn( i, aoCols[i] ); 2385 } 2386 } 2387 } 2388 2389 /** 2390 * Add a data array to the table, creating DOM node etc. This is the parallel to 2391 * _fnGatherData, but for adding rows from a Javascript source, rather than a 2392 * DOM source. 2393 * @param {object} oSettings dataTables settings object 2394 * @param {array} aData data array to be added 2395 * @param {node} [nTr] TR element to add to the table - optional. If not given, 2396 * DataTables will create a row automatically 2397 * @param {array} [anTds] Array of TD|TH elements for the row - must be given 2398 * if nTr is. 2399 * @returns {int} >=0 if successful (index of new aoData entry), -1 if failed 2400 * @memberof DataTable#oApi 2401 */ 2402 function _fnAddData ( oSettings, aDataIn, nTr, anTds ) 2403 { 2404 /* Create the object for storing information about this new row */ 2405 var iRow = oSettings.aoData.length; 2406 var oData = $.extend( true, {}, DataTable.models.oRow, { 2407 src: nTr ? 'dom' : 'data', 2408 idx: iRow 2409 } ); 2410 2411 oData._aData = aDataIn; 2412 oSettings.aoData.push( oData ); 2413 2414 /* Create the cells */ 2415 var nTd, sThisType; 2416 var columns = oSettings.aoColumns; 2417 2418 // Invalidate the column types as the new data needs to be revalidated 2419 for ( var i=0, iLen=columns.length ; i<iLen ; i++ ) 2420 { 2421 columns[i].sType = null; 2422 } 2423 2424 /* Add to the display array */ 2425 oSettings.aiDisplayMaster.push( iRow ); 2426 2427 var id = oSettings.rowIdFn( aDataIn ); 2428 if ( id !== undefined ) { 2429 oSettings.aIds[ id ] = oData; 2430 } 2431 2432 /* Create the DOM information, or register it if already present */ 2433 if ( nTr || ! oSettings.oFeatures.bDeferRender ) 2434 { 2435 _fnCreateTr( oSettings, iRow, nTr, anTds ); 2436 } 2437 2438 return iRow; 2439 } 2440 2441 2442 /** 2443 * Add one or more TR elements to the table. Generally we'd expect to 2444 * use this for reading data from a DOM sourced table, but it could be 2445 * used for an TR element. Note that if a TR is given, it is used (i.e. 2446 * it is not cloned). 2447 * @param {object} settings dataTables settings object 2448 * @param {array|node|jQuery} trs The TR element(s) to add to the table 2449 * @returns {array} Array of indexes for the added rows 2450 * @memberof DataTable#oApi 2451 */ 2452 function _fnAddTr( settings, trs ) 2453 { 2454 var row; 2455 2456 // Allow an individual node to be passed in 2457 if ( ! (trs instanceof $) ) { 2458 trs = $(trs); 2459 } 2460 2461 return trs.map( function (i, el) { 2462 row = _fnGetRowElements( settings, el ); 2463 return _fnAddData( settings, row.data, el, row.cells ); 2464 } ); 2465 } 2466 2467 2468 /** 2469 * Take a TR element and convert it to an index in aoData 2470 * @param {object} oSettings dataTables settings object 2471 * @param {node} n the TR element to find 2472 * @returns {int} index if the node is found, null if not 2473 * @memberof DataTable#oApi 2474 */ 2475 function _fnNodeToDataIndex( oSettings, n ) 2476 { 2477 return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null; 2478 } 2479 2480 2481 /** 2482 * Take a TD element and convert it into a column data index (not the visible index) 2483 * @param {object} oSettings dataTables settings object 2484 * @param {int} iRow The row number the TD/TH can be found in 2485 * @param {node} n The TD/TH element to find 2486 * @returns {int} index if the node is found, -1 if not 2487 * @memberof DataTable#oApi 2488 */ 2489 function _fnNodeToColumnIndex( oSettings, iRow, n ) 2490 { 2491 return $.inArray( n, oSettings.aoData[ iRow ].anCells ); 2492 } 2493 2494 2495 /** 2496 * Get the data for a given cell from the internal cache, taking into account data mapping 2497 * @param {object} settings dataTables settings object 2498 * @param {int} rowIdx aoData row id 2499 * @param {int} colIdx Column index 2500 * @param {string} type data get type ('display', 'type' 'filter' 'sort') 2501 * @returns {*} Cell data 2502 * @memberof DataTable#oApi 2503 */ 2504 function _fnGetCellData( settings, rowIdx, colIdx, type ) 2505 { 2506 var draw = settings.iDraw; 2507 var col = settings.aoColumns[colIdx]; 2508 var rowData = settings.aoData[rowIdx]._aData; 2509 var defaultContent = col.sDefaultContent; 2510 var cellData = col.fnGetData( rowData, type, { 2511 settings: settings, 2512 row: rowIdx, 2513 col: colIdx 2514 } ); 2515 2516 if ( cellData === undefined ) { 2517 if ( settings.iDrawError != draw && defaultContent === null ) { 2518 _fnLog( settings, 0, "Requested unknown parameter "+ 2519 (typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+ 2520 " for row "+rowIdx+", column "+colIdx, 4 ); 2521 settings.iDrawError = draw; 2522 } 2523 return defaultContent; 2524 } 2525 2526 // When the data source is null and a specific data type is requested (i.e. 2527 // not the original data), we can use default column data 2528 if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) { 2529 cellData = defaultContent; 2530 } 2531 else if ( typeof cellData === 'function' ) { 2532 // If the data source is a function, then we run it and use the return, 2533 // executing in the scope of the data object (for instances) 2534 return cellData.call( rowData ); 2535 } 2536 2537 if ( cellData === null && type == 'display' ) { 2538 return ''; 2539 } 2540 return cellData; 2541 } 2542 2543 2544 /** 2545 * Set the value for a specific cell, into the internal data cache 2546 * @param {object} settings dataTables settings object 2547 * @param {int} rowIdx aoData row id 2548 * @param {int} colIdx Column index 2549 * @param {*} val Value to set 2550 * @memberof DataTable#oApi 2551 */ 2552 function _fnSetCellData( settings, rowIdx, colIdx, val ) 2553 { 2554 var col = settings.aoColumns[colIdx]; 2555 var rowData = settings.aoData[rowIdx]._aData; 2556 2557 col.fnSetData( rowData, val, { 2558 settings: settings, 2559 row: rowIdx, 2560 col: colIdx 2561 } ); 2562 } 2563 2564 2565 // Private variable that is used to match action syntax in the data property object 2566 var __reArray = /\[.*?\]$/; 2567 var __reFn = /\(\)$/; 2568 2569 /** 2570 * Split string on periods, taking into account escaped periods 2571 * @param {string} str String to split 2572 * @return {array} Split string 2573 */ 2574 function _fnSplitObjNotation( str ) 2575 { 2576 return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) { 2577 return s.replace(/\\\./g, '.'); 2578 } ); 2579 } 2580 2581 2582 /** 2583 * Return a function that can be used to get data from a source object, taking 2584 * into account the ability to use nested objects as a source 2585 * @param {string|int|function} mSource The data source for the object 2586 * @returns {function} Data get function 2587 * @memberof DataTable#oApi 2588 */ 2589 function _fnGetObjectDataFn( mSource ) 2590 { 2591 if ( $.isPlainObject( mSource ) ) 2592 { 2593 /* Build an object of get functions, and wrap them in a single call */ 2594 var o = {}; 2595 $.each( mSource, function (key, val) { 2596 if ( val ) { 2597 o[key] = _fnGetObjectDataFn( val ); 2598 } 2599 } ); 2600 2601 return function (data, type, row, meta) { 2602 var t = o[type] || o._; 2603 return t !== undefined ? 2604 t(data, type, row, meta) : 2605 data; 2606 }; 2607 } 2608 else if ( mSource === null ) 2609 { 2610 /* Give an empty string for rendering / sorting etc */ 2611 return function (data) { // type, row and meta also passed, but not used 2612 return data; 2613 }; 2614 } 2615 else if ( typeof mSource === 'function' ) 2616 { 2617 return function (data, type, row, meta) { 2618 return mSource( data, type, row, meta ); 2619 }; 2620 } 2621 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || 2622 mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) ) 2623 { 2624 /* If there is a . in the source string then the data source is in a 2625 * nested object so we loop over the data for each level to get the next 2626 * level down. On each loop we test for undefined, and if found immediately 2627 * return. This allows entire objects to be missing and sDefaultContent to 2628 * be used if defined, rather than throwing an error 2629 */ 2630 var fetchData = function (data, type, src) { 2631 var arrayNotation, funcNotation, out, innerSrc; 2632 2633 if ( src !== "" ) 2634 { 2635 var a = _fnSplitObjNotation( src ); 2636 2637 for ( var i=0, iLen=a.length ; i<iLen ; i++ ) 2638 { 2639 // Check if we are dealing with special notation 2640 arrayNotation = a[i].match(__reArray); 2641 funcNotation = a[i].match(__reFn); 2642 2643 if ( arrayNotation ) 2644 { 2645 // Array notation 2646 a[i] = a[i].replace(__reArray, ''); 2647 2648 // Condition allows simply [] to be passed in 2649 if ( a[i] !== "" ) { 2650 data = data[ a[i] ]; 2651 } 2652 out = []; 2653 2654 // Get the remainder of the nested object to get 2655 a.splice( 0, i+1 ); 2656 innerSrc = a.join('.'); 2657 2658 // Traverse each entry in the array getting the properties requested 2659 if ( $.isArray( data ) ) { 2660 for ( var j=0, jLen=data.length ; j<jLen ; j++ ) { 2661 out.push( fetchData( data[j], type, innerSrc ) ); 2662 } 2663 } 2664 2665 // If a string is given in between the array notation indicators, that 2666 // is used to join the strings together, otherwise an array is returned 2667 var join = arrayNotation[0].substring(1, arrayNotation[0].length-1); 2668 data = (join==="") ? out : out.join(join); 2669 2670 // The inner call to fetchData has already traversed through the remainder 2671 // of the source requested, so we exit from the loop 2672 break; 2673 } 2674 else if ( funcNotation ) 2675 { 2676 // Function call 2677 a[i] = a[i].replace(__reFn, ''); 2678 data = data[ a[i] ](); 2679 continue; 2680 } 2681 2682 if ( data === null || data[ a[i] ] === undefined ) 2683 { 2684 return undefined; 2685 } 2686 data = data[ a[i] ]; 2687 } 2688 } 2689 2690 return data; 2691 }; 2692 2693 return function (data, type) { // row and meta also passed, but not used 2694 return fetchData( data, type, mSource ); 2695 }; 2696 } 2697 else 2698 { 2699 /* Array or flat object mapping */ 2700 return function (data, type) { // row and meta also passed, but not used 2701 return data[mSource]; 2702 }; 2703 } 2704 } 2705 2706 2707 /** 2708 * Return a function that can be used to set data from a source object, taking 2709 * into account the ability to use nested objects as a source 2710 * @param {string|int|function} mSource The data source for the object 2711 * @returns {function} Data set function 2712 * @memberof DataTable#oApi 2713 */ 2714 function _fnSetObjectDataFn( mSource ) 2715 { 2716 if ( $.isPlainObject( mSource ) ) 2717 { 2718 /* Unlike get, only the underscore (global) option is used for for 2719 * setting data since we don't know the type here. This is why an object 2720 * option is not documented for `mData` (which is read/write), but it is 2721 * for `mRender` which is read only. 2722 */ 2723 return _fnSetObjectDataFn( mSource._ ); 2724 } 2725 else if ( mSource === null ) 2726 { 2727 /* Nothing to do when the data source is null */ 2728 return function () {}; 2729 } 2730 else if ( typeof mSource === 'function' ) 2731 { 2732 return function (data, val, meta) { 2733 mSource( data, 'set', val, meta ); 2734 }; 2735 } 2736 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || 2737 mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) ) 2738 { 2739 /* Like the get, we need to get data from a nested object */ 2740 var setData = function (data, val, src) { 2741 var a = _fnSplitObjNotation( src ), b; 2742 var aLast = a[a.length-1]; 2743 var arrayNotation, funcNotation, o, innerSrc; 2744 2745 for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ ) 2746 { 2747 // Check if we are dealing with an array notation request 2748 arrayNotation = a[i].match(__reArray); 2749 funcNotation = a[i].match(__reFn); 2750 2751 if ( arrayNotation ) 2752 { 2753 a[i] = a[i].replace(__reArray, ''); 2754 data[ a[i] ] = []; 2755 2756 // Get the remainder of the nested object to set so we can recurse 2757 b = a.slice(); 2758 b.splice( 0, i+1 ); 2759 innerSrc = b.join('.'); 2760 2761 // Traverse each entry in the array setting the properties requested 2762 if ( $.isArray( val ) ) 2763 { 2764 for ( var j=0, jLen=val.length ; j<jLen ; j++ ) 2765 { 2766 o = {}; 2767 setData( o, val[j], innerSrc ); 2768 data[ a[i] ].push( o ); 2769 } 2770 } 2771 else 2772 { 2773 // We've been asked to save data to an array, but it 2774 // isn't array data to be saved. Best that can be done 2775 // is to just save the value. 2776 data[ a[i] ] = val; 2777 } 2778 2779 // The inner call to setData has already traversed through the remainder 2780 // of the source and has set the data, thus we can exit here 2781 return; 2782 } 2783 else if ( funcNotation ) 2784 { 2785 // Function call 2786 a[i] = a[i].replace(__reFn, ''); 2787 data = data[ a[i] ]( val ); 2788 } 2789 2790 // If the nested object doesn't currently exist - since we are 2791 // trying to set the value - create it 2792 if ( data[ a[i] ] === null || data[ a[i] ] === undefined ) 2793 { 2794 data[ a[i] ] = {}; 2795 } 2796 data = data[ a[i] ]; 2797 } 2798 2799 // Last item in the input - i.e, the actual set 2800 if ( aLast.match(__reFn ) ) 2801 { 2802 // Function call 2803 data = data[ aLast.replace(__reFn, '') ]( val ); 2804 } 2805 else 2806 { 2807 // If array notation is used, we just want to strip it and use the property name 2808 // and assign the value. If it isn't used, then we get the result we want anyway 2809 data[ aLast.replace(__reArray, '') ] = val; 2810 } 2811 }; 2812 2813 return function (data, val) { // meta is also passed in, but not used 2814 return setData( data, val, mSource ); 2815 }; 2816 } 2817 else 2818 { 2819 /* Array or flat object mapping */ 2820 return function (data, val) { // meta is also passed in, but not used 2821 data[mSource] = val; 2822 }; 2823 } 2824 } 2825 2826 2827 /** 2828 * Return an array with the full table data 2829 * @param {object} oSettings dataTables settings object 2830 * @returns array {array} aData Master data array 2831 * @memberof DataTable#oApi 2832 */ 2833 function _fnGetDataMaster ( settings ) 2834 { 2835 return _pluck( settings.aoData, '_aData' ); 2836 } 2837 2838 2839 /** 2840 * Nuke the table 2841 * @param {object} oSettings dataTables settings object 2842 * @memberof DataTable#oApi 2843 */ 2844 function _fnClearTable( settings ) 2845 { 2846 settings.aoData.length = 0; 2847 settings.aiDisplayMaster.length = 0; 2848 settings.aiDisplay.length = 0; 2849 settings.aIds = {}; 2850 } 2851 2852 2853 /** 2854 * Take an array of integers (index array) and remove a target integer (value - not 2855 * the key!) 2856 * @param {array} a Index array to target 2857 * @param {int} iTarget value to find 2858 * @memberof DataTable#oApi 2859 */ 2860 function _fnDeleteIndex( a, iTarget, splice ) 2861 { 2862 var iTargetIndex = -1; 2863 2864 for ( var i=0, iLen=a.length ; i<iLen ; i++ ) 2865 { 2866 if ( a[i] == iTarget ) 2867 { 2868 iTargetIndex = i; 2869 } 2870 else if ( a[i] > iTarget ) 2871 { 2872 a[i]--; 2873 } 2874 } 2875 2876 if ( iTargetIndex != -1 && splice === undefined ) 2877 { 2878 a.splice( iTargetIndex, 1 ); 2879 } 2880 } 2881 2882 2883 /**
2884 * Mark cached data as invalid such that a re-read of the data will occur when 2885 * the cached data is next requested. Also update from the data source object. 2886 * 2887 * @param {object} settings DataTables settings object 2888 * @param {int} rowIdx Row index to invalidate 2889 * @param {string} [src] Source to invalidate from: undefined, 'auto', 'dom' 2890 * or 'data' 2891 * @param {int} [colIdx] Column index to invalidate. If undefined the whole 2892 * row will be invalidated 2893 * @memberof DataTable#oApi 2894 * 2895 * @todo For the modularisation of v1.11 this will need to become a callback, so 2896 * the sort and filter methods can subscribe to it. That will required 2897 * initialisation options for sorting, which is why it is not already baked in 2898 */ 2899 function _fnInvalidate( settings, rowIdx, src, colIdx ) 2900 { 2901 var row = settings.aoData[ rowIdx ]; 2902 var i, ien; 2903 var cellWrite = function ( cell, col ) { 2904 // This is very frustrating, but in IE if you just write directly 2905 // to innerHTML, and elements that are overwritten are GC'ed, 2906 // even if there is a reference to them elsewhere 2907 while ( cell.childNodes.length ) { 2908 cell.removeChild( cell.firstChild ); 2909 } 2910 2911 cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' ); 2912 }; 2913 2914 // Are we reading last data from DOM or the data object? 2915 if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) { 2916 // Read the data from the DOM 2917 row._aData = _fnGetRowElements( 2918 settings, row, colIdx, colIdx === undefined ? undefined : row._aData 2919 ) 2920 .data; 2921 } 2922 else { 2923 // Reading from data object, update the DOM 2924 var cells = row.anCells; 2925 2926 if ( cells ) { 2927 if ( colIdx !== undefined ) { 2928 cellWrite( cells[colIdx], colIdx ); 2929 } 2930 else { 2931 for ( i=0, ien=cells.length ; i<ien ; i++ ) { 2932 cellWrite( cells[i], i ); 2933 } 2934 } 2935 } 2936 } 2937 2938 // For both row and cell invalidation, the cached data for sorting and 2939 // filtering is nulled out 2940 row._aSortData = null; 2941 row._aFilterData = null; 2942 2943 // Invalidate the type for a specific column (if given) or all columns since 2944 // the data might have changed 2945 var cols = settings.aoColumns; 2946 if ( colIdx !== undefined ) { 2947 cols[ colIdx ].sType = null; 2948 } 2949 else { 2950 for ( i=0, ien=cols.length ; i<ien ; i++ ) { 2951 cols[i].sType = null; 2952 } 2953 2954 // Update DataTables special `DT_*` attributes for the row 2955 _fnRowAttributes( settings, row ); 2956 } 2957 } 2958 2959 2960 /** 2961 * Build a data source object from an HTML row, reading the contents of the 2962 * cells that are in the row. 2963 * 2964 * @param {object} settings DataTables settings object 2965 * @param {node|object} TR element from which to read data or existing row 2966 * object from which to re-read the data from the cells 2967 * @param {int} [colIdx] Optional column index 2968 * @param {array|object} [d] Data source object. If `colIdx` is given then this 2969 * parameter should also be given and will be used to write the data into. 2970 * Only the column in question will be written 2971 * @returns {object} Object with two parameters: `data` the data read, in 2972 * document order, and `cells` and array of nodes (they can be useful to the 2973 * caller, so rather than needing a second traversal to get them, just return 2974 * them from here). 2975 * @memberof DataTable#oApi 2976 */ 2977 function _fnGetRowElements( settings, row, colIdx, d ) 2978 { 2979 var 2980 tds = [], 2981 td = row.firstChild, 2982 name, col, o, i=0, contents, 2983 columns = settings.aoColumns, 2984 objectRead = settings._rowReadObject; 2985 2986 // Allow the data object to be passed in, or construct 2987 d = d !== undefined ? 2988 d : 2989 objectRead ? 2990 {} : 2991 []; 2992 2993 var attr = function ( str, td ) { 2994 if ( typeof str === 'string' ) { 2995 var idx = str.indexOf('@'); 2996 2997 if ( idx !== -1 ) { 2998 var attr = str.substring( idx+1 ); 2999 var setter = _fnSetObjectDataFn( str ); 3000 setter( d, td.getAttribute( attr ) ); 3001 } 3002 } 3003 }; 3004 3005 // Read data from a cell and store into the data object 3006 var cellProcess = function ( cell ) { 3007 if ( colIdx === undefined || colIdx === i ) { 3008 col = columns[i]; 3009 contents = $.trim(cell.innerHTML); 3010 3011 if ( col && col._bAttrSrc ) { 3012 var setter = _fnSetObjectDataFn( col.mData._ ); 3013 setter( d, contents ); 3014 3015 attr( col.mData.sort, cell ); 3016 attr( col.mData.type, cell ); 3017 attr( col.mData.filter, cell ); 3018 } 3019 else { 3020 // Depending on the `data` option for the columns the data can 3021 // be read to either an object or an array.
vendor: 10,997 bytes, lines 3022-3444
3022 if ( objectRead ) { 3023 if ( ! col._setter ) { 3024 // Cache the setter function 3025 col._setter = _fnSetObjectDataFn( col.mData ); 3026 } 3027 col._setter( d, contents ); 3028 } 3029 else { 3030 d[i] = contents; 3031 } 3032 } 3033 } 3034 3035 i++; 3036 }; 3037 3038 if ( td ) { 3039 // `tr` element was passed in 3040 while ( td ) { 3041 name = td.nodeName.toUpperCase(); 3042 3043 if ( name == "TD" || name == "TH" ) { 3044 cellProcess( td ); 3045 tds.push( td ); 3046 } 3047 3048 td = td.nextSibling; 3049 } 3050 } 3051 else { 3052 // Existing row object passed in 3053 tds = row.anCells; 3054 3055 for ( var j=0, jen=tds.length ; j<jen ; j++ ) { 3056 cellProcess( tds[j] ); 3057 } 3058 } 3059 3060 // Read the ID from the DOM if present 3061 var rowNode = row.firstChild ? row : row.nTr; 3062 3063 if ( rowNode ) { 3064 var id = rowNode.getAttribute( 'id' ); 3065 3066 if ( id ) { 3067 _fnSetObjectDataFn( settings.rowId )( d, id ); 3068 } 3069 } 3070 3071 return { 3072 data: d, 3073 cells: tds 3074 }; 3075 } 3076 /** 3077 * Create a new TR element (and it's TD children) for a row 3078 * @param {object} oSettings dataTables settings object 3079 * @param {int} iRow Row to consider 3080 * @param {node} [nTrIn] TR element to add to the table - optional. If not given, 3081 * DataTables will create a row automatically 3082 * @param {array} [anTds] Array of TD|TH elements for the row - must be given 3083 * if nTr is. 3084 * @memberof DataTable#oApi 3085 */ 3086 function _fnCreateTr ( oSettings, iRow, nTrIn, anTds ) 3087 { 3088 var 3089 row = oSettings.aoData[iRow], 3090 rowData = row._aData, 3091 cells = [], 3092 nTr, nTd, oCol, 3093 i, iLen; 3094 3095 if ( row.nTr === null ) 3096 { 3097 nTr = nTrIn || document.createElement('tr'); 3098 3099 row.nTr = nTr; 3100 row.anCells = cells; 3101 3102 /* Use a private property on the node to allow reserve mapping from the node 3103 * to the aoData array for fast look up 3104 */ 3105 nTr._DT_RowIndex = iRow; 3106 3107 /* Special parameters can be given by the data source to be used on the row */ 3108 _fnRowAttributes( oSettings, row ); 3109 3110 /* Process each column */ 3111 for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) 3112 { 3113 oCol = oSettings.aoColumns[i]; 3114 3115 nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType ); 3116 nTd._DT_CellIndex = { 3117 row: iRow, 3118 column: i 3119 }; 3120 3121 cells.push( nTd ); 3122 3123 // Need to create the HTML if new, or if a rendering function is defined 3124 if ( (!nTrIn || oCol.mRender || oCol.mData !== i) && 3125 (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display') 3126 ) { 3127 nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' ); 3128 } 3129 3130 /* Add user defined class */ 3131 if ( oCol.sClass ) 3132 { 3133 nTd.className += ' '+oCol.sClass; 3134 } 3135 3136 // Visibility - add or remove as required 3137 if ( oCol.bVisible && ! nTrIn ) 3138 { 3139 nTr.appendChild( nTd ); 3140 } 3141 else if ( ! oCol.bVisible && nTrIn ) 3142 { 3143 nTd.parentNode.removeChild( nTd ); 3144 } 3145 3146 if ( oCol.fnCreatedCell ) 3147 { 3148 oCol.fnCreatedCell.call( oSettings.oInstance, 3149 nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i 3150 ); 3151 } 3152 } 3153 3154 _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow, cells] ); 3155 } 3156 3157 // Remove once webkit bug 131819 and Chromium bug 365619 have been resolved 3158 // and deployed 3159 row.nTr.setAttribute( 'role', 'row' ); 3160 } 3161 3162 3163 /** 3164 * Add attributes to a row based on the special `DT_*` parameters in a data 3165 * source object. 3166 * @param {object} settings DataTables settings object 3167 * @param {object} DataTables row object for the row to be modified 3168 * @memberof DataTable#oApi 3169 */ 3170 function _fnRowAttributes( settings, row ) 3171 { 3172 var tr = row.nTr; 3173 var data = row._aData; 3174 3175 if ( tr ) { 3176 var id = settings.rowIdFn( data ); 3177 3178 if ( id ) { 3179 tr.id = id; 3180 } 3181 3182 if ( data.DT_RowClass ) { 3183 // Remove any classes added by DT_RowClass before 3184 var a = data.DT_RowClass.split(' '); 3185 row.__rowc = row.__rowc ? 3186 _unique( row.__rowc.concat( a ) ) : 3187 a; 3188 3189 $(tr) 3190 .removeClass( row.__rowc.join(' ') ) 3191 .addClass( data.DT_RowClass ); 3192 } 3193 3194 if ( data.DT_RowAttr ) { 3195 $(tr).attr( data.DT_RowAttr ); 3196 } 3197 3198 if ( data.DT_RowData ) { 3199 $(tr).data( data.DT_RowData ); 3200 } 3201 } 3202 } 3203 3204 3205 /** 3206 * Create the HTML header for the table 3207 * @param {object} oSettings dataTables settings object 3208 * @memberof DataTable#oApi 3209 */ 3210 function _fnBuildHead( oSettings ) 3211 { 3212 var i, ien, cell, row, column; 3213 var thead = oSettings.nTHead; 3214 var tfoot = oSettings.nTFoot; 3215 var createHeader = $('th, td', thead).length === 0; 3216 var classes = oSettings.oClasses; 3217 var columns = oSettings.aoColumns; 3218 3219 if ( createHeader ) { 3220 row = $('<tr/>').appendTo( thead ); 3221 } 3222 3223 for ( i=0, ien=columns.length ; i<ien ; i++ ) { 3224 column = columns[i]; 3225 cell = $( column.nTh ).addClass( column.sClass ); 3226 3227 if ( createHeader ) { 3228 cell.appendTo( row ); 3229 } 3230 3231 // 1.11 move into sorting 3232 if ( oSettings.oFeatures.bSort ) { 3233 cell.addClass( column.sSortingClass ); 3234 3235 if ( column.bSortable !== false ) { 3236 cell 3237 .attr( 'tabindex', oSettings.iTabIndex ) 3238 .attr( 'aria-controls', oSettings.sTableId ); 3239 3240 _fnSortAttachListener( oSettings, column.nTh, i ); 3241 } 3242 } 3243 3244 if ( column.sTitle != cell[0].innerHTML ) { 3245 cell.html( column.sTitle ); 3246 } 3247 3248 _fnRenderer( oSettings, 'header' )( 3249 oSettings, cell, column, classes 3250 ); 3251 } 3252 3253 if ( createHeader ) { 3254 _fnDetectHeader( oSettings.aoHeader, thead ); 3255 } 3256 3257 /* ARIA role for the rows */ 3258 $(thead).find('>tr').attr('role', 'row'); 3259 3260 /* Deal with the footer - add classes if required */ 3261 $(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH ); 3262 $(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH ); 3263 3264 // Cache the footer cells. Note that we only take the cells from the first 3265 // row in the footer. If there is more than one row the user wants to 3266 // interact with, they need to use the table().foot() method. Note also this 3267 // allows cells to be used for multiple columns using colspan 3268 if ( tfoot !== null ) { 3269 var cells = oSettings.aoFooter[0]; 3270 3271 for ( i=0, ien=cells.length ; i<ien ; i++ ) { 3272 column = columns[i]; 3273 column.nTf = cells[i].cell; 3274 3275 if ( column.sClass ) { 3276 $(column.nTf).addClass( column.sClass ); 3277 } 3278 } 3279 } 3280 } 3281 3282 3283 /** 3284 * Draw the header (or footer) element based on the column visibility states. The 3285 * methodology here is to use the layout array from _fnDetectHeader, modified for 3286 * the instantaneous column visibility, to construct the new layout. The grid is 3287 * traversed over cell at a time in a rows x columns grid fashion, although each 3288 * cell insert can cover multiple elements in the grid - which is tracks using the 3289 * aApplied array. Cell inserts in the grid will only occur where there isn't 3290 * already a cell in that position. 3291 * @param {object} oSettings dataTables settings object 3292 * @param array {objects} aoSource Layout array from _fnDetectHeader 3293 * @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc, 3294 * @memberof DataTable#oApi 3295 */ 3296 function _fnDrawHead( oSettings, aoSource, bIncludeHidden ) 3297 { 3298 var i, iLen, j, jLen, k, kLen, n, nLocalTr; 3299 var aoLocal = []; 3300 var aApplied = []; 3301 var iColumns = oSettings.aoColumns.length; 3302 var iRowspan, iColspan; 3303 3304 if ( ! aoSource ) 3305 { 3306 return; 3307 } 3308 3309 if ( bIncludeHidden === undefined ) 3310 { 3311 bIncludeHidden = false; 3312 } 3313 3314 /* Make a copy of the master layout array, but without the visible columns in it */ 3315 for ( i=0, iLen=aoSource.length ; i<iLen ; i++ ) 3316 { 3317 aoLocal[i] = aoSource[i].slice(); 3318 aoLocal[i].nTr = aoSource[i].nTr; 3319 3320 /* Remove any columns which are currently hidden */ 3321 for ( j=iColumns-1 ; j>=0 ; j-- ) 3322 { 3323 if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden ) 3324 { 3325 aoLocal[i].splice( j, 1 ); 3326 } 3327 } 3328 3329 /* Prep the applied array - it needs an element for each row */ 3330 aApplied.push( [] ); 3331 } 3332 3333 for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ ) 3334 { 3335 nLocalTr = aoLocal[i].nTr; 3336 3337 /* All cells are going to be replaced, so empty out the row */ 3338 if ( nLocalTr ) 3339 { 3340 while( (n = nLocalTr.firstChild) ) 3341 { 3342 nLocalTr.removeChild( n ); 3343 } 3344 } 3345 3346 for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ ) 3347 { 3348 iRowspan = 1; 3349 iColspan = 1; 3350 3351 /* Check to see if there is already a cell (row/colspan) covering our target 3352 * insert point. If there is, then there is nothing to do. 3353 */ 3354 if ( aApplied[i][j] === undefined ) 3355 { 3356 nLocalTr.appendChild( aoLocal[i][j].cell ); 3357 aApplied[i][j] = 1; 3358 3359 /* Expand the cell to cover as many rows as needed */ 3360 while ( aoLocal[i+iRowspan] !== undefined && 3361 aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell ) 3362 { 3363 aApplied[i+iRowspan][j] = 1; 3364 iRowspan++; 3365 } 3366 3367 /* Expand the cell to cover as many columns as needed */ 3368 while ( aoLocal[i][j+iColspan] !== undefined && 3369 aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell ) 3370 { 3371 /* Must update the applied array over the rows for the columns */ 3372 for ( k=0 ; k<iRowspan ; k++ ) 3373 { 3374 aApplied[i+k][j+iColspan] = 1; 3375 } 3376 iColspan++; 3377 } 3378 3379 /* Do the actual expansion in the DOM */ 3380 $(aoLocal[i][j].cell) 3381 .attr('rowspan', iRowspan) 3382 .attr('colspan', iColspan); 3383 } 3384 } 3385 } 3386 } 3387 3388 3389 /** 3390 * Insert the required TR nodes into the table for display 3391 * @param {object} oSettings dataTables settings object 3392 * @memberof DataTable#oApi 3393 */ 3394 function _fnDraw( oSettings ) 3395 { 3396 /* Provide a pre-callback function which can be used to cancel the draw is false is returned */ 3397 var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] ); 3398 if ( $.inArray( false, aPreDraw ) !== -1 ) 3399 { 3400 _fnProcessingDisplay( oSettings, false ); 3401 return; 3402 } 3403 3404 var i, iLen, n; 3405 var anRows = []; 3406 var iRowCount = 0; 3407 var asStripeClasses = oSettings.asStripeClasses; 3408 var iStripes = asStripeClasses.length; 3409 var iOpenRows = oSettings.aoOpenRows.length; 3410 var oLang = oSettings.oLanguage; 3411 var iInitDisplayStart = oSettings.iInitDisplayStart; 3412 var bServerSide = _fnDataSource( oSettings ) == 'ssp'; 3413 var aiDisplay = oSettings.aiDisplay; 3414 3415 oSettings.bDrawing = true; 3416 3417 /* Check and see if we have an initial draw position from state saving */ 3418 if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 ) 3419 { 3420 oSettings._iDisplayStart = bServerSide ? 3421 iInitDisplayStart : 3422 iInitDisplayStart >= oSettings.fnRecordsDisplay() ? 3423 0 : 3424 iInitDisplayStart; 3425 3426 oSettings.iInitDisplayStart = -1; 3427 } 3428 3429 var iDisplayStart = oSettings._iDisplayStart; 3430 var iDisplayEnd = oSettings.fnDisplayEnd(); 3431 3432 /* Server-side processing draw intercept */ 3433 if ( oSettings.bDeferLoading ) 3434 { 3435 oSettings.bDeferLoading = false; 3436 oSettings.iDraw++; 3437 _fnProcessingDisplay( oSettings, false ); 3438 } 3439 else if ( !bServerSide ) 3440 { 3441 oSettings.iDraw++; 3442 } 3443 else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) ) 3444 {
vendor: 10,503 bytes, lines 3444-3833
3444 3445 return; 3446 } 3447 3448 if ( aiDisplay.length !== 0 ) 3449 { 3450 var iStart = bServerSide ? 0 : iDisplayStart; 3451 var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd; 3452 3453 for ( var j=iStart ; j<iEnd ; j++ ) 3454 { 3455 var iDataIndex = aiDisplay[j]; 3456 var aoData = oSettings.aoData[ iDataIndex ]; 3457 if ( aoData.nTr === null ) 3458 { 3459 _fnCreateTr( oSettings, iDataIndex ); 3460 } 3461 3462 var nRow = aoData.nTr; 3463 3464 /* Remove the old striping classes and then add the new one */ 3465 if ( iStripes !== 0 ) 3466 { 3467 var sStripe = asStripeClasses[ iRowCount % iStripes ]; 3468 if ( aoData._sRowStripe != sStripe ) 3469 { 3470 $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe ); 3471 aoData._sRowStripe = sStripe; 3472 } 3473 } 3474 3475 // Row callback functions - might want to manipulate the row 3476 // iRowCount and j are not currently documented. Are they at all 3477 // useful? 3478 _fnCallbackFire( oSettings, 'aoRowCallback', null, 3479 [nRow, aoData._aData, iRowCount, j, iDataIndex] ); 3480 3481 anRows.push( nRow ); 3482 iRowCount++; 3483 } 3484 } 3485 else 3486 { 3487 /* Table is empty - create a row with an empty message in it */ 3488 var sZero = oLang.sZeroRecords; 3489 if ( oSettings.iDraw == 1 && _fnDataSource( oSettings ) == 'ajax' ) 3490 { 3491 sZero = oLang.sLoadingRecords; 3492 } 3493 else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 ) 3494 { 3495 sZero = oLang.sEmptyTable; 3496 } 3497 3498 anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } ) 3499 .append( $('<td />', { 3500 'valign': 'top', 3501 'colSpan': _fnVisbleColumns( oSettings ), 3502 'class': oSettings.oClasses.sRowEmpty 3503 } ).html( sZero ) )[0]; 3504 } 3505 3506 /* Header and footer callbacks */ 3507 _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0], 3508 _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] ); 3509 3510 _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0], 3511 _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] ); 3512 3513 var body = $(oSettings.nTBody); 3514 3515 body.children().detach(); 3516 body.append( $(anRows) ); 3517 3518 /* Call all required callback functions for the end of a draw */ 3519 _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] ); 3520 3521 /* Draw is complete, sorting and filtering must be as well */ 3522 oSettings.bSorted = false; 3523 oSettings.bFiltered = false; 3524 oSettings.bDrawing = false; 3525 } 3526 3527 3528 /** 3529 * Redraw the table - taking account of the various features which are enabled 3530 * @param {object} oSettings dataTables settings object 3531 * @param {boolean} [holdPosition] Keep the current paging position. By default 3532 * the paging is reset to the first page 3533 * @memberof DataTable#oApi 3534 */ 3535 function _fnReDraw( settings, holdPosition ) 3536 { 3537 var 3538 features = settings.oFeatures, 3539 sort = features.bSort, 3540 filter = features.bFilter; 3541 3542 if ( sort ) { 3543 _fnSort( settings ); 3544 } 3545 3546 if ( filter ) { 3547 _fnFilterComplete( settings, settings.oPreviousSearch ); 3548 } 3549 else { 3550 // No filtering, so we want to just use the display master 3551 settings.aiDisplay = settings.aiDisplayMaster.slice(); 3552 } 3553 3554 if ( holdPosition !== true ) { 3555 settings._iDisplayStart = 0; 3556 } 3557 3558 // Let any modules know about the draw hold position state (used by 3559 // scrolling internally) 3560 settings._drawHold = holdPosition; 3561 3562 _fnDraw( settings ); 3563 3564 settings._drawHold = false; 3565 } 3566 3567 3568 /** 3569 * Add the options to the page HTML for the table 3570 * @param {object} oSettings dataTables settings object 3571 * @memberof DataTable#oApi 3572 */ 3573 function _fnAddOptionsHtml ( oSettings ) 3574 { 3575 var classes = oSettings.oClasses; 3576 var table = $(oSettings.nTable); 3577 var holding = $('<div/>').insertBefore( table ); // Holding element for speed 3578 var features = oSettings.oFeatures; 3579 3580 // All DataTables are wrapped in a div 3581 var insert = $('<div/>', { 3582 id: oSettings.sTableId+'_wrapper', 3583 'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter) 3584 } ); 3585 3586 oSettings.nHolding = holding[0]; 3587 oSettings.nTableWrapper = insert[0]; 3588 oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling; 3589 3590 /* Loop over the user set positioning and place the elements as needed */ 3591 var aDom = oSettings.sDom.split(''); 3592 var featureNode, cOption, nNewNode, cNext, sAttr, j; 3593 for ( var i=0 ; i<aDom.length ; i++ ) 3594 { 3595 featureNode = null; 3596 cOption = aDom[i]; 3597 3598 if ( cOption == '<' ) 3599 { 3600 /* New container div */ 3601 nNewNode = $('<div/>')[0]; 3602 3603 /* Check to see if we should append an id and/or a class name to the container */ 3604 cNext = aDom[i+1]; 3605 if ( cNext == "'" || cNext == '"' ) 3606 { 3607 sAttr = ""; 3608 j = 2; 3609 while ( aDom[i+j] != cNext ) 3610 { 3611 sAttr += aDom[i+j]; 3612 j++; 3613 } 3614 3615 /* Replace jQuery UI constants @todo depreciated */ 3616 if ( sAttr == "H" ) 3617 { 3618 sAttr = classes.sJUIHeader; 3619 } 3620 else if ( sAttr == "F" ) 3621 { 3622 sAttr = classes.sJUIFooter; 3623 } 3624 3625 /* The attribute can be in the format of "#id.class", "#id" or "class" This logic 3626 * breaks the string into parts and applies them as needed 3627 */ 3628 if ( sAttr.indexOf('.') != -1 ) 3629 { 3630 var aSplit = sAttr.split('.'); 3631 nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1); 3632 nNewNode.className = aSplit[1]; 3633 } 3634 else if ( sAttr.charAt(0) == "#" ) 3635 { 3636 nNewNode.id = sAttr.substr(1, sAttr.length-1); 3637 } 3638 else 3639 { 3640 nNewNode.className = sAttr; 3641 } 3642 3643 i += j; /* Move along the position array */ 3644 } 3645 3646 insert.append( nNewNode ); 3647 insert = $(nNewNode); 3648 } 3649 else if ( cOption == '>' ) 3650 { 3651 /* End container div */ 3652 insert = insert.parent(); 3653 } 3654 // @todo Move options into their own plugins? 3655 else if ( cOption == 'l' && features.bPaginate && features.bLengthChange ) 3656 { 3657 /* Length */ 3658 featureNode = _fnFeatureHtmlLength( oSettings ); 3659 } 3660 else if ( cOption == 'f' && features.bFilter ) 3661 { 3662 /* Filter */ 3663 featureNode = _fnFeatureHtmlFilter( oSettings ); 3664 } 3665 else if ( cOption == 'r' && features.bProcessing ) 3666 { 3667 /* pRocessing */ 3668 featureNode = _fnFeatureHtmlProcessing( oSettings ); 3669 } 3670 else if ( cOption == 't' ) 3671 { 3672 /* Table */ 3673 featureNode = _fnFeatureHtmlTable( oSettings ); 3674 } 3675 else if ( cOption == 'i' && features.bInfo ) 3676 { 3677 /* Info */ 3678 featureNode = _fnFeatureHtmlInfo( oSettings ); 3679 } 3680 else if ( cOption == 'p' && features.bPaginate ) 3681 { 3682 /* Pagination */ 3683 featureNode = _fnFeatureHtmlPaginate( oSettings ); 3684 } 3685 else if ( DataTable.ext.feature.length !== 0 ) 3686 { 3687 /* Plug-in features */ 3688 var aoFeatures = DataTable.ext.feature; 3689 for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ ) 3690 { 3691 if ( cOption == aoFeatures[k].cFeature ) 3692 { 3693 featureNode = aoFeatures[k].fnInit( oSettings ); 3694 break; 3695 } 3696 } 3697 } 3698 3699 /* Add to the 2D features array */ 3700 if ( featureNode ) 3701 { 3702 var aanFeatures = oSettings.aanFeatures; 3703 3704 if ( ! aanFeatures[cOption] ) 3705 { 3706 aanFeatures[cOption] = []; 3707 } 3708 3709 aanFeatures[cOption].push( featureNode ); 3710 insert.append( featureNode ); 3711 } 3712 } 3713 3714 /* Built our DOM structure - replace the holding div with what we want */ 3715 holding.replaceWith( insert ); 3716 oSettings.nHolding = null; 3717 } 3718 3719 3720 /** 3721 * Use the DOM source to create up an array of header cells. The idea here is to 3722 * create a layout grid (array) of rows x columns, which contains a reference 3723 * to the cell that that point in the grid (regardless of col/rowspan), such that 3724 * any column / row could be removed and the new grid constructed 3725 * @param array {object} aLayout Array to store the calculated layout in 3726 * @param {node} nThead The header/footer element for the table 3727 * @memberof DataTable#oApi 3728 */ 3729 function _fnDetectHeader ( aLayout, nThead ) 3730 { 3731 var nTrs = $(nThead).children('tr'); 3732 var nTr, nCell; 3733 var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan; 3734 var bUnique; 3735 var fnShiftCol = function ( a, i, j ) { 3736 var k = a[i]; 3737 while ( k[j] ) { 3738 j++; 3739 } 3740 return j; 3741 }; 3742 3743 aLayout.splice( 0, aLayout.length ); 3744 3745 /* We know how many rows there are in the layout - so prep it */ 3746 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ ) 3747 { 3748 aLayout.push( [] ); 3749 } 3750 3751 /* Calculate a layout array */ 3752 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ ) 3753 { 3754 nTr = nTrs[i]; 3755 iColumn = 0; 3756 3757 /* For every cell in the row... */ 3758 nCell = nTr.firstChild; 3759 while ( nCell ) { 3760 if ( nCell.nodeName.toUpperCase() == "TD" || 3761 nCell.nodeName.toUpperCase() == "TH" ) 3762 { 3763 /* Get the col and rowspan attributes from the DOM and sanitise them */ 3764 iColspan = nCell.getAttribute('colspan') * 1; 3765 iRowspan = nCell.getAttribute('rowspan') * 1; 3766 iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan; 3767 iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan; 3768 3769 /* There might be colspan cells already in this row, so shift our target 3770 * accordingly 3771 */ 3772 iColShifted = fnShiftCol( aLayout, i, iColumn ); 3773 3774 /* Cache calculation for unique columns */ 3775 bUnique = iColspan === 1 ? true : false; 3776 3777 /* If there is col / rowspan, copy the information into the layout grid */ 3778 for ( l=0 ; l<iColspan ; l++ ) 3779 { 3780 for ( k=0 ; k<iRowspan ; k++ ) 3781 { 3782 aLayout[i+k][iColShifted+l] = { 3783 "cell": nCell, 3784 "unique": bUnique 3785 }; 3786 aLayout[i+k].nTr = nTr; 3787 } 3788 } 3789 } 3790 nCell = nCell.nextSibling; 3791 } 3792 } 3793 } 3794 3795 3796 /** 3797 * Get an array of unique th elements, one for each column 3798 * @param {object} oSettings dataTables settings object 3799 * @param {node} nHeader automatically detect the layout from this node - optional 3800 * @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional 3801 * @returns array {node} aReturn list of unique th's 3802 * @memberof DataTable#oApi 3803 */ 3804 function _fnGetUniqueThs ( oSettings, nHeader, aLayout ) 3805 { 3806 var aReturn = []; 3807 if ( !aLayout ) 3808 { 3809 aLayout = oSettings.aoHeader; 3810 if ( nHeader ) 3811 { 3812 aLayout = []; 3813 _fnDetectHeader( aLayout, nHeader ); 3814 } 3815 } 3816 3817 for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ ) 3818 { 3819 for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ ) 3820 { 3821 if ( aLayout[i][j].unique && 3822 (!aReturn[j] || !oSettings.bSortCellsTop) ) 3823 { 3824 aReturn[j] = aLayout[i][j].cell; 3825 } 3826 } 3827 } 3828 3829 return aReturn; 3830 } 3831 3832 /** 3833 *
vendor: 47,598 bytes, lines 3833-5472
3833Create an Ajax call based on the table's settings, taking into account that 3834 * parameters can have multiple forms, and backwards compatibility. 3835 * 3836 * @param {object} oSettings dataTables settings object 3837 * @param {array} data Data to send to the server, required by 3838 * DataTables - may be augmented by developer callbacks 3839 * @param {function} fn Callback function to run when data is obtained 3840 */ 3841 function _fnBuildAjax( oSettings, data, fn ) 3842 { 3843 // Compatibility with 1.9-, allow fnServerData and event to manipulate 3844 _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] ); 3845 3846 // Convert to object based for 1.10+ if using the old array scheme which can 3847 // come from server-side processing or serverParams 3848 if ( data && $.isArray(data) ) { 3849 var tmp = {}; 3850 var rbracket = /(.*?)\[\]$/; 3851 3852 $.each( data, function (key, val) { 3853 var match = val.name.match(rbracket); 3854 3855 if ( match ) { 3856 // Support for arrays 3857 var name = match[0]; 3858 3859 if ( ! tmp[ name ] ) { 3860 tmp[ name ] = []; 3861 } 3862 tmp[ name ].push( val.value ); 3863 } 3864 else { 3865 tmp[val.name] = val.value; 3866 } 3867 } ); 3868 data = tmp; 3869 } 3870 3871 var ajaxData; 3872 var ajax = oSettings.ajax; 3873 var instance = oSettings.oInstance; 3874 var callback = function ( json ) { 3875 _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] ); 3876 fn( json ); 3877 }; 3878 3879 if ( $.isPlainObject( ajax ) && ajax.data ) 3880 { 3881 ajaxData = ajax.data; 3882 3883 var newData = typeof ajaxData === 'function' ? 3884 ajaxData( data, oSettings ) : // fn can manipulate data or return 3885 ajaxData; // an object object or array to merge 3886 3887 // If the function returned something, use that alone 3888 data = typeof ajaxData === 'function' && newData ? 3889 newData : 3890 $.extend( true, data, newData ); 3891 3892 // Remove the data property as we've resolved it already and don't want 3893 // jQuery to do it again (it is restored at the end of the function) 3894 delete ajax.data; 3895 } 3896 3897 var baseAjax = { 3898 "data": data, 3899 "success": function (json) { 3900 var error = json.error || json.sError; 3901 if ( error ) { 3902 _fnLog( oSettings, 0, error ); 3903 } 3904 3905 oSettings.json = json; 3906 callback( json ); 3907 }, 3908 "dataType": "json", 3909 "cache": false, 3910 "type": oSettings.sServerMethod, 3911 "error": function (xhr, error, thrown) { 3912 var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] ); 3913 3914 if ( $.inArray( true, ret ) === -1 ) { 3915 if ( error == "parsererror" ) { 3916 _fnLog( oSettings, 0, 'Invalid JSON response', 1 ); 3917 } 3918 else if ( xhr.readyState === 4 ) { 3919 _fnLog( oSettings, 0, 'Ajax error', 7 ); 3920 } 3921 } 3922 3923 _fnProcessingDisplay( oSettings, false ); 3924 } 3925 }; 3926 3927 // Store the data submitted for the API 3928 oSettings.oAjaxData = data; 3929 3930 // Allow plug-ins and external processes to modify the data 3931 _fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] ); 3932 3933 if ( oSettings.fnServerData ) 3934 { 3935 // DataTables 1.9- compatibility 3936 oSettings.fnServerData.call( instance, 3937 oSettings.sAjaxSource, 3938 $.map( data, function (val, key) { // Need to convert back to 1.9 trad format 3939 return { name: key, value: val }; 3940 } ), 3941 callback, 3942 oSettings 3943 ); 3944 } 3945 else if ( oSettings.sAjaxSource || typeof ajax === 'string' ) 3946 { 3947 // DataTables 1.9- compatibility 3948 oSettings.jqXHR = $.ajax( $.extend( baseAjax, { 3949 url: ajax || oSettings.sAjaxSource 3950 } ) ); 3951 } 3952 else if ( typeof ajax === 'function' ) 3953 { 3954 // Is a function - let the caller define what needs to be done 3955 oSettings.jqXHR = ajax.call( instance, data, callback, oSettings ); 3956 } 3957 else 3958 { 3959 // Object to extend the base settings 3960 oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) ); 3961 3962 // Restore for next time around 3963 ajax.data = ajaxData; 3964 } 3965 } 3966 3967 3968 /** 3969 * Update the table using an Ajax call 3970 * @param {object} settings dataTables settings object 3971 * @returns {boolean} Block the table drawing or not 3972 * @memberof DataTable#oApi 3973 */ 3974 function _fnAjaxUpdate( settings ) 3975 { 3976 if ( settings.bAjaxDataGet ) { 3977 settings.iDraw++; 3978 _fnProcessingDisplay( settings, true ); 3979 3980 _fnBuildAjax( 3981 settings, 3982 _fnAjaxParameters( settings ), 3983 function(json) { 3984 _fnAjaxUpdateDraw( settings, json ); 3985 } 3986 ); 3987 3988 return false; 3989 } 3990 return true; 3991 } 3992 3993 3994 /** 3995 * Build up the parameters in an object needed for a server-side processing 3996 * request. Note that this is basically done twice, is different ways - a modern 3997 * method which is used by default in DataTables 1.10 which uses objects and 3998 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if 3999 * the sAjaxSource option is used in the initialisation, or the legacyAjax 4000 * option is set. 4001 * @param {object} oSettings dataTables settings object 4002 * @returns {bool} block the table drawing or not 4003 * @memberof DataTable#oApi 4004 */ 4005 function _fnAjaxParameters( settings ) 4006 { 4007 var 4008 columns = settings.aoColumns, 4009 columnCount = columns.length, 4010 features = settings.oFeatures, 4011 preSearch = settings.oPreviousSearch, 4012 preColSearch = settings.aoPreSearchCols, 4013 i, data = [], dataProp, column, columnSearch, 4014 sort = _fnSortFlatten( settings ), 4015 displayStart = settings._iDisplayStart, 4016 displayLength = features.bPaginate !== false ? 4017 settings._iDisplayLength : 4018 -1; 4019 4020 var param = function ( name, value ) { 4021 data.push( { 'name': name, 'value': value } ); 4022 }; 4023 4024 // DataTables 1.9- compatible method 4025 param( 'sEcho', settings.iDraw ); 4026 param( 'iColumns', columnCount ); 4027 param( 'sColumns', _pluck( columns, 'sName' ).join(',') ); 4028 param( 'iDisplayStart', displayStart ); 4029 param( 'iDisplayLength', displayLength ); 4030 4031 // DataTables 1.10+ method 4032 var d = { 4033 draw: settings.iDraw, 4034 columns: [], 4035 order: [], 4036 start: displayStart, 4037 length: displayLength, 4038 search: { 4039 value: preSearch.sSearch, 4040 regex: preSearch.bRegex 4041 } 4042 }; 4043 4044 for ( i=0 ; i<columnCount ; i++ ) { 4045 column = columns[i]; 4046 columnSearch = preColSearch[i]; 4047 dataProp = typeof column.mData=="function" ? 'function' : column.mData ; 4048 4049 d.columns.push( { 4050 data: dataProp, 4051 name: column.sName, 4052 searchable: column.bSearchable, 4053 orderable: column.bSortable, 4054 search: { 4055 value: columnSearch.sSearch, 4056 regex: columnSearch.bRegex 4057 } 4058 } ); 4059 4060 param( "mDataProp_"+i, dataProp ); 4061 4062 if ( features.bFilter ) { 4063 param( 'sSearch_'+i, columnSearch.sSearch ); 4064 param( 'bRegex_'+i, columnSearch.bRegex ); 4065 param( 'bSearchable_'+i, column.bSearchable ); 4066 } 4067 4068 if ( features.bSort ) { 4069 param( 'bSortable_'+i, column.bSortable ); 4070 } 4071 } 4072 4073 if ( features.bFilter ) { 4074 param( 'sSearch', preSearch.sSearch ); 4075 param( 'bRegex', preSearch.bRegex ); 4076 } 4077 4078 if ( features.bSort ) { 4079 $.each( sort, function ( i, val ) { 4080 d.order.push( { column: val.col, dir: val.dir } ); 4081 4082 param( 'iSortCol_'+i, val.col ); 4083 param( 'sSortDir_'+i, val.dir ); 4084 } ); 4085 4086 param( 'iSortingCols', sort.length ); 4087 } 4088 4089 // If the legacy.ajax parameter is null, then we automatically decide which 4090 // form to use, based on sAjaxSource 4091 var legacy = DataTable.ext.legacy.ajax; 4092 if ( legacy === null ) { 4093 return settings.sAjaxSource ? data : d; 4094 } 4095 4096 // Otherwise, if legacy has been specified then we use that to decide on the 4097 // form 4098 return legacy ? data : d; 4099 } 4100 4101 4102 /** 4103 * Data the data from the server (nuking the old) and redraw the table 4104 * @param {object} oSettings dataTables settings object 4105 * @param {object} json json data return from the server. 4106 * @param {string} json.sEcho Tracking flag for DataTables to match requests 4107 * @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering 4108 * @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering 4109 * @param {array} json.aaData The data to display on this page 4110 * @param {string} [json.sColumns] Column ordering (sName, comma separated) 4111 * @memberof DataTable#oApi 4112 */ 4113 function _fnAjaxUpdateDraw ( settings, json ) 4114 { 4115 // v1.10 uses camelCase variables, while 1.9 uses Hungarian notation. 4116 // Support both 4117 var compat = function ( old, modern ) { 4118 return json[old] !== undefined ? json[old] : json[modern]; 4119 }; 4120 4121 var data = _fnAjaxDataSrc( settings, json ); 4122 var draw = compat( 'sEcho', 'draw' ); 4123 var recordsTotal = compat( 'iTotalRecords', 'recordsTotal' ); 4124 var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' ); 4125 4126 if ( draw ) { 4127 // Protect against out of sequence returns 4128 if ( draw*1 < settings.iDraw ) { 4129 return; 4130 } 4131 settings.iDraw = draw * 1; 4132 } 4133 4134 _fnClearTable( settings ); 4135 settings._iRecordsTotal = parseInt(recordsTotal, 10); 4136 settings._iRecordsDisplay = parseInt(recordsFiltered, 10); 4137 4138 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 4139 _fnAddData( settings, data[i] ); 4140 } 4141 settings.aiDisplay = settings.aiDisplayMaster.slice(); 4142 4143 settings.bAjaxDataGet = false; 4144 _fnDraw( settings ); 4145 4146 if ( ! settings._bInitComplete ) { 4147 _fnInitComplete( settings, json ); 4148 } 4149 4150 settings.bAjaxDataGet = true; 4151 _fnProcessingDisplay( settings, false ); 4152 } 4153 4154 4155 /** 4156 * Get the data from the JSON data source to use for drawing a table. Using 4157 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the 4158 * source object, or from a processing function. 4159 * @param {object} oSettings dataTables settings object 4160 * @param {object} json Data source object / array from the server 4161 * @return {array} Array of data to use 4162 */ 4163 function _fnAjaxDataSrc ( oSettings, json ) 4164 { 4165 var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ? 4166 oSettings.ajax.dataSrc : 4167 oSettings.sAjaxDataProp; // Compatibility with 1.9-. 4168 4169 // Compatibility with 1.9-. In order to read from aaData, check if the 4170 // default has been changed, if not, check for aaData 4171 if ( dataSrc === 'data' ) { 4172 return json.aaData || json[dataSrc]; 4173 } 4174 4175 return dataSrc !== "" ? 4176 _fnGetObjectDataFn( dataSrc )( json ) : 4177 json; 4178 } 4179 4180 /** 4181 * Generate the node required for filtering text 4182 * @returns {node} Filter control element 4183 * @param {object} oSettings dataTables settings object 4184 * @memberof DataTable#oApi 4185 */ 4186 function _fnFeatureHtmlFilter ( settings ) 4187 { 4188 var classes = settings.oClasses; 4189 var tableId = settings.sTableId; 4190 var language = settings.oLanguage; 4191 var previousSearch = settings.oPreviousSearch; 4192 var features = settings.aanFeatures; 4193 var input = '<input type="search" class="'+classes.sFilterInput+'"/>'; 4194 4195 var str = language.sSearch; 4196 str = str.match(/_INPUT_/) ? 4197 str.replace('_INPUT_', input) : 4198 str+input; 4199 4200 var filter = $('<div/>', { 4201 'id': ! features.f ? tableId+'_filter' : null, 4202 'class': classes.sFilter 4203 } ) 4204 .append( $('<label/>' ).append( str ) ); 4205 4206 var searchFn = function() { 4207 /* Update all other filter input elements for the new display */ 4208 var n = features.f; 4209 var val = !this.value ? "" : this.value; // mental IE8 fix :-( 4210 4211 /* Now do the filter */ 4212 if ( val != previousSearch.sSearch ) { 4213 _fnFilterComplete( settings, { 4214 "sSearch": val, 4215 "bRegex": previousSearch.bRegex, 4216 "bSmart": previousSearch.bSmart , 4217 "bCaseInsensitive": previousSearch.bCaseInsensitive 4218 } ); 4219 4220 // Need to redraw, without resorting 4221 settings._iDisplayStart = 0; 4222 _fnDraw( settings ); 4223 } 4224 }; 4225 4226 var searchDelay = settings.searchDelay !== null ? 4227 settings.searchDelay : 4228 _fnDataSource( settings ) === 'ssp' ? 4229 400 : 4230 0; 4231 4232 var jqFilter = $('input', filter) 4233 .val( previousSearch.sSearch ) 4234 .attr( 'placeholder', language.sSearchPlaceholder ) 4235 .on( 4236 'keyup.DT search.DT input.DT paste.DT cut.DT', 4237 searchDelay ? 4238 _fnThrottle( searchFn, searchDelay ) : 4239 searchFn 4240 ) 4241 .on( 'keypress.DT', function(e) { 4242 /* Prevent form submission */ 4243 if ( e.keyCode == 13 ) { 4244 return false; 4245 } 4246 } ) 4247 .attr('aria-controls', tableId); 4248 4249 // Update the input elements whenever the table is filtered 4250 $(settings.nTable).on( 'search.dt.DT', function ( ev, s ) { 4251 if ( settings === s ) { 4252 // IE9 throws an 'unknown error' if document.activeElement is used 4253 // inside an iframe or frame... 4254 try { 4255 if ( jqFilter[0] !== document.activeElement ) { 4256 jqFilter.val( previousSearch.sSearch ); 4257 } 4258 } 4259 catch ( e ) {} 4260 } 4261 } ); 4262 4263 return filter[0]; 4264 } 4265 4266 4267 /** 4268 * Filter the table using both the global filter and column based filtering 4269 * @param {object} oSettings dataTables settings object 4270 * @param {object} oSearch search information 4271 * @param {int} [iForce] force a research of the master array (1) or not (undefined or 0) 4272 * @memberof DataTable#oApi 4273 */ 4274 function _fnFilterComplete ( oSettings, oInput, iForce ) 4275 { 4276 var oPrevSearch = oSettings.oPreviousSearch; 4277 var aoPrevSearch = oSettings.aoPreSearchCols; 4278 var fnSaveFilter = function ( oFilter ) { 4279 /* Save the filtering values */ 4280 oPrevSearch.sSearch = oFilter.sSearch; 4281 oPrevSearch.bRegex = oFilter.bRegex; 4282 oPrevSearch.bSmart = oFilter.bSmart; 4283 oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive; 4284 }; 4285 var fnRegex = function ( o ) { 4286 // Backwards compatibility with the bEscapeRegex option 4287 return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex; 4288 }; 4289 4290 // Resolve any column types that are unknown due to addition or invalidation 4291 // @todo As per sort - can this be moved into an event handler? 4292 _fnColumnTypes( oSettings ); 4293 4294 /* In server-side processing all filtering is done by the server, so no point hanging around here */ 4295 if ( _fnDataSource( oSettings ) != 'ssp' ) 4296 { 4297 /* Global filter */ 4298 _fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive ); 4299 fnSaveFilter( oInput ); 4300 4301 /* Now do the individual column filter */ 4302 for ( var i=0 ; i<aoPrevSearch.length ; i++ ) 4303 { 4304 _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]), 4305 aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive ); 4306 } 4307 4308 /* Custom filtering */ 4309 _fnFilterCustom( oSettings ); 4310 } 4311 else 4312 { 4313 fnSaveFilter( oInput ); 4314 } 4315 4316 /* Tell the draw function we have been filtering */ 4317 oSettings.bFiltered = true; 4318 _fnCallbackFire( oSettings, null, 'search', [oSettings] ); 4319 } 4320 4321 4322 /** 4323 * Apply custom filtering functions 4324 * @param {object} oSettings dataTables settings object 4325 * @memberof DataTable#oApi 4326 */ 4327 function _fnFilterCustom( settings ) 4328 { 4329 var filters = DataTable.ext.search; 4330 var displayRows = settings.aiDisplay; 4331 var row, rowIdx; 4332 4333 for ( var i=0, ien=filters.length ; i<ien ; i++ ) { 4334 var rows = []; 4335 4336 // Loop over each row and see if it should be included 4337 for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) { 4338 rowIdx = displayRows[ j ]; 4339 row = settings.aoData[ rowIdx ]; 4340 4341 if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) { 4342 rows.push( rowIdx ); 4343 } 4344 } 4345 4346 // So the array reference doesn't break set the results into the 4347 // existing array 4348 displayRows.length = 0; 4349 $.merge( displayRows, rows ); 4350 } 4351 } 4352 4353 4354 /** 4355 * Filter the table on a per-column basis 4356 * @param {object} oSettings dataTables settings object 4357 * @param {string} sInput string to filter on 4358 * @param {int} iColumn column to filter 4359 * @param {bool} bRegex treat search string as a regular expression or not 4360 * @param {bool} bSmart use smart filtering or not 4361 * @param {bool} bCaseInsensitive Do case insenstive matching or not 4362 * @memberof DataTable#oApi 4363 */ 4364 function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive ) 4365 { 4366 if ( searchStr === '' ) { 4367 return; 4368 } 4369 4370 var data; 4371 var out = []; 4372 var display = settings.aiDisplay; 4373 var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive ); 4374 4375 for ( var i=0 ; i<display.length ; i++ ) { 4376 data = settings.aoData[ display[i] ]._aFilterData[ colIdx ]; 4377 4378 if ( rpSearch.test( data ) ) { 4379 out.push( display[i] ); 4380 } 4381 } 4382 4383 settings.aiDisplay = out; 4384 } 4385 4386 4387 /** 4388 * Filter the data table based on user input and draw the table 4389 * @param {object} settings dataTables settings object 4390 * @param {string} input string to filter on 4391 * @param {int} force optional - force a research of the master array (1) or not (undefined or 0) 4392 * @param {bool} regex treat as a regular expression or not 4393 * @param {bool} smart perform smart filtering or not 4394 * @param {bool} caseInsensitive Do case insenstive matching or not 4395 * @memberof DataTable#oApi 4396 */ 4397 function _fnFilter( settings, input, force, regex, smart, caseInsensitive ) 4398 { 4399 var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive ); 4400 var prevSearch = settings.oPreviousSearch.sSearch; 4401 var displayMaster = settings.aiDisplayMaster; 4402 var display, invalidated, i; 4403 var filtered = []; 4404 4405 // Need to take account of custom filtering functions - always filter 4406 if ( DataTable.ext.search.length !== 0 ) { 4407 force = true; 4408 } 4409 4410 // Check if any of the rows were invalidated 4411 invalidated = _fnFilterData( settings ); 4412 4413 // If the input is blank - we just want the full data set 4414 if ( input.length <= 0 ) { 4415 settings.aiDisplay = displayMaster.slice(); 4416 } 4417 else { 4418 // New search - start from the master array 4419 if ( invalidated || 4420 force || 4421 prevSearch.length > input.length || 4422 input.indexOf(prevSearch) !== 0 || 4423 settings.bSorted // On resort, the display master needs to be 4424 // re-filtered since indexes will have changed 4425 ) { 4426 settings.aiDisplay = displayMaster.slice(); 4427 } 4428 4429 // Search the display array 4430 display = settings.aiDisplay; 4431 4432 for ( i=0 ; i<display.length ; i++ ) { 4433 if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) { 4434 filtered.push( display[i] ); 4435 } 4436 } 4437 4438 settings.aiDisplay = filtered; 4439 } 4440 } 4441 4442 4443 /** 4444 * Build a regular expression object suitable for searching a table 4445 * @param {string} sSearch string to search for 4446 * @param {bool} bRegex treat as a regular expression or not 4447 * @param {bool} bSmart perform smart filtering or not 4448 * @param {bool} bCaseInsensitive Do case insensitive matching or not 4449 * @returns {RegExp} constructed object 4450 * @memberof DataTable#oApi 4451 */ 4452 function _fnFilterCreateSearch( search, regex, smart, caseInsensitive ) 4453 { 4454 search = regex ? 4455 search : 4456 _fnEscapeRegex( search ); 4457 4458 if ( smart ) { 4459 /* For smart filtering we want to allow the search to work regardless of 4460 * word order. We also want double quoted text to be preserved, so word 4461 * order is important - a la google. So this is what we want to 4462 * generate: 4463 * 4464 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$ 4465 */ 4466 var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) { 4467 if ( word.charAt(0) === '"' ) { 4468 var m = word.match( /^"(.*)"$/ ); 4469 word = m ? m[1] : word; 4470 } 4471 4472 return word.replace('"', ''); 4473 } ); 4474 4475 search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$'; 4476 } 4477 4478 return new RegExp( search, caseInsensitive ? 'i' : '' ); 4479 } 4480 4481 4482 /** 4483 * Escape a string such that it can be used in a regular expression 4484 * @param {string} sVal string to escape 4485 * @returns {string} escaped string 4486 * @memberof DataTable#oApi 4487 */ 4488 var _fnEscapeRegex = DataTable.util.escapeRegex; 4489 4490 var __filter_div = $('<div>')[0]; 4491 var __filter_div_textContent = __filter_div.textContent !== undefined; 4492 4493 // Update the filtering data for each row if needed (by invalidation or first run) 4494 function _fnFilterData ( settings ) 4495 { 4496 var columns = settings.aoColumns; 4497 var column; 4498 var i, j, ien, jen, filterData, cellData, row; 4499 var fomatters = DataTable.ext.type.search; 4500 var wasInvalidated = false; 4501 4502 for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 4503 row = settings.aoData[i]; 4504 4505 if ( ! row._aFilterData ) { 4506 filterData = []; 4507 4508 for ( j=0, jen=columns.length ; j<jen ; j++ ) { 4509 column = columns[j]; 4510 4511 if ( column.bSearchable ) { 4512 cellData = _fnGetCellData( settings, i, j, 'filter' ); 4513 4514 if ( fomatters[ column.sType ] ) { 4515 cellData = fomatters[ column.sType ]( cellData ); 4516 } 4517 4518 // Search in DataTables 1.10 is string based. In 1.11 this 4519 // should be altered to also allow strict type checking. 4520 if ( cellData === null ) { 4521 cellData = ''; 4522 } 4523 4524 if ( typeof cellData !== 'string' && cellData.toString ) { 4525 cellData = cellData.toString(); 4526 } 4527 } 4528 else { 4529 cellData = ''; 4530 } 4531 4532 // If it looks like there is an HTML entity in the string, 4533 // attempt to decode it so sorting works as expected. Note that 4534 // we could use a single line of jQuery to do this, but the DOM 4535 // method used here is much faster http://jsperf.com/html-decode 4536 if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) { 4537 __filter_div.innerHTML = cellData; 4538 cellData = __filter_div_textContent ? 4539 __filter_div.textContent : 4540 __filter_div.innerText; 4541 } 4542 4543 if ( cellData.replace ) { 4544 cellData = cellData.replace(/[\r\n]/g, ''); 4545 } 4546 4547 filterData.push( cellData ); 4548 } 4549 4550 row._aFilterData = filterData; 4551 row._sFilterRow = filterData.join(' '); 4552 wasInvalidated = true; 4553 } 4554 } 4555 4556 return wasInvalidated; 4557 } 4558 4559 4560 /** 4561 * Convert from the internal Hungarian notation to camelCase for external 4562 * interaction 4563 * @param {object} obj Object to convert 4564 * @returns {object} Inverted object 4565 * @memberof DataTable#oApi 4566 */ 4567 function _fnSearchToCamel ( obj ) 4568 { 4569 return { 4570 search: obj.sSearch, 4571 smart: obj.bSmart, 4572 regex: obj.bRegex, 4573 caseInsensitive: obj.bCaseInsensitive 4574 }; 4575 } 4576 4577 4578 4579 /** 4580 * Convert from camelCase notation to the internal Hungarian. We could use the 4581 * Hungarian convert function here, but this is cleaner 4582 * @param {object} obj Object to convert 4583 * @returns {object} Inverted object 4584 * @memberof DataTable#oApi 4585 */ 4586 function _fnSearchToHung ( obj ) 4587 { 4588 return { 4589 sSearch: obj.search, 4590 bSmart: obj.smart, 4591 bRegex: obj.regex, 4592 bCaseInsensitive: obj.caseInsensitive 4593 }; 4594 } 4595 4596 /** 4597 * Generate the node required for the info display 4598 * @param {object} oSettings dataTables settings object 4599 * @returns {node} Information element 4600 * @memberof DataTable#oApi 4601 */ 4602 function _fnFeatureHtmlInfo ( settings ) 4603 { 4604 var 4605 tid = settings.sTableId, 4606 nodes = settings.aanFeatures.i, 4607 n = $('<div/>', { 4608 'class': settings.oClasses.sInfo, 4609 'id': ! nodes ? tid+'_info' : null 4610 } ); 4611 4612 if ( ! nodes ) { 4613 // Update display on each draw 4614 settings.aoDrawCallback.push( { 4615 "fn": _fnUpdateInfo, 4616 "sName": "information" 4617 } ); 4618 4619 n 4620 .attr( 'role', 'status' ) 4621 .attr( 'aria-live', 'polite' ); 4622 4623 // Table is described by our info div 4624 $(settings.nTable).attr( 'aria-describedby', tid+'_info' ); 4625 } 4626 4627 return n[0]; 4628 } 4629 4630 4631 /** 4632 * Update the information elements in the display 4633 * @param {object} settings dataTables settings object 4634 * @memberof DataTable#oApi 4635 */ 4636 function _fnUpdateInfo ( settings ) 4637 { 4638 /* Show information about the table */ 4639 var nodes = settings.aanFeatures.i; 4640 if ( nodes.length === 0 ) { 4641 return; 4642 } 4643 4644 var 4645 lang = settings.oLanguage, 4646 start = settings._iDisplayStart+1, 4647 end = settings.fnDisplayEnd(), 4648 max = settings.fnRecordsTotal(), 4649 total = settings.fnRecordsDisplay(), 4650 out = total ? 4651 lang.sInfo : 4652 lang.sInfoEmpty; 4653 4654 if ( total !== max ) { 4655 /* Record set after filtering */ 4656 out += ' ' + lang.sInfoFiltered; 4657 } 4658 4659 // Convert the macros 4660 out += lang.sInfoPostFix; 4661 out = _fnInfoMacros( settings, out ); 4662 4663 var callback = lang.fnInfoCallback; 4664 if ( callback !== null ) { 4665 out = callback.call( settings.oInstance, 4666 settings, start, end, max, total, out 4667 ); 4668 } 4669 4670 $(nodes).html( out ); 4671 } 4672 4673 4674 function _fnInfoMacros ( settings, str ) 4675 { 4676 // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only 4677 // internally 4678 var 4679 formatter = settings.fnFormatNumber, 4680 start = settings._iDisplayStart+1, 4681 len = settings._iDisplayLength, 4682 vis = settings.fnRecordsDisplay(), 4683 all = len === -1; 4684 4685 return str. 4686 replace(/_START_/g, formatter.call( settings, start ) ). 4687 replace(/_END_/g, formatter.call( settings, settings.fnDisplayEnd() ) ). 4688 replace(/_MAX_/g, formatter.call( settings, settings.fnRecordsTotal() ) ). 4689 replace(/_TOTAL_/g, formatter.call( settings, vis ) ). 4690 replace(/_PAGE_/g, formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ). 4691 replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) ); 4692 } 4693 4694 4695 4696 /** 4697 * Draw the table for the first time, adding all required features 4698 * @param {object} settings dataTables settings object 4699 * @memberof DataTable#oApi 4700 */ 4701 function _fnInitialise ( settings ) 4702 { 4703 var i, iLen, iAjaxStart=settings.iInitDisplayStart; 4704 var columns = settings.aoColumns, column; 4705 var features = settings.oFeatures; 4706 var deferLoading = settings.bDeferLoading; // value modified by the draw 4707 4708 /* Ensure that the table data is fully initialised */ 4709 if ( ! settings.bInitialised ) { 4710 setTimeout( function(){ _fnInitialise( settings ); }, 200 ); 4711 return; 4712 } 4713 4714 /* Show the display HTML options */ 4715 _fnAddOptionsHtml( settings ); 4716 4717 /* Build and draw the header / footer for the table */ 4718 _fnBuildHead( settings ); 4719 _fnDrawHead( settings, settings.aoHeader ); 4720 _fnDrawHead( settings, settings.aoFooter ); 4721 4722 /* Okay to show that something is going on now */ 4723 _fnProcessingDisplay( settings, true ); 4724 4725 /* Calculate sizes for columns */ 4726 if ( features.bAutoWidth ) { 4727 _fnCalculateColumnWidths( settings ); 4728 } 4729 4730 for ( i=0, iLen=columns.length ; i<iLen ; i++ ) { 4731 column = columns[i]; 4732 4733 if ( column.sWidth ) { 4734 column.nTh.style.width = _fnStringToCss( column.sWidth ); 4735 } 4736 } 4737 4738 _fnCallbackFire( settings, null, 'preInit', [settings] ); 4739 4740 // If there is default sorting required - let's do it. The sort function 4741 // will do the drawing for us. Otherwise we draw the table regardless of the 4742 // Ajax source - this allows the table to look initialised for Ajax sourcing 4743 // data (show 'loading' message possibly) 4744 _fnReDraw( settings ); 4745 4746 // Server-side processing init complete is done by _fnAjaxUpdateDraw 4747 var dataSrc = _fnDataSource( settings ); 4748 if ( dataSrc != 'ssp' || deferLoading ) { 4749 // if there is an ajax source load the data 4750 if ( dataSrc == 'ajax' ) { 4751 _fnBuildAjax( settings, [], function(json) { 4752 var aData = _fnAjaxDataSrc( settings, json ); 4753 4754 // Got the data - add it to the table 4755 for ( i=0 ; i<aData.length ; i++ ) { 4756 _fnAddData( settings, aData[i] ); 4757 } 4758 4759 // Reset the init display for cookie saving. We've already done 4760 // a filter, and therefore cleared it before. So we need to make 4761 // it appear 'fresh' 4762 settings.iInitDisplayStart = iAjaxStart; 4763 4764 _fnReDraw( settings ); 4765 4766 _fnProcessingDisplay( settings, false ); 4767 _fnInitComplete( settings, json ); 4768 }, settings ); 4769 } 4770 else { 4771 _fnProcessingDisplay( settings, false ); 4772 _fnInitComplete( settings ); 4773 } 4774 } 4775 } 4776 4777 4778 /** 4779 * Draw the table for the first time, adding all required features 4780 * @param {object} oSettings dataTables settings object 4781 * @param {object} [json] JSON from the server that completed the table, if using Ajax source 4782 * with client-side processing (optional) 4783 * @memberof DataTable#oApi 4784 */ 4785 function _fnInitComplete ( settings, json ) 4786 { 4787 settings._bInitComplete = true; 4788 4789 // When data was added after the initialisation (data or Ajax) we need to 4790 // calculate the column sizing 4791 if ( json || settings.oInit.aaData ) { 4792 _fnAdjustColumnSizing( settings ); 4793 } 4794 4795 _fnCallbackFire( settings, null, 'plugin-init', [settings, json] ); 4796 _fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] ); 4797 } 4798 4799 4800 function _fnLengthChange ( settings, val ) 4801 { 4802 var len = parseInt( val, 10 ); 4803 settings._iDisplayLength = len; 4804 4805 _fnLengthOverflow( settings ); 4806 4807 // Fire length change event 4808 _fnCallbackFire( settings, null, 'length', [settings, len] ); 4809 } 4810 4811 4812 /** 4813 * Generate the node required for user display length changing 4814 * @param {object} settings dataTables settings object 4815 * @returns {node} Display length feature node 4816 * @memberof DataTable#oApi 4817 */ 4818 function _fnFeatureHtmlLength ( settings ) 4819 { 4820 var 4821 classes = settings.oClasses, 4822 tableId = settings.sTableId, 4823 menu = settings.aLengthMenu, 4824 d2 = $.isArray( menu[0] ), 4825 lengths = d2 ? menu[0] : menu, 4826 language = d2 ? menu[1] : menu; 4827 4828 var select = $('<select/>', { 4829 'name': tableId+'_length', 4830 'aria-controls': tableId, 4831 'class': classes.sLengthSelect 4832 } ); 4833 4834 for ( var i=0, ien=lengths.length ; i<ien ; i++ ) { 4835 select[0][ i ] = new Option( 4836 typeof language[i] === 'number' ? 4837 settings.fnFormatNumber( language[i] ) : 4838 language[i], 4839 lengths[i] 4840 ); 4841 } 4842 4843 var div = $('<div><label/></div>').addClass( classes.sLength ); 4844 if ( ! settings.aanFeatures.l ) { 4845 div[0].id = tableId+'_length'; 4846 } 4847 4848 div.children().append( 4849 settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML ) 4850 ); 4851 4852 // Can't use `select` variable as user might provide their own and the 4853 // reference is broken by the use of outerHTML 4854 $('select', div) 4855 .val( settings._iDisplayLength ) 4856 .on( 'change.DT', function(e) { 4857 _fnLengthChange( settings, $(this).val() ); 4858 _fnDraw( settings ); 4859 } ); 4860 4861 // Update node value whenever anything changes the table's length 4862 $(settings.nTable).on( 'length.dt.DT', function (e, s, len) { 4863 if ( settings === s ) { 4864 $('select', div).val( len ); 4865 } 4866 } ); 4867 4868 return div[0]; 4869 } 4870 4871 4872 4873 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 4874 * Note that most of the paging logic is done in 4875 * DataTable.ext.pager 4876 */ 4877 4878 /** 4879 * Generate the node required for default pagination 4880 * @param {object} oSettings dataTables settings object 4881 * @returns {node} Pagination feature node 4882 * @memberof DataTable#oApi 4883 */ 4884 function _fnFeatureHtmlPaginate ( settings ) 4885 { 4886 var 4887 type = settings.sPaginationType, 4888 plugin = DataTable.ext.pager[ type ], 4889 modern = typeof plugin === 'function', 4890 redraw = function( settings ) { 4891 _fnDraw( settings ); 4892 }, 4893 node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0], 4894 features = settings.aanFeatures; 4895 4896 if ( ! modern ) { 4897 plugin.fnInit( settings, node, redraw ); 4898 } 4899 4900 /* Add a draw callback for the pagination on first instance, to update the paging display */ 4901 if ( ! features.p ) 4902 { 4903 node.id = settings.sTableId+'_paginate'; 4904 4905 settings.aoDrawCallback.push( { 4906 "fn": function( settings ) { 4907 if ( modern ) { 4908 var 4909 start = settings._iDisplayStart, 4910 len = settings._iDisplayLength, 4911 visRecords = settings.fnRecordsDisplay(), 4912 all = len === -1, 4913 page = all ? 0 : Math.ceil( start / len ), 4914 pages = all ? 1 : Math.ceil( visRecords / len ), 4915 buttons = plugin(page, pages), 4916 i, ien; 4917 4918 for ( i=0, ien=features.p.length ; i<ien ; i++ ) { 4919 _fnRenderer( settings, 'pageButton' )( 4920 settings, features.p[i], i, buttons, page, pages 4921 ); 4922 } 4923 } 4924 else { 4925 plugin.fnUpdate( settings, redraw ); 4926 } 4927 }, 4928 "sName": "pagination" 4929 } ); 4930 } 4931 4932 return node; 4933 } 4934 4935 4936 /** 4937 * Alter the display settings to change the page 4938 * @param {object} settings DataTables settings object 4939 * @param {string|int} action Paging action to take: "first", "previous", 4940 * "next" or "last" or page number to jump to (integer) 4941 * @param [bool] redraw Automatically draw the update or not 4942 * @returns {bool} true page has changed, false - no change 4943 * @memberof DataTable#oApi 4944 */ 4945 function _fnPageChange ( settings, action, redraw ) 4946 { 4947 var 4948 start = settings._iDisplayStart, 4949 len = settings._iDisplayLength, 4950 records = settings.fnRecordsDisplay(); 4951 4952 if ( records === 0 || len === -1 ) 4953 { 4954 start = 0; 4955 } 4956 else if ( typeof action === "number" ) 4957 { 4958 start = action * len; 4959 4960 if ( start > records ) 4961 { 4962 start = 0; 4963 } 4964 } 4965 else if ( action == "first" ) 4966 { 4967 start = 0; 4968 } 4969 else if ( action == "previous" ) 4970 { 4971 start = len >= 0 ? 4972 start - len : 4973 0; 4974 4975 if ( start < 0 ) 4976 { 4977 start = 0; 4978 } 4979 } 4980 else if ( action == "next" ) 4981 { 4982 if ( start + len < records ) 4983 { 4984 start += len; 4985 } 4986 } 4987 else if ( action == "last" ) 4988 { 4989 start = Math.floor( (records-1) / len) * len; 4990 } 4991 else 4992 { 4993 _fnLog( settings, 0, "Unknown paging action: "+action, 5 ); 4994 } 4995 4996 var changed = settings._iDisplayStart !== start; 4997 settings._iDisplayStart = start; 4998 4999 if ( changed ) { 5000 _fnCallbackFire( settings, null, 'page', [settings] ); 5001 5002 if ( redraw ) { 5003 _fnDraw( settings ); 5004 } 5005 } 5006 5007 return changed; 5008 } 5009 5010 5011 5012 /** 5013 * Generate the node required for the processing node 5014 * @param {object} settings dataTables settings object 5015 * @returns {node} Processing element 5016 * @memberof DataTable#oApi 5017 */ 5018 function _fnFeatureHtmlProcessing ( settings ) 5019 { 5020 return $('<div/>', { 5021 'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null, 5022 'class': settings.oClasses.sProcessing 5023 } ) 5024 .html( settings.oLanguage.sProcessing ) 5025 .insertBefore( settings.nTable )[0]; 5026 } 5027 5028 5029 /** 5030 * Display or hide the processing indicator 5031 * @param {object} settings dataTables settings object 5032 * @param {bool} show Show the processing indicator (true) or not (false) 5033 * @memberof DataTable#oApi 5034 */ 5035 function _fnProcessingDisplay ( settings, show ) 5036 { 5037 if ( settings.oFeatures.bProcessing ) { 5038 $(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' ); 5039 } 5040 5041 _fnCallbackFire( settings, null, 'processing', [settings, show] ); 5042 } 5043 5044 /** 5045 * Add any control elements for the table - specifically scrolling 5046 * @param {object} settings dataTables settings object 5047 * @returns {node} Node to add to the DOM 5048 * @memberof DataTable#oApi 5049 */ 5050 function _fnFeatureHtmlTable ( settings ) 5051 { 5052 var table = $(settings.nTable); 5053 5054 // Add the ARIA grid role to the table 5055 table.attr( 'role', 'grid' ); 5056 5057 // Scrolling from here on in 5058 var scroll = settings.oScroll; 5059 5060 if ( scroll.sX === '' && scroll.sY === '' ) { 5061 return settings.nTable; 5062 } 5063 5064 var scrollX = scroll.sX; 5065 var scrollY = scroll.sY; 5066 var classes = settings.oClasses; 5067 var caption = table.children('caption'); 5068 var captionSide = caption.length ? caption[0]._captionSide : null; 5069 var headerClone = $( table[0].cloneNode(false) ); 5070 var footerClone = $( table[0].cloneNode(false) ); 5071 var footer = table.children('tfoot'); 5072 var _div = '<div/>'; 5073 var size = function ( s ) { 5074 return !s ? null : _fnStringToCss( s ); 5075 }; 5076 5077 if ( ! footer.length ) { 5078 footer = null; 5079 } 5080 5081 /* 5082 * The HTML structure that we want to generate in this function is: 5083 * div - scroller 5084 * div - scroll head 5085 * div - scroll head inner 5086 * table - scroll head table 5087 * thead - thead 5088 * div - scroll body 5089 * table - table (master table) 5090 * thead - thead clone for sizing 5091 * tbody - tbody 5092 * div - scroll foot 5093 * div - scroll foot inner 5094 * table - scroll foot table 5095 * tfoot - tfoot 5096 */ 5097 var scroller = $( _div, { 'class': classes.sScrollWrapper } ) 5098 .append( 5099 $(_div, { 'class': classes.sScrollHead } ) 5100 .css( { 5101 overflow: 'hidden', 5102 position: 'relative', 5103 border: 0, 5104 width: scrollX ? size(scrollX) : '100%' 5105 } ) 5106 .append( 5107 $(_div, { 'class': classes.sScrollHeadInner } ) 5108 .css( { 5109 'box-sizing': 'content-box', 5110 width: scroll.sXInner || '100%' 5111 } ) 5112 .append( 5113 headerClone 5114 .removeAttr('id') 5115 .css( 'margin-left', 0 ) 5116 .append( captionSide === 'top' ? caption : null ) 5117 .append( 5118 table.children('thead') 5119 ) 5120 ) 5121 ) 5122 ) 5123 .append( 5124 $(_div, { 'class': classes.sScrollBody } ) 5125 .css( { 5126 position: 'relative', 5127 overflow: 'auto', 5128 width: size( scrollX ) 5129 } ) 5130 .append( table ) 5131 ); 5132 5133 if ( footer ) { 5134 scroller.append( 5135 $(_div, { 'class': classes.sScrollFoot } ) 5136 .css( { 5137 overflow: 'hidden', 5138 border: 0, 5139 width: scrollX ? size(scrollX) : '100%' 5140 } ) 5141 .append( 5142 $(_div, { 'class': classes.sScrollFootInner } ) 5143 .append( 5144 footerClone 5145 .removeAttr('id') 5146 .css( 'margin-left', 0 ) 5147 .append( captionSide === 'bottom' ? caption : null ) 5148 .append( 5149 table.children('tfoot') 5150 ) 5151 ) 5152 ) 5153 ); 5154 } 5155 5156 var children = scroller.children(); 5157 var scrollHead = children[0]; 5158 var scrollBody = children[1]; 5159 var scrollFoot = footer ? children[2] : null; 5160 5161 // When the body is scrolled, then we also want to scroll the headers 5162 if ( scrollX ) { 5163 $(scrollBody).on( 'scroll.DT', function (e) { 5164 var scrollLeft = this.scrollLeft; 5165 5166 scrollHead.scrollLeft = scrollLeft; 5167 5168 if ( footer ) { 5169 scrollFoot.scrollLeft = scrollLeft; 5170 } 5171 } ); 5172 } 5173 5174 $(scrollBody).css( 5175 scrollY && scroll.bCollapse ? 'max-height' : 'height', 5176 scrollY 5177 ); 5178 5179 settings.nScrollHead = scrollHead; 5180 settings.nScrollBody = scrollBody; 5181 settings.nScrollFoot = scrollFoot; 5182 5183 // On redraw - align columns 5184 settings.aoDrawCallback.push( { 5185 "fn": _fnScrollDraw, 5186 "sName": "scrolling" 5187 } ); 5188 5189 return scroller[0]; 5190 } 5191 5192 5193 5194 /** 5195 * Update the header, footer and body tables for resizing - i.e. column 5196 * alignment. 5197 * 5198 * Welcome to the most horrible function DataTables. The process that this 5199 * function follows is basically: 5200 * 1. Re-create the table inside the scrolling div 5201 * 2. Take live measurements from the DOM 5202 * 3. Apply the measurements to align the columns 5203 * 4. Clean up 5204 * 5205 * @param {object} settings dataTables settings object 5206 * @memberof DataTable#oApi 5207 */ 5208 function _fnScrollDraw ( settings ) 5209 { 5210 // Given that this is such a monster function, a lot of variables are use 5211 // to try and keep the minimised size as small as possible 5212 var 5213 scroll = settings.oScroll, 5214 scrollX = scroll.sX, 5215 scrollXInner = scroll.sXInner, 5216 scrollY = scroll.sY, 5217 barWidth = scroll.iBarWidth, 5218 divHeader = $(settings.nScrollHead), 5219 divHeaderStyle = divHeader[0].style, 5220 divHeaderInner = divHeader.children('div'), 5221 divHeaderInnerStyle = divHeaderInner[0].style, 5222 divHeaderTable = divHeaderInner.children('table'), 5223 divBodyEl = settings.nScrollBody, 5224 divBody = $(divBodyEl), 5225 divBodyStyle = divBodyEl.style, 5226 divFooter = $(settings.nScrollFoot), 5227 divFooterInner = divFooter.children('div'), 5228 divFooterTable = divFooterInner.children('table'), 5229 header = $(settings.nTHead), 5230 table = $(settings.nTable), 5231 tableEl = table[0], 5232 tableStyle = tableEl.style, 5233 footer = settings.nTFoot ? $(settings.nTFoot) : null, 5234 browser = settings.oBrowser, 5235 ie67 = browser.bScrollOversize, 5236 dtHeaderCells = _pluck( settings.aoColumns, 'nTh' ), 5237 headerTrgEls, footerTrgEls, 5238 headerSrcEls, footerSrcEls, 5239 headerCopy, footerCopy, 5240 headerWidths=[], footerWidths=[], 5241 headerContent=[], footerContent=[], 5242 idx, correction, sanityWidth, 5243 zeroOut = function(nSizer) { 5244 var style = nSizer.style; 5245 style.paddingTop = "0"; 5246 style.paddingBottom = "0"; 5247 style.borderTopWidth = "0"; 5248 style.borderBottomWidth = "0"; 5249 style.height = 0; 5250 }; 5251 5252 // If the scrollbar visibility has changed from the last draw, we need to 5253 // adjust the column sizes as the table width will have changed to account 5254 // for the scrollbar 5255 var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight; 5256 5257 if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) { 5258 settings.scrollBarVis = scrollBarVis; 5259 _fnAdjustColumnSizing( settings ); 5260 return; // adjust column sizing will call this function again 5261 } 5262 else { 5263 settings.scrollBarVis = scrollBarVis; 5264 } 5265 5266 /* 5267 * 1. Re-create the table inside the scrolling div 5268 */ 5269 5270 // Remove the old minimised thead and tfoot elements in the inner table 5271 table.children('thead, tfoot').remove(); 5272 5273 if ( footer ) { 5274 footerCopy = footer.clone().prependTo( table ); 5275 footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized 5276 footerSrcEls = footerCopy.find('tr'); 5277 } 5278 5279 // Clone the current header and footer elements and then place it into the inner table 5280 headerCopy = header.clone().prependTo( table ); 5281 headerTrgEls = header.find('tr'); // original header is in its own table 5282 headerSrcEls = headerCopy.find('tr'); 5283 headerCopy.find('th, td').removeAttr('tabindex'); 5284 5285 5286 /* 5287 * 2. Take live measurements from the DOM - do not alter the DOM itself! 5288 */ 5289 5290 // Remove old sizing and apply the calculated column widths 5291 // Get the unique column headers in the newly created (cloned) header. We want to apply the 5292 // calculated sizes to this header 5293 if ( ! scrollX ) 5294 { 5295 divBodyStyle.width = '100%'; 5296 divHeader[0].style.width = '100%'; 5297 } 5298 5299 $.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) { 5300 idx = _fnVisibleToColumnIndex( settings, i ); 5301 el.style.width = settings.aoColumns[idx].sWidth; 5302 } ); 5303 5304 if ( footer ) { 5305 _fnApplyToChildren( function(n) { 5306 n.style.width = ""; 5307 }, footerSrcEls ); 5308 } 5309 5310 // Size the table as a whole 5311 sanityWidth = table.outerWidth(); 5312 if ( scrollX === "" ) { 5313 // No x scrolling 5314 tableStyle.width = "100%"; 5315 5316 // IE7 will make the width of the table when 100% include the scrollbar 5317 // - which is shouldn't. When there is a scrollbar we need to take this 5318 // into account. 5319 if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight || 5320 divBody.css('overflow-y') == "scroll") 5321 ) { 5322 tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth); 5323 } 5324 5325 // Recalculate the sanity width 5326 sanityWidth = table.outerWidth(); 5327 } 5328 else if ( scrollXInner !== "" ) { 5329 // legacy x scroll inner has been given - use it 5330 tableStyle.width = _fnStringToCss(scrollXInner); 5331 5332 // Recalculate the sanity width 5333 sanityWidth = table.outerWidth(); 5334 } 5335 5336 // Hidden header should have zero height, so remove padding and borders. Then 5337 // set the width based on the real headers 5338 5339 // Apply all styles in one pass 5340 _fnApplyToChildren( zeroOut, headerSrcEls ); 5341 5342 // Read all widths in next pass 5343 _fnApplyToChildren( function(nSizer) { 5344 headerContent.push( nSizer.innerHTML ); 5345 headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) ); 5346 }, headerSrcEls ); 5347 5348 // Apply all widths in final pass 5349 _fnApplyToChildren( function(nToSize, i) { 5350 // Only apply widths to the DataTables detected header cells - this 5351 // prevents complex headers from having contradictory sizes applied 5352 if ( $.inArray( nToSize, dtHeaderCells ) !== -1 ) { 5353 nToSize.style.width = headerWidths[i]; 5354 } 5355 }, headerTrgEls ); 5356 5357 $(headerSrcEls).height(0); 5358 5359 /* Same again with the footer if we have one */ 5360 if ( footer ) 5361 { 5362 _fnApplyToChildren( zeroOut, footerSrcEls ); 5363 5364 _fnApplyToChildren( function(nSizer) { 5365 footerContent.push( nSizer.innerHTML ); 5366 footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) ); 5367 }, footerSrcEls ); 5368 5369 _fnApplyToChildren( function(nToSize, i) { 5370 nToSize.style.width = footerWidths[i]; 5371 }, footerTrgEls ); 5372 5373 $(footerSrcEls).height(0); 5374 } 5375 5376 5377 /* 5378 * 3. Apply the measurements 5379 */ 5380 5381 // "Hide" the header and footer that we used for the sizing. We need to keep 5382 // the content of the cell so that the width applied to the header and body 5383 // both match, but we want to hide it completely. We want to also fix their 5384 // width to what they currently are 5385 _fnApplyToChildren( function(nSizer, i) { 5386 nSizer.innerHTML = '<div class="dataTables_sizing">'+headerContent[i]+'</div>'; 5387 nSizer.childNodes[0].style.height = "0"; 5388 nSizer.childNodes[0].style.overflow = "hidden"; 5389 nSizer.style.width = headerWidths[i]; 5390 }, headerSrcEls ); 5391 5392 if ( footer ) 5393 { 5394 _fnApplyToChildren( function(nSizer, i) { 5395 nSizer.innerHTML = '<div class="dataTables_sizing">'+footerContent[i]+'</div>'; 5396 nSizer.childNodes[0].style.height = "0"; 5397 nSizer.childNodes[0].style.overflow = "hidden"; 5398 nSizer.style.width = footerWidths[i]; 5399 }, footerSrcEls ); 5400 } 5401 5402 // Sanity check that the table is of a sensible width. If not then we are going to get 5403 // misalignment - try to prevent this by not allowing the table to shrink below its min width 5404 if ( table.outerWidth() < sanityWidth ) 5405 { 5406 // The min width depends upon if we have a vertical scrollbar visible or not */ 5407 correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight || 5408 divBody.css('overflow-y') == "scroll")) ? 5409 sanityWidth+barWidth : 5410 sanityWidth; 5411 5412 // IE6/7 are a law unto themselves... 5413 if ( ie67 && (divBodyEl.scrollHeight > 5414 divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll") 5415 ) { 5416 tableStyle.width = _fnStringToCss( correction-barWidth ); 5417 } 5418 5419 // And give the user a warning that we've stopped the table getting too small 5420 if ( scrollX === "" || scrollXInner !== "" ) { 5421 _fnLog( settings, 1, 'Possible column misalignment', 6 ); 5422 } 5423 } 5424 else 5425 { 5426 correction = '100%'; 5427 } 5428 5429 // Apply to the container elements 5430 divBodyStyle.width = _fnStringToCss( correction ); 5431 divHeaderStyle.width = _fnStringToCss( correction ); 5432 5433 if ( footer ) { 5434 settings.nScrollFoot.style.width = _fnStringToCss( correction ); 5435 } 5436 5437 5438 /* 5439 * 4. Clean up 5440 */ 5441 if ( ! scrollY ) { 5442 /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting 5443 * the scrollbar height from the visible display, rather than adding it on. We need to 5444 * set the height in order to sort this. Don't want to do it in any other browsers. 5445 */ 5446 if ( ie67 ) { 5447 divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth ); 5448 } 5449 } 5450 5451 /* Finally set the width's of the header and footer tables */ 5452 var iOuterWidth = table.outerWidth(); 5453 divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth ); 5454 divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth ); 5455 5456 // Figure out if there are scrollbar present - if so then we need a the header and footer to 5457 // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar) 5458 var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll"; 5459 var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' ); 5460 divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px"; 5461 5462 if ( footer ) { 5463 divFooterTable[0].style.width = _fnStringToCss( iOuterWidth ); 5464 divFooterInner[0].style.width = _fnStringToCss( iOuterWidth ); 5465 divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px"; 5466 } 5467 5468 // Correct DOM ordering for colgroup - comes before the thead 5469 table.children('colgroup').insertBefore( table.children('thead') ); 5470 5471 /* Adjust the position of the header in case we loose the y-scrollbar */ 5472 divBody.scroll(
vendor: 11,594 bytes, lines 5472-5870
5472); 5473 5474 // If sorting or filtering has occurred, jump the scrolling back to the top 5475 // only if we aren't holding the position 5476 if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) { 5477 divBodyEl.scrollTop = 0; 5478 } 5479 } 5480 5481 5482 5483 /** 5484 * Apply a given function to the display child nodes of an element array (typically 5485 * TD children of TR rows 5486 * @param {function} fn Method to apply to the objects 5487 * @param array {nodes} an1 List of elements to look through for display children 5488 * @param array {nodes} an2 Another list (identical structure to the first) - optional 5489 * @memberof DataTable#oApi 5490 */ 5491 function _fnApplyToChildren( fn, an1, an2 ) 5492 { 5493 var index=0, i=0, iLen=an1.length; 5494 var nNode1, nNode2; 5495 5496 while ( i < iLen ) { 5497 nNode1 = an1[i].firstChild; 5498 nNode2 = an2 ? an2[i].firstChild : null; 5499 5500 while ( nNode1 ) { 5501 if ( nNode1.nodeType === 1 ) { 5502 if ( an2 ) { 5503 fn( nNode1, nNode2, index ); 5504 } 5505 else { 5506 fn( nNode1, index ); 5507 } 5508 5509 index++; 5510 } 5511 5512 nNode1 = nNode1.nextSibling; 5513 nNode2 = an2 ? nNode2.nextSibling : null; 5514 } 5515 5516 i++; 5517 } 5518 } 5519 5520 5521 5522 var __re_html_remove = /<.*?>/g; 5523 5524 5525 /** 5526 * Calculate the width of columns for the table 5527 * @param {object} oSettings dataTables settings object 5528 * @memberof DataTable#oApi 5529 */ 5530 function _fnCalculateColumnWidths ( oSettings ) 5531 { 5532 var 5533 table = oSettings.nTable, 5534 columns = oSettings.aoColumns, 5535 scroll = oSettings.oScroll, 5536 scrollY = scroll.sY, 5537 scrollX = scroll.sX, 5538 scrollXInner = scroll.sXInner, 5539 columnCount = columns.length, 5540 visibleColumns = _fnGetColumns( oSettings, 'bVisible' ), 5541 headerCells = $('th', oSettings.nTHead), 5542 tableWidthAttr = table.getAttribute('width'), // from DOM element 5543 tableContainer = table.parentNode, 5544 userInputs = false, 5545 i, column, columnIdx, width, outerWidth, 5546 browser = oSettings.oBrowser, 5547 ie67 = browser.bScrollOversize; 5548 5549 var styleWidth = table.style.width; 5550 if ( styleWidth && styleWidth.indexOf('%') !== -1 ) { 5551 tableWidthAttr = styleWidth; 5552 } 5553 5554 /* Convert any user input sizes into pixel sizes */ 5555 for ( i=0 ; i<visibleColumns.length ; i++ ) { 5556 column = columns[ visibleColumns[i] ]; 5557 5558 if ( column.sWidth !== null ) { 5559 column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer ); 5560 5561 userInputs = true; 5562 } 5563 } 5564 5565 /* If the number of columns in the DOM equals the number that we have to 5566 * process in DataTables, then we can use the offsets that are created by 5567 * the web- browser. No custom sizes can be set in order for this to happen, 5568 * nor scrolling used 5569 */ 5570 if ( ie67 || ! userInputs && ! scrollX && ! scrollY && 5571 columnCount == _fnVisbleColumns( oSettings ) && 5572 columnCount == headerCells.length 5573 ) { 5574 for ( i=0 ; i<columnCount ; i++ ) { 5575 var colIdx = _fnVisibleToColumnIndex( oSettings, i ); 5576 5577 if ( colIdx !== null ) { 5578 columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() ); 5579 } 5580 } 5581 } 5582 else 5583 { 5584 // Otherwise construct a single row, worst case, table with the widest 5585 // node in the data, assign any user defined widths, then insert it into 5586 // the DOM and allow the browser to do all the hard work of calculating 5587 // table widths 5588 var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table 5589 .css( 'visibility', 'hidden' ) 5590 .removeAttr( 'id' ); 5591 5592 // Clean up the table body 5593 tmpTable.find('tbody tr').remove(); 5594 var tr = $('<tr/>').appendTo( tmpTable.find('tbody') ); 5595 5596 // Clone the table header and footer - we can't use the header / footer 5597 // from the cloned table, since if scrolling is active, the table's 5598 // real header and footer are contained in different table tags 5599 tmpTable.find('thead, tfoot').remove(); 5600 tmpTable 5601 .append( $(oSettings.nTHead).clone() ) 5602 .append( $(oSettings.nTFoot).clone() ); 5603 5604 // Remove any assigned widths from the footer (from scrolling) 5605 tmpTable.find('tfoot th, tfoot td').css('width', ''); 5606 5607 // Apply custom sizing to the cloned header 5608 headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] ); 5609 5610 for ( i=0 ; i<visibleColumns.length ; i++ ) { 5611 column = columns[ visibleColumns[i] ]; 5612 5613 headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ? 5614 _fnStringToCss( column.sWidthOrig ) : 5615 ''; 5616 5617 // For scrollX we need to force the column width otherwise the 5618 // browser will collapse it. If this width is smaller than the 5619 // width the column requires, then it will have no effect 5620 if ( column.sWidthOrig && scrollX ) { 5621 $( headerCells[i] ).append( $('<div/>').css( { 5622 width: column.sWidthOrig, 5623 margin: 0, 5624 padding: 0, 5625 border: 0, 5626 height: 1 5627 } ) ); 5628 } 5629 } 5630 5631 // Find the widest cell for each column and put it into the table 5632 if ( oSettings.aoData.length ) { 5633 for ( i=0 ; i<visibleColumns.length ; i++ ) { 5634 columnIdx = visibleColumns[i]; 5635 column = columns[ columnIdx ]; 5636 5637 $( _fnGetWidestNode( oSettings, columnIdx ) ) 5638 .clone( false ) 5639 .append( column.sContentPadding ) 5640 .appendTo( tr ); 5641 } 5642 } 5643 5644 // Tidy the temporary table - remove name attributes so there aren't 5645 // duplicated in the dom (radio elements for example) 5646 $('[name]', tmpTable).removeAttr('name'); 5647 5648 // Table has been built, attach to the document so we can work with it. 5649 // A holding element is used, positioned at the top of the container 5650 // with minimal height, so it has no effect on if the container scrolls 5651 // or not. Otherwise it might trigger scrolling when it actually isn't 5652 // needed 5653 var holder = $('<div/>').css( scrollX || scrollY ? 5654 { 5655 position: 'absolute', 5656 top: 0, 5657 left: 0, 5658 height: 1, 5659 right: 0, 5660 overflow: 'hidden' 5661 } : 5662 {} 5663 ) 5664 .append( tmpTable ) 5665 .appendTo( tableContainer ); 5666 5667 // When scrolling (X or Y) we want to set the width of the table as 5668 // appropriate. However, when not scrolling leave the table width as it 5669 // is. This results in slightly different, but I think correct behaviour 5670 if ( scrollX && scrollXInner ) { 5671 tmpTable.width( scrollXInner ); 5672 } 5673 else if ( scrollX ) { 5674 tmpTable.css( 'width', 'auto' ); 5675 tmpTable.removeAttr('width'); 5676 5677 // If there is no width attribute or style, then allow the table to 5678 // collapse 5679 if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) { 5680 tmpTable.width( tableContainer.clientWidth ); 5681 } 5682 } 5683 else if ( scrollY ) { 5684 tmpTable.width( tableContainer.clientWidth ); 5685 } 5686 else if ( tableWidthAttr ) { 5687 tmpTable.width( tableWidthAttr ); 5688 } 5689 5690 // Get the width of each column in the constructed table - we need to 5691 // know the inner width (so it can be assigned to the other table's 5692 // cells) and the outer width so we can calculate the full width of the 5693 // table. This is safe since DataTables requires a unique cell for each 5694 // column, but if ever a header can span multiple columns, this will 5695 // need to be modified. 5696 var total = 0; 5697 for ( i=0 ; i<visibleColumns.length ; i++ ) { 5698 var cell = $(headerCells[i]); 5699 var border = cell.outerWidth() - cell.width(); 5700 5701 // Use getBounding... where possible (not IE8-) because it can give 5702 // sub-pixel accuracy, which we then want to round up! 5703 var bounding = browser.bBounding ? 5704 Math.ceil( headerCells[i].getBoundingClientRect().width ) : 5705 cell.outerWidth(); 5706 5707 // Total is tracked to remove any sub-pixel errors as the outerWidth 5708 // of the table might not equal the total given here (IE!). 5709 total += bounding; 5710 5711 // Width for each column to use 5712 columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border ); 5713 } 5714 5715 table.style.width = _fnStringToCss( total ); 5716 5717 // Finished with the table - ditch it 5718 holder.remove(); 5719 } 5720 5721 // If there is a width attr, we want to attach an event listener which 5722 // allows the table sizing to automatically adjust when the window is 5723 // resized. Use the width attr rather than CSS, since we can't know if the 5724 // CSS is a relative value or absolute - DOM read is always px. 5725 if ( tableWidthAttr ) { 5726 table.style.width = _fnStringToCss( tableWidthAttr ); 5727 } 5728 5729 if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) { 5730 var bindResize = function () { 5731 $(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () { 5732 _fnAdjustColumnSizing( oSettings ); 5733 } ) ); 5734 }; 5735 5736 // IE6/7 will crash if we bind a resize event handler on page load. 5737 // To be removed in 1.11 which drops IE6/7 support 5738 if ( ie67 ) { 5739 setTimeout( bindResize, 1000 ); 5740 } 5741 else { 5742 bindResize(); 5743 } 5744 5745 oSettings._reszEvt = true; 5746 } 5747 } 5748 5749 5750 /** 5751 * Throttle the calls to a function. Arguments and context are maintained for 5752 * the throttled function 5753 * @param {function} fn Function to be called 5754 * @param {int} [freq=200] call frequency in mS 5755 * @returns {function} wrapped function 5756 * @memberof DataTable#oApi 5757 */ 5758 var _fnThrottle = DataTable.util.throttle; 5759 5760 5761 /** 5762 * Convert a CSS unit width to pixels (e.g. 2em) 5763 * @param {string} width width to be converted 5764 * @param {node} parent parent to get the with for (required for relative widths) - optional 5765 * @returns {int} width in pixels 5766 * @memberof DataTable#oApi 5767 */ 5768 function _fnConvertToWidth ( width, parent ) 5769 { 5770 if ( ! width ) { 5771 return 0; 5772 } 5773 5774 var n = $('<div/>') 5775 .css( 'width', _fnStringToCss( width ) ) 5776 .appendTo( parent || document.body ); 5777 5778 var val = n[0].offsetWidth; 5779 n.remove(); 5780 5781 return val; 5782 } 5783 5784 5785 /** 5786 * Get the widest node 5787 * @param {object} settings dataTables settings object 5788 * @param {int} colIdx column of interest 5789 * @returns {node} widest table node 5790 * @memberof DataTable#oApi 5791 */ 5792 function _fnGetWidestNode( settings, colIdx ) 5793 { 5794 var idx = _fnGetMaxLenString( settings, colIdx ); 5795 if ( idx < 0 ) { 5796 return null; 5797 } 5798 5799 var data = settings.aoData[ idx ]; 5800 return ! data.nTr ? // Might not have been created when deferred rendering 5801 $('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] : 5802 data.anCells[ colIdx ]; 5803 } 5804 5805 5806 /** 5807 * Get the maximum strlen for each data column 5808 * @param {object} settings dataTables settings object 5809 * @param {int} colIdx column of interest 5810 * @returns {string} max string length for each column 5811 * @memberof DataTable#oApi 5812 */ 5813 function _fnGetMaxLenString( settings, colIdx ) 5814 { 5815 var s, max=-1, maxIdx = -1; 5816 5817 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 5818 s = _fnGetCellData( settings, i, colIdx, 'display' )+''; 5819 s = s.replace( __re_html_remove, '' ); 5820 s = s.replace( / /g, ' ' ); 5821 5822 if ( s.length > max ) { 5823 max = s.length; 5824 maxIdx = i; 5825 } 5826 } 5827 5828 return maxIdx; 5829 } 5830 5831 5832 /** 5833 * Append a CSS unit (only if required) to a string 5834 * @param {string} value to css-ify 5835 * @returns {string} value with css unit 5836 * @memberof DataTable#oApi 5837 */ 5838 function _fnStringToCss( s ) 5839 { 5840 if ( s === null ) { 5841 return '0px'; 5842 } 5843 5844 if ( typeof s == 'number' ) { 5845 return s < 0 ? 5846 '0px' : 5847 s+'px'; 5848 } 5849 5850 // Check it has a unit character already 5851 return s.match(/\d$/) ? 5852 s+'px' : 5853 s; 5854 } 5855 5856 5857 5858 function _fnSortFlatten ( settings ) 5859 { 5860 var 5861 i, iLen, k, kLen, 5862 aSort = [], 5863 aiOrig = [], 5864 aoColumns = settings.aoColumns, 5865 aDataSort, iCol, sType, srcCol, 5866 fixed = settings.aaSortingFixed, 5867 fixedObj = $.isPlainObject( fixed ), 5868 nestedSort = [], 5869 add = function ( a ) { 5870 if ( a.length && !
vendor: 39,758 bytes, lines 5870-7391
5870$.isArray( a[0] ) ) { 5871 // 1D array 5872 nestedSort.push( a ); 5873 } 5874 else { 5875 // 2D array 5876 $.merge( nestedSort, a ); 5877 } 5878 }; 5879 5880 // Build the sort array, with pre-fix and post-fix options if they have been 5881 // specified 5882 if ( $.isArray( fixed ) ) { 5883 add( fixed ); 5884 } 5885 5886 if ( fixedObj && fixed.pre ) { 5887 add( fixed.pre ); 5888 } 5889 5890 add( settings.aaSorting ); 5891 5892 if (fixedObj && fixed.post ) { 5893 add( fixed.post ); 5894 } 5895 5896 for ( i=0 ; i<nestedSort.length ; i++ ) 5897 { 5898 srcCol = nestedSort[i][0]; 5899 aDataSort = aoColumns[ srcCol ].aDataSort; 5900 5901 for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ ) 5902 { 5903 iCol = aDataSort[k]; 5904 sType = aoColumns[ iCol ].sType || 'string'; 5905 5906 if ( nestedSort[i]._idx === undefined ) { 5907 nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting ); 5908 } 5909 5910 aSort.push( { 5911 src: srcCol, 5912 col: iCol, 5913 dir: nestedSort[i][1], 5914 index: nestedSort[i]._idx, 5915 type: sType, 5916 formatter: DataTable.ext.type.order[ sType+"-pre" ] 5917 } ); 5918 } 5919 } 5920 5921 return aSort; 5922 } 5923 5924 /** 5925 * Change the order of the table 5926 * @param {object} oSettings dataTables settings object 5927 * @memberof DataTable#oApi 5928 * @todo This really needs split up! 5929 */ 5930 function _fnSort ( oSettings ) 5931 { 5932 var 5933 i, ien, iLen, j, jLen, k, kLen, 5934 sDataType, nTh, 5935 aiOrig = [], 5936 oExtSort = DataTable.ext.type.order, 5937 aoData = oSettings.aoData, 5938 aoColumns = oSettings.aoColumns, 5939 aDataSort, data, iCol, sType, oSort, 5940 formatters = 0, 5941 sortCol, 5942 displayMaster = oSettings.aiDisplayMaster, 5943 aSort; 5944 5945 // Resolve any column types that are unknown due to addition or invalidation 5946 // @todo Can this be moved into a 'data-ready' handler which is called when 5947 // data is going to be used in the table? 5948 _fnColumnTypes( oSettings ); 5949 5950 aSort = _fnSortFlatten( oSettings ); 5951 5952 for ( i=0, ien=aSort.length ; i<ien ; i++ ) { 5953 sortCol = aSort[i]; 5954 5955 // Track if we can use the fast sort algorithm 5956 if ( sortCol.formatter ) { 5957 formatters++; 5958 } 5959 5960 // Load the data needed for the sort, for each cell 5961 _fnSortData( oSettings, sortCol.col ); 5962 } 5963 5964 /* No sorting required if server-side or no sorting array */ 5965 if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 ) 5966 { 5967 // Create a value - key array of the current row positions such that we can use their 5968 // current position during the sort, if values match, in order to perform stable sorting 5969 for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) { 5970 aiOrig[ displayMaster[i] ] = i; 5971 } 5972 5973 /* Do the sort - here we want multi-column sorting based on a given data source (column) 5974 * and sorting function (from oSort) in a certain direction. It's reasonably complex to 5975 * follow on it's own, but this is what we want (example two column sorting): 5976 * fnLocalSorting = function(a,b){ 5977 * var iTest; 5978 * iTest = oSort['string-asc']('data11', 'data12'); 5979 * if (iTest !== 0) 5980 * return iTest; 5981 * iTest = oSort['numeric-desc']('data21', 'data22'); 5982 * if (iTest !== 0) 5983 * return iTest; 5984 * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] ); 5985 * } 5986 * Basically we have a test for each sorting column, if the data in that column is equal, 5987 * test the next column. If all columns match, then we use a numeric sort on the row 5988 * positions in the original data array to provide a stable sort. 5989 * 5990 * Note - I know it seems excessive to have two sorting methods, but the first is around 5991 * 15% faster, so the second is only maintained for backwards compatibility with sorting 5992 * methods which do not have a pre-sort formatting function. 5993 */ 5994 if ( formatters === aSort.length ) { 5995 // All sort types have formatting functions 5996 displayMaster.sort( function ( a, b ) { 5997 var 5998 x, y, k, test, sort, 5999 len=aSort.length, 6000 dataA = aoData[a]._aSortData, 6001 dataB = aoData[b]._aSortData; 6002 6003 for ( k=0 ; k<len ; k++ ) { 6004 sort = aSort[k]; 6005 6006 x = dataA[ sort.col ]; 6007 y = dataB[ sort.col ]; 6008 6009 test = x<y ? -1 : x>y ? 1 : 0; 6010 if ( test !== 0 ) { 6011 return sort.dir === 'asc' ? test : -test; 6012 } 6013 } 6014 6015 x = aiOrig[a]; 6016 y = aiOrig[b]; 6017 return x<y ? -1 : x>y ? 1 : 0; 6018 } ); 6019 } 6020 else { 6021 // Depreciated - remove in 1.11 (providing a plug-in option) 6022 // Not all sort types have formatting methods, so we have to call their sorting 6023 // methods. 6024 displayMaster.sort( function ( a, b ) { 6025 var 6026 x, y, k, l, test, sort, fn, 6027 len=aSort.length, 6028 dataA = aoData[a]._aSortData, 6029 dataB = aoData[b]._aSortData; 6030 6031 for ( k=0 ; k<len ; k++ ) { 6032 sort = aSort[k]; 6033 6034 x = dataA[ sort.col ]; 6035 y = dataB[ sort.col ]; 6036 6037 fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ]; 6038 test = fn( x, y ); 6039 if ( test !== 0 ) { 6040 return test; 6041 } 6042 } 6043 6044 x = aiOrig[a]; 6045 y = aiOrig[b]; 6046 return x<y ? -1 : x>y ? 1 : 0; 6047 } ); 6048 } 6049 } 6050 6051 /* Tell the draw function that we have sorted the data */ 6052 oSettings.bSorted = true; 6053 } 6054 6055 6056 function _fnSortAria ( settings ) 6057 { 6058 var label; 6059 var nextSort; 6060 var columns = settings.aoColumns; 6061 var aSort = _fnSortFlatten( settings ); 6062 var oAria = settings.oLanguage.oAria; 6063 6064 // ARIA attributes - need to loop all columns, to update all (removing old 6065 // attributes as needed) 6066 for ( var i=0, iLen=columns.length ; i<iLen ; i++ ) 6067 { 6068 var col = columns[i]; 6069 var asSorting = col.asSorting; 6070 var sTitle = col.sTitle.replace( /<.*?>/g, "" ); 6071 var th = col.nTh; 6072 6073 // IE7 is throwing an error when setting these properties with jQuery's 6074 // attr() and removeAttr() methods... 6075 th.removeAttribute('aria-sort'); 6076 6077 /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */ 6078 if ( col.bSortable ) { 6079 if ( aSort.length > 0 && aSort[0].col == i ) { 6080 th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" ); 6081 nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0]; 6082 } 6083 else { 6084 nextSort = asSorting[0]; 6085 } 6086 6087 label = sTitle + ( nextSort === "asc" ? 6088 oAria.sSortAscending : 6089 oAria.sSortDescending 6090 ); 6091 } 6092 else { 6093 label = sTitle; 6094 } 6095 6096 th.setAttribute('aria-label', label); 6097 } 6098 } 6099 6100 6101 /** 6102 * Function to run on user sort request 6103 * @param {object} settings dataTables settings object 6104 * @param {node} attachTo node to attach the handler to 6105 * @param {int} colIdx column sorting index 6106 * @param {boolean} [append=false] Append the requested sort to the existing 6107 * sort if true (i.e. multi-column sort) 6108 * @param {function} [callback] callback function 6109 * @memberof DataTable#oApi 6110 */ 6111 function _fnSortListener ( settings, colIdx, append, callback ) 6112 { 6113 var col = settings.aoColumns[ colIdx ]; 6114 var sorting = settings.aaSorting; 6115 var asSorting = col.asSorting; 6116 var nextSortIdx; 6117 var next = function ( a, overflow ) { 6118 var idx = a._idx; 6119 if ( idx === undefined ) { 6120 idx = $.inArray( a[1], asSorting ); 6121 } 6122 6123 return idx+1 < asSorting.length ? 6124 idx+1 : 6125 overflow ? 6126 null : 6127 0; 6128 }; 6129 6130 // Convert to 2D array if needed 6131 if ( typeof sorting[0] === 'number' ) { 6132 sorting = settings.aaSorting = [ sorting ]; 6133 } 6134 6135 // If appending the sort then we are multi-column sorting 6136 if ( append && settings.oFeatures.bSortMulti ) { 6137 // Are we already doing some kind of sort on this column? 6138 var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') ); 6139 6140 if ( sortIdx !== -1 ) { 6141 // Yes, modify the sort 6142 nextSortIdx = next( sorting[sortIdx], true ); 6143 6144 if ( nextSortIdx === null && sorting.length === 1 ) { 6145 nextSortIdx = 0; // can't remove sorting completely 6146 } 6147 6148 if ( nextSortIdx === null ) { 6149 sorting.splice( sortIdx, 1 ); 6150 } 6151 else { 6152 sorting[sortIdx][1] = asSorting[ nextSortIdx ]; 6153 sorting[sortIdx]._idx = nextSortIdx; 6154 } 6155 } 6156 else { 6157 // No sort on this column yet 6158 sorting.push( [ colIdx, asSorting[0], 0 ] ); 6159 sorting[sorting.length-1]._idx = 0; 6160 } 6161 } 6162 else if ( sorting.length && sorting[0][0] == colIdx ) { 6163 // Single column - already sorting on this column, modify the sort 6164 nextSortIdx = next( sorting[0] ); 6165 6166 sorting.length = 1; 6167 sorting[0][1] = asSorting[ nextSortIdx ]; 6168 sorting[0]._idx = nextSortIdx; 6169 } 6170 else { 6171 // Single column - sort only on this column 6172 sorting.length = 0; 6173 sorting.push( [ colIdx, asSorting[0] ] ); 6174 sorting[0]._idx = 0; 6175 } 6176 6177 // Run the sort by calling a full redraw 6178 _fnReDraw( settings ); 6179 6180 // callback used for async user interaction 6181 if ( typeof callback == 'function' ) { 6182 callback( settings ); 6183 } 6184 } 6185 6186 6187 /** 6188 * Attach a sort handler (click) to a node 6189 * @param {object} settings dataTables settings object 6190 * @param {node} attachTo node to attach the handler to 6191 * @param {int} colIdx column sorting index 6192 * @param {function} [callback] callback function 6193 * @memberof DataTable#oApi 6194 */ 6195 function _fnSortAttachListener ( settings, attachTo, colIdx, callback ) 6196 { 6197 var col = settings.aoColumns[ colIdx ]; 6198 6199 _fnBindAction( attachTo, {}, function (e) { 6200 /* If the column is not sortable - don't to anything */ 6201 if ( col.bSortable === false ) { 6202 return; 6203 } 6204 6205 // If processing is enabled use a timeout to allow the processing 6206 // display to be shown - otherwise to it synchronously 6207 if ( settings.oFeatures.bProcessing ) { 6208 _fnProcessingDisplay( settings, true ); 6209 6210 setTimeout( function() { 6211 _fnSortListener( settings, colIdx, e.shiftKey, callback ); 6212 6213 // In server-side processing, the draw callback will remove the 6214 // processing display 6215 if ( _fnDataSource( settings ) !== 'ssp' ) { 6216 _fnProcessingDisplay( settings, false ); 6217 } 6218 }, 0 ); 6219 } 6220 else { 6221 _fnSortListener( settings, colIdx, e.shiftKey, callback ); 6222 } 6223 } ); 6224 } 6225 6226 6227 /** 6228 * Set the sorting classes on table's body, Note: it is safe to call this function 6229 * when bSort and bSortClasses are false 6230 * @param {object} oSettings dataTables settings object 6231 * @memberof DataTable#oApi 6232 */ 6233 function _fnSortingClasses( settings ) 6234 { 6235 var oldSort = settings.aLastSort; 6236 var sortClass = settings.oClasses.sSortColumn; 6237 var sort = _fnSortFlatten( settings ); 6238 var features = settings.oFeatures; 6239 var i, ien, colIdx; 6240 6241 if ( features.bSort && features.bSortClasses ) { 6242 // Remove old sorting classes 6243 for ( i=0, ien=oldSort.length ; i<ien ; i++ ) { 6244 colIdx = oldSort[i].src; 6245 6246 // Remove column sorting 6247 $( _pluck( settings.aoData, 'anCells', colIdx ) ) 6248 .removeClass( sortClass + (i<2 ? i+1 : 3) ); 6249 } 6250 6251 // Add new column sorting 6252 for ( i=0, ien=sort.length ; i<ien ; i++ ) { 6253 colIdx = sort[i].src; 6254 6255 $( _pluck( settings.aoData, 'anCells', colIdx ) ) 6256 .addClass( sortClass + (i<2 ? i+1 : 3) ); 6257 } 6258 } 6259 6260 settings.aLastSort = sort; 6261 } 6262 6263 6264 // Get the data to sort a column, be it from cache, fresh (populating the 6265 // cache), or from a sort formatter 6266 function _fnSortData( settings, idx ) 6267 { 6268 // Custom sorting function - provided by the sort data type 6269 var column = settings.aoColumns[ idx ]; 6270 var customSort = DataTable.ext.order[ column.sSortDataType ]; 6271 var customData; 6272 6273 if ( customSort ) { 6274 customData = customSort.call( settings.oInstance, settings, idx, 6275 _fnColumnIndexToVisible( settings, idx ) 6276 ); 6277 } 6278 6279 // Use / populate cache 6280 var row, cellData; 6281 var formatter = DataTable.ext.type.order[ column.sType+"-pre" ]; 6282 6283 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 6284 row = settings.aoData[i]; 6285 6286 if ( ! row._aSortData ) { 6287 row._aSortData = []; 6288 } 6289 6290 if ( ! row._aSortData[idx] || customSort ) { 6291 cellData = customSort ? 6292 customData[i] : // If there was a custom sort function, use data from there 6293 _fnGetCellData( settings, i, idx, 'sort' ); 6294 6295 row._aSortData[ idx ] = formatter ? 6296 formatter( cellData ) : 6297 cellData; 6298 } 6299 } 6300 } 6301 6302 6303 6304 /** 6305 * Save the state of a table 6306 * @param {object} oSettings dataTables settings object 6307 * @memberof DataTable#oApi 6308 */ 6309 function _fnSaveState ( settings ) 6310 { 6311 if ( !settings.oFeatures.bStateSave || settings.bDestroying ) 6312 { 6313 return; 6314 } 6315 6316 /* Store the interesting variables */ 6317 var state = { 6318 time: +new Date(), 6319 start: settings._iDisplayStart, 6320 length: settings._iDisplayLength, 6321 order: $.extend( true, [], settings.aaSorting ), 6322 search: _fnSearchToCamel( settings.oPreviousSearch ), 6323 columns: $.map( settings.aoColumns, function ( col, i ) { 6324 return { 6325 visible: col.bVisible, 6326 search: _fnSearchToCamel( settings.aoPreSearchCols[i] ) 6327 }; 6328 } ) 6329 }; 6330 6331 _fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] ); 6332 6333 settings.oSavedState = state; 6334 settings.fnStateSaveCallback.call( settings.oInstance, settings, state ); 6335 } 6336 6337 6338 /** 6339 * Attempt to load a saved table state 6340 * @param {object} oSettings dataTables settings object 6341 * @param {object} oInit DataTables init object so we can override settings 6342 * @param {function} callback Callback to execute when the state has been loaded 6343 * @memberof DataTable#oApi 6344 */ 6345 function _fnLoadState ( settings, oInit, callback ) 6346 { 6347 var i, ien; 6348 var columns = settings.aoColumns; 6349 var loaded = function ( s ) { 6350 if ( ! s || ! s.time ) { 6351 callback(); 6352 return; 6353 } 6354 6355 // Allow custom and plug-in manipulation functions to alter the saved data set and 6356 // cancelling of loading by returning false 6357 var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] ); 6358 if ( $.inArray( false, abStateLoad ) !== -1 ) { 6359 callback(); 6360 return; 6361 } 6362 6363 // Reject old data 6364 var duration = settings.iStateDuration; 6365 if ( duration > 0 && s.time < +new Date() - (duration*1000) ) { 6366 callback(); 6367 return; 6368 } 6369 6370 // Number of columns have changed - all bets are off, no restore of settings 6371 if ( s.columns && columns.length !== s.columns.length ) { 6372 callback(); 6373 return; 6374 } 6375 6376 // Store the saved state so it might be accessed at any time 6377 settings.oLoadedState = $.extend( true, {}, s ); 6378 6379 // Restore key features - todo - for 1.11 this needs to be done by 6380 // subscribed events 6381 if ( s.start !== undefined ) { 6382 settings._iDisplayStart = s.start; 6383 settings.iInitDisplayStart = s.start; 6384 } 6385 if ( s.length !== undefined ) { 6386 settings._iDisplayLength = s.length; 6387 } 6388 6389 // Order 6390 if ( s.order !== undefined ) { 6391 settings.aaSorting = []; 6392 $.each( s.order, function ( i, col ) { 6393 settings.aaSorting.push( col[0] >= columns.length ? 6394 [ 0, col[1] ] : 6395 col 6396 ); 6397 } ); 6398 } 6399 6400 // Search 6401 if ( s.search !== undefined ) { 6402 $.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) ); 6403 } 6404 6405 // Columns 6406 // 6407 if ( s.columns ) { 6408 for ( i=0, ien=s.columns.length ; i<ien ; i++ ) { 6409 var col = s.columns[i]; 6410 6411 // Visibility 6412 if ( col.visible !== undefined ) { 6413 columns[i].bVisible = col.visible; 6414 } 6415 6416 // Search 6417 if ( col.search !== undefined ) { 6418 $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) ); 6419 } 6420 } 6421 } 6422 6423 _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] ); 6424 callback(); 6425 } 6426 6427 if ( ! settings.oFeatures.bStateSave ) { 6428 callback(); 6429 return; 6430 } 6431 6432 var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded ); 6433 6434 if ( state !== undefined ) { 6435 loaded( state ); 6436 } 6437 // otherwise, wait for the loaded callback to be executed 6438 } 6439 6440 6441 /** 6442 * Return the settings object for a particular table 6443 * @param {node} table table we are using as a dataTable 6444 * @returns {object} Settings object - or null if not found 6445 * @memberof DataTable#oApi 6446 */ 6447 function _fnSettingsFromNode ( table ) 6448 { 6449 var settings = DataTable.settings; 6450 var idx = $.inArray( table, _pluck( settings, 'nTable' ) ); 6451 6452 return idx !== -1 ? 6453 settings[ idx ] : 6454 null; 6455 } 6456 6457 6458 /** 6459 * Log an error message 6460 * @param {object} settings dataTables settings object 6461 * @param {int} level log error messages, or display them to the user 6462 * @param {string} msg error message 6463 * @param {int} tn Technical note id to get more information about the error. 6464 * @memberof DataTable#oApi 6465 */ 6466 function _fnLog( settings, level, msg, tn ) 6467 { 6468 msg = 'DataTables warning: '+ 6469 (settings ? 'table id='+settings.sTableId+' - ' : '')+msg; 6470 6471 if ( tn ) { 6472 msg += '. For more information about this error, please see '+ 6473 'http://datatables.net/tn/'+tn; 6474 } 6475 6476 if ( ! level ) { 6477 // Backwards compatibility pre 1.10 6478 var ext = DataTable.ext; 6479 var type = ext.sErrMode || ext.errMode; 6480 6481 if ( settings ) { 6482 _fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] ); 6483 } 6484 6485 if ( type == 'alert' ) { 6486 alert( msg ); 6487 } 6488 else if ( type == 'throw' ) { 6489 throw new Error(msg); 6490 } 6491 else if ( typeof type == 'function' ) { 6492 type( settings, tn, msg ); 6493 } 6494 } 6495 else if ( window.console && console.log ) { 6496 console.log( msg ); 6497 } 6498 } 6499 6500 6501 /** 6502 * See if a property is defined on one object, if so assign it to the other object 6503 * @param {object} ret target object 6504 * @param {object} src source object 6505 * @param {string} name property 6506 * @param {string} [mappedName] name to map too - optional, name used if not given 6507 * @memberof DataTable#oApi 6508 */ 6509 function _fnMap( ret, src, name, mappedName ) 6510 { 6511 if ( $.isArray( name ) ) { 6512 $.each( name, function (i, val) { 6513 if ( $.isArray( val ) ) { 6514 _fnMap( ret, src, val[0], val[1] ); 6515 } 6516 else { 6517 _fnMap( ret, src, val ); 6518 } 6519 } ); 6520 6521 return; 6522 } 6523 6524 if ( mappedName === undefined ) { 6525 mappedName = name; 6526 } 6527 6528 if ( src[name] !== undefined ) { 6529 ret[mappedName] = src[name]; 6530 } 6531 } 6532 6533 6534 /** 6535 * Extend objects - very similar to jQuery.extend, but deep copy objects, and 6536 * shallow copy arrays. The reason we need to do this, is that we don't want to 6537 * deep copy array init values (such as aaSorting) since the dev wouldn't be 6538 * able to override them, but we do want to deep copy arrays. 6539 * @param {object} out Object to extend 6540 * @param {object} extender Object from which the properties will be applied to 6541 * out 6542 * @param {boolean} breakRefs If true, then arrays will be sliced to take an 6543 * independent copy with the exception of the `data` or `aaData` parameters 6544 * if they are present. This is so you can pass in a collection to 6545 * DataTables and have that used as your data source without breaking the 6546 * references 6547 * @returns {object} out Reference, just for convenience - out === the return. 6548 * @memberof DataTable#oApi 6549 * @todo This doesn't take account of arrays inside the deep copied objects. 6550 */ 6551 function _fnExtend( out, extender, breakRefs ) 6552 { 6553 var val; 6554 6555 for ( var prop in extender ) { 6556 if ( extender.hasOwnProperty(prop) ) { 6557 val = extender[prop]; 6558 6559 if ( $.isPlainObject( val ) ) { 6560 if ( ! $.isPlainObject( out[prop] ) ) { 6561 out[prop] = {}; 6562 } 6563 $.extend( true, out[prop], val ); 6564 } 6565 else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) { 6566 out[prop] = val.slice(); 6567 } 6568 else { 6569 out[prop] = val; 6570 } 6571 } 6572 } 6573 6574 return out; 6575 } 6576 6577 6578 /** 6579 * Bind an event handers to allow a click or return key to activate the callback. 6580 * This is good for accessibility since a return on the keyboard will have the 6581 * same effect as a click, if the element has focus. 6582 * @param {element} n Element to bind the action to 6583 * @param {object} oData Data object to pass to the triggered function 6584 * @param {function} fn Callback function for when the event is triggered 6585 * @memberof DataTable#oApi 6586 */ 6587 function _fnBindAction( n, oData, fn ) 6588 { 6589 $(n) 6590 .on( 'click.DT', oData, function (e) { 6591 $(n).blur(); // Remove focus outline for mouse users 6592 fn(e); 6593 } ) 6594 .on( 'keypress.DT', oData, function (e){ 6595 if ( e.which === 13 ) { 6596 e.preventDefault(); 6597 fn(e); 6598 } 6599 } ) 6600 .on( 'selectstart.DT', function () { 6601 /* Take the brutal approach to cancelling text selection */ 6602 return false; 6603 } ); 6604 } 6605 6606 6607 /** 6608 * Register a callback function. Easily allows a callback function to be added to 6609 * an array store of callback functions that can then all be called together. 6610 * @param {object} oSettings dataTables settings object 6611 * @param {string} sStore Name of the array storage for the callbacks in oSettings 6612 * @param {function} fn Function to be called back 6613 * @param {string} sName Identifying name for the callback (i.e. a label) 6614 * @memberof DataTable#oApi 6615 */ 6616 function _fnCallbackReg( oSettings, sStore, fn, sName ) 6617 { 6618 if ( fn ) 6619 { 6620 oSettings[sStore].push( { 6621 "fn": fn, 6622 "sName": sName 6623 } ); 6624 } 6625 } 6626 6627 6628 /** 6629 * Fire callback functions and trigger events. Note that the loop over the 6630 * callback array store is done backwards! Further note that you do not want to 6631 * fire off triggers in time sensitive applications (for example cell creation) 6632 * as its slow. 6633 * @param {object} settings dataTables settings object 6634 * @param {string} callbackArr Name of the array storage for the callbacks in 6635 * oSettings 6636 * @param {string} eventName Name of the jQuery custom event to trigger. If 6637 * null no trigger is fired 6638 * @param {array} args Array of arguments to pass to the callback function / 6639 * trigger 6640 * @memberof DataTable#oApi 6641 */ 6642 function _fnCallbackFire( settings, callbackArr, eventName, args ) 6643 { 6644 var ret = []; 6645 6646 if ( callbackArr ) { 6647 ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) { 6648 return val.fn.apply( settings.oInstance, args ); 6649 } ); 6650 } 6651 6652 if ( eventName !== null ) { 6653 var e = $.Event( eventName+'.dt' ); 6654 6655 $(settings.nTable).trigger( e, args ); 6656 6657 ret.push( e.result ); 6658 } 6659 6660 return ret; 6661 } 6662 6663 6664 function _fnLengthOverflow ( settings ) 6665 { 6666 var 6667 start = settings._iDisplayStart, 6668 end = settings.fnDisplayEnd(), 6669 len = settings._iDisplayLength; 6670 6671 /* If we have space to show extra rows (backing up from the end point - then do so */ 6672 if ( start >= end ) 6673 { 6674 start = end - len; 6675 } 6676 6677 // Keep the start record on the current page 6678 start -= (start % len); 6679 6680 if ( len === -1 || start < 0 ) 6681 { 6682 start = 0; 6683 } 6684 6685 settings._iDisplayStart = start; 6686 } 6687 6688 6689 function _fnRenderer( settings, type ) 6690 { 6691 var renderer = settings.renderer; 6692 var host = DataTable.ext.renderer[type]; 6693 6694 if ( $.isPlainObject( renderer ) && renderer[type] ) { 6695 // Specific renderer for this type. If available use it, otherwise use 6696 // the default. 6697 return host[renderer[type]] || host._; 6698 } 6699 else if ( typeof renderer === 'string' ) { 6700 // Common renderer - if there is one available for this type use it, 6701 // otherwise use the default 6702 return host[renderer] || host._; 6703 } 6704 6705 // Use the default 6706 return host._; 6707 } 6708 6709 6710 /** 6711 * Detect the data source being used for the table. Used to simplify the code 6712 * a little (ajax) and to make it compress a little smaller. 6713 * 6714 * @param {object} settings dataTables settings object 6715 * @returns {string} Data source 6716 * @memberof DataTable#oApi 6717 */ 6718 function _fnDataSource ( settings ) 6719 { 6720 if ( settings.oFeatures.bServerSide ) { 6721 return 'ssp'; 6722 } 6723 else if ( settings.ajax || settings.sAjaxSource ) { 6724 return 'ajax'; 6725 } 6726 return 'dom'; 6727 } 6728 6729 6730 6731 6732 /** 6733 * Computed structure of the DataTables API, defined by the options passed to 6734 * `DataTable.Api.register()` when building the API. 6735 * 6736 * The structure is built in order to speed creation and extension of the Api 6737 * objects since the extensions are effectively pre-parsed. 6738 * 6739 * The array is an array of objects with the following structure, where this 6740 * base array represents the Api prototype base: 6741 * 6742 * [ 6743 * { 6744 * name: 'data' -- string - Property name 6745 * val: function () {}, -- function - Api method (or undefined if just an object 6746 * methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result 6747 * propExt: [ ... ] -- array - Array of Api object definitions to extend the property 6748 * }, 6749 * { 6750 * name: 'row' 6751 * val: {}, 6752 * methodExt: [ ... ], 6753 * propExt: [ 6754 * { 6755 * name: 'data' 6756 * val: function () {}, 6757 * methodExt: [ ... ], 6758 * propExt: [ ... ] 6759 * }, 6760 * ... 6761 * ] 6762 * } 6763 * ] 6764 * 6765 * @type {Array} 6766 * @ignore 6767 */ 6768 var __apiStruct = []; 6769 6770 6771 /** 6772 * `Array.prototype` reference. 6773 * 6774 * @type object 6775 * @ignore 6776 */ 6777 var __arrayProto = Array.prototype; 6778 6779 6780 /** 6781 * Abstraction for `context` parameter of the `Api` constructor to allow it to 6782 * take several different forms for ease of use. 6783 * 6784 * Each of the input parameter types will be converted to a DataTables settings 6785 * object where possible. 6786 * 6787 * @param {string|node|jQuery|object} mixed DataTable identifier. Can be one 6788 * of: 6789 * 6790 * * `string` - jQuery selector. Any DataTables' matching the given selector 6791 * with be found and used. 6792 * * `node` - `TABLE` node which has already been formed into a DataTable. 6793 * * `jQuery` - A jQuery object of `TABLE` nodes. 6794 * * `object` - DataTables settings object 6795 * * `DataTables.Api` - API instance 6796 * @return {array|null} Matching DataTables settings objects. `null` or 6797 * `undefined` is returned if no matching DataTable is found. 6798 * @ignore 6799 */ 6800 var _toSettings = function ( mixed ) 6801 { 6802 var idx, jq; 6803 var settings = DataTable.settings; 6804 var tables = $.map( settings, function (el, i) { 6805 return el.nTable; 6806 } ); 6807 6808 if ( ! mixed ) { 6809 return []; 6810 } 6811 else if ( mixed.nTable && mixed.oApi ) { 6812 // DataTables settings object 6813 return [ mixed ]; 6814 } 6815 else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) { 6816 // Table node 6817 idx = $.inArray( mixed, tables ); 6818 return idx !== -1 ? [ settings[idx] ] : null; 6819 } 6820 else if ( mixed && typeof mixed.settings === 'function' ) { 6821 return mixed.settings().toArray(); 6822 } 6823 else if ( typeof mixed === 'string' ) { 6824 // jQuery selector 6825 jq = $(mixed); 6826 } 6827 else if ( mixed instanceof $ ) { 6828 // jQuery object (also DataTables instance) 6829 jq = mixed; 6830 } 6831 6832 if ( jq ) { 6833 return jq.map( function(i) { 6834 idx = $.inArray( this, tables ); 6835 return idx !== -1 ? settings[idx] : null; 6836 } ).toArray(); 6837 } 6838 }; 6839 6840 6841 /** 6842 * DataTables API class - used to control and interface with one or more 6843 * DataTables enhanced tables. 6844 * 6845 * The API class is heavily based on jQuery, presenting a chainable interface 6846 * that you can use to interact with tables. Each instance of the API class has 6847 * a "context" - i.e. the tables that it will operate on. This could be a single 6848 * table, all tables on a page or a sub-set thereof. 6849 * 6850 * Additionally the API is designed to allow you to easily work with the data in 6851 * the tables, retrieving and manipulating it as required. This is done by 6852 * presenting the API class as an array like interface. The contents of the 6853 * array depend upon the actions requested by each method (for example 6854 * `rows().nodes()` will return an array of nodes, while `rows().data()` will 6855 * return an array of objects or arrays depending upon your table's 6856 * configuration). The API object has a number of array like methods (`push`, 6857 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`, 6858 * `unique` etc) to assist your working with the data held in a table. 6859 * 6860 * Most methods (those which return an Api instance) are chainable, which means 6861 * the return from a method call also has all of the methods available that the 6862 * top level object had. For example, these two calls are equivalent: 6863 * 6864 * // Not chained 6865 * api.row.add( {...} ); 6866 * api.draw(); 6867 * 6868 * // Chained 6869 * api.row.add( {...} ).draw(); 6870 * 6871 * @class DataTable.Api 6872 * @param {array|object|string|jQuery} context DataTable identifier. This is 6873 * used to define which DataTables enhanced tables this API will operate on. 6874 * Can be one of: 6875 * 6876 * * `string` - jQuery selector. Any DataTables' matching the given selector 6877 * with be found and used. 6878 * * `node` - `TABLE` node which has already been formed into a DataTable. 6879 * * `jQuery` - A jQuery object of `TABLE` nodes. 6880 * * `object` - DataTables settings object 6881 * @param {array} [data] Data to initialise the Api instance with. 6882 * 6883 * @example 6884 * // Direct initialisation during DataTables construction 6885 * var api = $('#example').DataTable(); 6886 * 6887 * @example 6888 * // Initialisation using a DataTables jQuery object 6889 * var api = $('#example').dataTable().api(); 6890 * 6891 * @example 6892 * // Initialisation as a constructor 6893 * var api = new $.fn.DataTable.Api( 'table.dataTable' ); 6894 */ 6895 _Api = function ( context, data ) 6896 { 6897 if ( ! (this instanceof _Api) ) { 6898 return new _Api( context, data ); 6899 } 6900 6901 var settings = []; 6902 var ctxSettings = function ( o ) { 6903 var a = _toSettings( o ); 6904 if ( a ) { 6905 settings = settings.concat( a ); 6906 } 6907 }; 6908 6909 if ( $.isArray( context ) ) { 6910 for ( var i=0, ien=context.length ; i<ien ; i++ ) { 6911 ctxSettings( context[i] ); 6912 } 6913 } 6914 else { 6915 ctxSettings( context ); 6916 } 6917 6918 // Remove duplicates 6919 this.context = _unique( settings ); 6920 6921 // Initial data 6922 if ( data ) { 6923 $.merge( this, data ); 6924 } 6925 6926 // selector 6927 this.selector = { 6928 rows: null, 6929 cols: null, 6930 opts: null 6931 }; 6932 6933 _Api.extend( this, this, __apiStruct ); 6934 }; 6935 6936 DataTable.Api = _Api; 6937 6938 // Don't destroy the existing prototype, just extend it. Required for jQuery 2's 6939 // isPlainObject. 6940 $.extend( _Api.prototype, { 6941 any: function () 6942 { 6943 return this.count() !== 0; 6944 }, 6945 6946 6947 concat: __arrayProto.concat, 6948 6949 6950 context: [], // array of table settings objects 6951 6952 6953 count: function () 6954 { 6955 return this.flatten().length; 6956 }, 6957 6958 6959 each: function ( fn ) 6960 { 6961 for ( var i=0, ien=this.length ; i<ien; i++ ) { 6962 fn.call( this, this[i], i, this ); 6963 } 6964 6965 return this; 6966 }, 6967 6968 6969 eq: function ( idx ) 6970 { 6971 var ctx = this.context; 6972 6973 return ctx.length > idx ? 6974 new _Api( ctx[idx], this[idx] ) : 6975 null; 6976 }, 6977 6978 6979 filter: function ( fn ) 6980 { 6981 var a = []; 6982 6983 if ( __arrayProto.filter ) { 6984 a = __arrayProto.filter.call( this, fn, this ); 6985 } 6986 else { 6987 // Compatibility for browsers without EMCA-252-5 (JS 1.6) 6988 for ( var i=0, ien=this.length ; i<ien ; i++ ) { 6989 if ( fn.call( this, this[i], i, this ) ) { 6990 a.push( this[i] ); 6991 } 6992 } 6993 } 6994 6995 return new _Api( this.context, a ); 6996 }, 6997 6998 6999 flatten: function () 7000 { 7001 var a = []; 7002 return new _Api( this.context, a.concat.apply( a, this.toArray() ) ); 7003 }, 7004 7005 7006 join: __arrayProto.join, 7007 7008 7009 indexOf: __arrayProto.indexOf || function (obj, start) 7010 { 7011 for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) { 7012 if ( this[i] === obj ) { 7013 return i; 7014 } 7015 } 7016 return -1; 7017 }, 7018 7019 iterator: function ( flatten, type, fn, alwaysNew ) { 7020 var 7021 a = [], ret, 7022 i, ien, j, jen, 7023 context = this.context, 7024 rows, items, item, 7025 selector = this.selector; 7026 7027 // Argument shifting 7028 if ( typeof flatten === 'string' ) { 7029 alwaysNew = fn; 7030 fn = type; 7031 type = flatten; 7032 flatten = false; 7033 } 7034 7035 for ( i=0, ien=context.length ; i<ien ; i++ ) { 7036 var apiInst = new _Api( context[i] ); 7037 7038 if ( type === 'table' ) { 7039 ret = fn.call( apiInst, context[i], i ); 7040 7041 if ( ret !== undefined ) { 7042 a.push( ret ); 7043 } 7044 } 7045 else if ( type === 'columns' || type === 'rows' ) { 7046 // this has same length as context - one entry for each table 7047 ret = fn.call( apiInst, context[i], this[i], i ); 7048 7049 if ( ret !== undefined ) { 7050 a.push( ret ); 7051 } 7052 } 7053 else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) { 7054 // columns and rows share the same structure. 7055 // 'this' is an array of column indexes for each context 7056 items = this[i]; 7057 7058 if ( type === 'column-rows' ) { 7059 rows = _selector_row_indexes( context[i], selector.opts ); 7060 } 7061 7062 for ( j=0, jen=items.length ; j<jen ; j++ ) { 7063 item = items[j]; 7064 7065 if ( type === 'cell' ) { 7066 ret = fn.call( apiInst, context[i], item.row, item.column, i, j ); 7067 } 7068 else { 7069 ret = fn.call( apiInst, context[i], item, i, j, rows ); 7070 } 7071 7072 if ( ret !== undefined ) { 7073 a.push( ret ); 7074 } 7075 } 7076 } 7077 } 7078 7079 if ( a.length || alwaysNew ) { 7080 var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a ); 7081 var apiSelector = api.selector; 7082 apiSelector.rows = selector.rows; 7083 apiSelector.cols = selector.cols; 7084 apiSelector.opts = selector.opts; 7085 return api; 7086 } 7087 return this; 7088 }, 7089 7090 7091 lastIndexOf: __arrayProto.lastIndexOf || function (obj, start) 7092 { 7093 // Bit cheeky... 7094 return this.indexOf.apply( this.toArray.reverse(), arguments ); 7095 }, 7096 7097 7098 length: 0, 7099 7100 7101 map: function ( fn ) 7102 { 7103 var a = []; 7104 7105 if ( __arrayProto.map ) { 7106 a = __arrayProto.map.call( this, fn, this ); 7107 } 7108 else { 7109 // Compatibility for browsers without EMCA-252-5 (JS 1.6) 7110 for ( var i=0, ien=this.length ; i<ien ; i++ ) { 7111 a.push( fn.call( this, this[i], i ) ); 7112 } 7113 } 7114 7115 return new _Api( this.context, a ); 7116 }, 7117 7118 7119 pluck: function ( prop ) 7120 { 7121 return this.map( function ( el ) { 7122 return el[ prop ]; 7123 } ); 7124 }, 7125 7126 pop: __arrayProto.pop, 7127 7128 7129 push: __arrayProto.push, 7130 7131 7132 // Does not return an API instance 7133 reduce: __arrayProto.reduce || function ( fn, init ) 7134 { 7135 return _fnReduce( this, fn, init, 0, this.length, 1 ); 7136 }, 7137 7138 7139 reduceRight: __arrayProto.reduceRight || function ( fn, init ) 7140 { 7141 return _fnReduce( this, fn, init, this.length-1, -1, -1 ); 7142 }, 7143 7144 7145 reverse: __arrayProto.reverse, 7146 7147 7148 // Object with rows, columns and opts 7149 selector: null, 7150 7151 7152 shift: __arrayProto.shift, 7153 7154 7155 slice: function () { 7156 return new _Api( this.context, this ); 7157 }, 7158 7159 7160 sort: __arrayProto.sort, // ? name - order? 7161 7162 7163 splice: __arrayProto.splice, 7164 7165 7166 toArray: function () 7167 { 7168 return __arrayProto.slice.call( this ); 7169 }, 7170 7171 7172 to$: function () 7173 { 7174 return $( this ); 7175 }, 7176 7177 7178 toJQuery: function () 7179 { 7180 return $( this ); 7181 }, 7182 7183 7184 unique: function () 7185 { 7186 return new _Api( this.context, _unique(this) ); 7187 }, 7188 7189 7190 unshift: __arrayProto.unshift 7191 } ); 7192 7193 7194 _Api.extend = function ( scope, obj, ext ) 7195 { 7196 // Only extend API instances and static properties of the API 7197 if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) { 7198 return; 7199 } 7200 7201 var 7202 i, ien, 7203 j, jen, 7204 struct, inner, 7205 methodScoping = function ( scope, fn, struc ) { 7206 return function () { 7207 var ret = fn.apply( scope, arguments ); 7208 7209 // Method extension 7210 _Api.extend( ret, ret, struc.methodExt ); 7211 return ret; 7212 }; 7213 }; 7214 7215 for ( i=0, ien=ext.length ; i<ien ; i++ ) { 7216 struct = ext[i]; 7217 7218 // Value 7219 obj[ struct.name ] = typeof struct.val === 'function' ? 7220 methodScoping( scope, struct.val, struct ) : 7221 $.isPlainObject( struct.val ) ? 7222 {} : 7223 struct.val; 7224 7225 obj[ struct.name ].__dt_wrapper = true; 7226 7227 // Property extension 7228 _Api.extend( scope, obj[ struct.name ], struct.propExt ); 7229 } 7230 }; 7231 7232 7233 // @todo - Is there need for an augment function? 7234 // _Api.augment = function ( inst, name ) 7235 // { 7236 // // Find src object in the structure from the name 7237 // var parts = name.split('.'); 7238 7239 // _Api.extend( inst, obj ); 7240 // }; 7241 7242 7243 // [ 7244 // { 7245 // name: 'data' -- string - Property name 7246 // val: function () {}, -- function - Api method (or undefined if just an object 7247 // methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result 7248 // propExt: [ ... ] -- array - Array of Api object definitions to extend the property 7249 // }, 7250 // { 7251 // name: 'row' 7252 // val: {}, 7253 // methodExt: [ ... ], 7254 // propExt: [ 7255 // { 7256 // name: 'data' 7257 // val: function () {}, 7258 // methodExt: [ ... ], 7259 // propExt: [ ... ] 7260 // }, 7261 // ... 7262 // ] 7263 // } 7264 // ] 7265 7266 _Api.register = _api_register = function ( name, val ) 7267 { 7268 if ( $.isArray( name ) ) { 7269 for ( var j=0, jen=name.length ; j<jen ; j++ ) { 7270 _Api.register( name[j], val ); 7271 } 7272 return; 7273 } 7274 7275 var 7276 i, ien, 7277 heir = name.split('.'), 7278 struct = __apiStruct, 7279 key, method; 7280 7281 var find = function ( src, name ) { 7282 for ( var i=0, ien=src.length ; i<ien ; i++ ) { 7283 if ( src[i].name === name ) { 7284 return src[i]; 7285 } 7286 } 7287 return null; 7288 }; 7289 7290 for ( i=0, ien=heir.length ; i<ien ; i++ ) { 7291 method = heir[i].indexOf('()') !== -1; 7292 key = method ? 7293 heir[i].replace('()', '') : 7294 heir[i]; 7295 7296 var src = find( struct, key ); 7297 if ( ! src ) { 7298 src = { 7299 name: key, 7300 val: {}, 7301 methodExt: [], 7302 propExt: [] 7303 }; 7304 struct.push( src ); 7305 } 7306 7307 if ( i === ien-1 ) { 7308 src.val = val; 7309 } 7310 else { 7311 struct = method ? 7312 src.methodExt : 7313 src.propExt; 7314 } 7315 } 7316 }; 7317 7318 7319 _Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) { 7320 _Api.register( pluralName, val ); 7321 7322 _Api.register( singularName, function () { 7323 var ret = val.apply( this, arguments ); 7324 7325 if ( ret === this ) { 7326 // Returned item is the API instance that was passed in, return it 7327 return this; 7328 } 7329 else if ( ret instanceof _Api ) { 7330 // New API instance returned, want the value from the first item 7331 // in the returned array for the singular result. 7332 return ret.length ? 7333 $.isArray( ret[0] ) ? 7334 new _Api( ret.context, ret[0] ) : // Array results are 'enhanced' 7335 ret[0] : 7336 undefined; 7337 } 7338 7339 // Non-API return - just fire it back 7340 return ret; 7341 } ); 7342 }; 7343 7344 7345 /** 7346 * Selector for HTML tables. Apply the given selector to the give array of 7347 * DataTables settings objects. 7348 * 7349 * @param {string|integer} [selector] jQuery selector string or integer 7350 * @param {array} Array of DataTables settings objects to be filtered 7351 * @return {array} 7352 * @ignore 7353 */ 7354 var __table_selector = function ( selector, a ) 7355 { 7356 // Integer is used to pick out a table by index 7357 if ( typeof selector === 'number' ) { 7358 return [ a[ selector ] ]; 7359 } 7360 7361 // Perform a jQuery selector on the table nodes 7362 var nodes = $.map( a, function (el, i) { 7363 return el.nTable; 7364 } ); 7365 7366 return $(nodes) 7367 .filter( selector ) 7368 .map( function (i) { 7369 // Need to translate back from the table node to the settings 7370 var idx = $.inArray( this, nodes ); 7371 return a[ idx ]; 7372 } ) 7373 .toArray(); 7374 }; 7375 7376 7377 7378 /** 7379 * Context selector for the API's context (i.e. the tables the API instance 7380 * refers to. 7381 * 7382 * @name DataTable.Api#tables 7383 * @param {string|integer} [selector] Selector to pick which tables the iterator 7384 * should operate on. If not given, all tables in the current context are 7385 * used. This can be given as a jQuery selector (for example `':gt(0)'`) to 7386 * select multiple tables or as an integer to select a single table. 7387 * @returns {DataTable.Api} Returns a new API instance if a selector is given. 7388 */ 7389 _api_register( 'tables()', function ( selector ) { 7390 // A new instance is created if there was a selector specified 7391 return selector
vendor: 9,632 bytes, lines 7391-7739
7391 ? 7392 new _Api( __table_selector( selector, this.context ) ) : 7393 this; 7394 } ); 7395 7396 7397 _api_register( 'table()', function ( selector ) { 7398 var tables = this.tables( selector ); 7399 var ctx = tables.context; 7400 7401 // Truncate to the first matched table 7402 return ctx.length ? 7403 new _Api( ctx[0] ) : 7404 tables; 7405 } ); 7406 7407 7408 _api_registerPlural( 'tables().nodes()', 'table().node()' , function () { 7409 return this.iterator( 'table', function ( ctx ) { 7410 return ctx.nTable; 7411 }, 1 ); 7412 } ); 7413 7414 7415 _api_registerPlural( 'tables().body()', 'table().body()' , function () { 7416 return this.iterator( 'table', function ( ctx ) { 7417 return ctx.nTBody; 7418 }, 1 ); 7419 } ); 7420 7421 7422 _api_registerPlural( 'tables().header()', 'table().header()' , function () { 7423 return this.iterator( 'table', function ( ctx ) { 7424 return ctx.nTHead; 7425 }, 1 ); 7426 } ); 7427 7428 7429 _api_registerPlural( 'tables().footer()', 'table().footer()' , function () { 7430 return this.iterator( 'table', function ( ctx ) { 7431 return ctx.nTFoot; 7432 }, 1 ); 7433 } ); 7434 7435 7436 _api_registerPlural( 'tables().containers()', 'table().container()' , function () { 7437 return this.iterator( 'table', function ( ctx ) { 7438 return ctx.nTableWrapper; 7439 }, 1 ); 7440 } ); 7441 7442 7443 7444 /** 7445 * Redraw the tables in the current context. 7446 */ 7447 _api_register( 'draw()', function ( paging ) { 7448 return this.iterator( 'table', function ( settings ) { 7449 if ( paging === 'page' ) { 7450 _fnDraw( settings ); 7451 } 7452 else { 7453 if ( typeof paging === 'string' ) { 7454 paging = paging === 'full-hold' ? 7455 false : 7456 true; 7457 } 7458 7459 _fnReDraw( settings, paging===false ); 7460 } 7461 } ); 7462 } ); 7463 7464 7465 7466 /** 7467 * Get the current page index. 7468 * 7469 * @return {integer} Current page index (zero based) 7470 *//** 7471 * Set the current page. 7472 * 7473 * Note that if you attempt to show a page which does not exist, DataTables will 7474 * not throw an error, but rather reset the paging. 7475 * 7476 * @param {integer|string} action The paging action to take. This can be one of: 7477 * * `integer` - The page index to jump to 7478 * * `string` - An action to take: 7479 * * `first` - Jump to first page. 7480 * * `next` - Jump to the next page 7481 * * `previous` - Jump to previous page 7482 * * `last` - Jump to the last page. 7483 * @returns {DataTables.Api} this 7484 */ 7485 _api_register( 'page()', function ( action ) { 7486 if ( action === undefined ) { 7487 return this.page.info().page; // not an expensive call 7488 } 7489 7490 // else, have an action to take on all tables 7491 return this.iterator( 'table', function ( settings ) { 7492 _fnPageChange( settings, action ); 7493 } ); 7494 } ); 7495 7496 7497 /** 7498 * Paging information for the first table in the current context. 7499 * 7500 * If you require paging information for another table, use the `table()` method 7501 * with a suitable selector. 7502 * 7503 * @return {object} Object with the following properties set: 7504 * * `page` - Current page index (zero based - i.e. the first page is `0`) 7505 * * `pages` - Total number of pages 7506 * * `start` - Display index for the first record shown on the current page 7507 * * `end` - Display index for the last record shown on the current page 7508 * * `length` - Display length (number of records). Note that generally `start 7509 * + length = end`, but this is not always true, for example if there are 7510 * only 2 records to show on the final page, with a length of 10. 7511 * * `recordsTotal` - Full data set length 7512 * * `recordsDisplay` - Data set length once the current filtering criterion 7513 * are applied. 7514 */ 7515 _api_register( 'page.info()', function ( action ) { 7516 if ( this.context.length === 0 ) { 7517 return undefined; 7518 } 7519 7520 var 7521 settings = this.context[0], 7522 start = settings._iDisplayStart, 7523 len = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1, 7524 visRecords = settings.fnRecordsDisplay(), 7525 all = len === -1; 7526 7527 return { 7528 "page": all ? 0 : Math.floor( start / len ), 7529 "pages": all ? 1 : Math.ceil( visRecords / len ), 7530 "start": start, 7531 "end": settings.fnDisplayEnd(), 7532 "length": len, 7533 "recordsTotal": settings.fnRecordsTotal(), 7534 "recordsDisplay": visRecords, 7535 "serverSide": _fnDataSource( settings ) === 'ssp' 7536 }; 7537 } ); 7538 7539 7540 /** 7541 * Get the current page length. 7542 * 7543 * @return {integer} Current page length. Note `-1` indicates that all records 7544 * are to be shown. 7545 *//** 7546 * Set the current page length. 7547 * 7548 * @param {integer} Page length to set. Use `-1` to show all records. 7549 * @returns {DataTables.Api} this 7550 */ 7551 _api_register( 'page.len()', function ( len ) { 7552 // Note that we can't call this function 'length()' because `length` 7553 // is a Javascript property of functions which defines how many arguments 7554 // the function expects. 7555 if ( len === undefined ) { 7556 return this.context.length !== 0 ? 7557 this.context[0]._iDisplayLength : 7558 undefined; 7559 } 7560 7561 // else, set the page length 7562 return this.iterator( 'table', function ( settings ) { 7563 _fnLengthChange( settings, len ); 7564 } ); 7565 } ); 7566 7567 7568 7569 var __reload = function ( settings, holdPosition, callback ) { 7570 // Use the draw event to trigger a callback 7571 if ( callback ) { 7572 var api = new _Api( settings ); 7573 7574 api.one( 'draw', function () { 7575 callback( api.ajax.json() ); 7576 } ); 7577 } 7578 7579 if ( _fnDataSource( settings ) == 'ssp' ) { 7580 _fnReDraw( settings, holdPosition ); 7581 } 7582 else { 7583 _fnProcessingDisplay( settings, true ); 7584 7585 // Cancel an existing request 7586 var xhr = settings.jqXHR; 7587 if ( xhr && xhr.readyState !== 4 ) { 7588 xhr.abort(); 7589 } 7590 7591 // Trigger xhr 7592 _fnBuildAjax( settings, [], function( json ) { 7593 _fnClearTable( settings ); 7594 7595 var data = _fnAjaxDataSrc( settings, json ); 7596 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 7597 _fnAddData( settings, data[i] ); 7598 } 7599 7600 _fnReDraw( settings, holdPosition ); 7601 _fnProcessingDisplay( settings, false ); 7602 } ); 7603 } 7604 }; 7605 7606 7607 /** 7608 * Get the JSON response from the last Ajax request that DataTables made to the 7609 * server. Note that this returns the JSON from the first table in the current 7610 * context. 7611 * 7612 * @return {object} JSON received from the server. 7613 */ 7614 _api_register( 'ajax.json()', function () { 7615 var ctx = this.context; 7616 7617 if ( ctx.length > 0 ) { 7618 return ctx[0].json; 7619 } 7620 7621 // else return undefined; 7622 } ); 7623 7624 7625 /** 7626 * Get the data submitted in the last Ajax request 7627 */ 7628 _api_register( 'ajax.params()', function () { 7629 var ctx = this.context; 7630 7631 if ( ctx.length > 0 ) { 7632 return ctx[0].oAjaxData; 7633 } 7634 7635 // else return undefined; 7636 } ); 7637 7638 7639 /** 7640 * Reload tables from the Ajax data source. Note that this function will 7641 * automatically re-draw the table when the remote data has been loaded. 7642 * 7643 * @param {boolean} [reset=true] Reset (default) or hold the current paging 7644 * position. A full re-sort and re-filter is performed when this method is 7645 * called, which is why the pagination reset is the default action. 7646 * @returns {DataTables.Api} this 7647 */ 7648 _api_register( 'ajax.reload()', function ( callback, resetPaging ) { 7649 return this.iterator( 'table', function (settings) { 7650 __reload( settings, resetPaging===false, callback ); 7651 } ); 7652 } ); 7653 7654 7655 /** 7656 * Get the current Ajax URL. Note that this returns the URL from the first 7657 * table in the current context. 7658 * 7659 * @return {string} Current Ajax source URL 7660 *//** 7661 * Set the Ajax URL. Note that this will set the URL for all tables in the 7662 * current context. 7663 * 7664 * @param {string} url URL to set. 7665 * @returns {DataTables.Api} this 7666 */ 7667 _api_register( 'ajax.url()', function ( url ) { 7668 var ctx = this.context; 7669 7670 if ( url === undefined ) { 7671 // get 7672 if ( ctx.length === 0 ) { 7673 return undefined; 7674 } 7675 ctx = ctx[0]; 7676 7677 return ctx.ajax ? 7678 $.isPlainObject( ctx.ajax ) ? 7679 ctx.ajax.url : 7680 ctx.ajax : 7681 ctx.sAjaxSource; 7682 } 7683 7684 // set 7685 return this.iterator( 'table', function ( settings ) { 7686 if ( $.isPlainObject( settings.ajax ) ) { 7687 settings.ajax.url = url; 7688 } 7689 else { 7690 settings.ajax = url; 7691 } 7692 // No need to consider sAjaxSource here since DataTables gives priority 7693 // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any 7694 // value of `sAjaxSource` redundant. 7695 } ); 7696 } ); 7697 7698 7699 /** 7700 * Load data from the newly set Ajax URL. Note that this method is only 7701 * available when `ajax.url()` is used to set a URL. Additionally, this method 7702 * has the same effect as calling `ajax.reload()` but is provided for 7703 * convenience when setting a new URL. Like `ajax.reload()` it will 7704 * automatically redraw the table once the remote data has been loaded. 7705 * 7706 * @returns {DataTables.Api} this 7707 */ 7708 _api_register( 'ajax.url().load()', function ( callback, resetPaging ) { 7709 // Same as a reload, but makes sense to present it for easy access after a 7710 // url change 7711 return this.iterator( 'table', function ( ctx ) { 7712 __reload( ctx, resetPaging===false, callback ); 7713 } ); 7714 } ); 7715 7716 7717 7718 7719 var _selector_run = function ( type, selector, selectFn, settings, opts ) 7720 { 7721 var 7722 out = [], res, 7723 a, i, ien, j, jen, 7724 selectorType = typeof selector; 7725 7726 // Can't just check for isArray here, as an API or jQuery instance might be 7727 // given with their array like look 7728 if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) { 7729 selector = [ selector ]; 7730 } 7731 7732 for ( i=0, ien=selector.length ; i<ien ; i++ ) { 7733 // Only split on simple strings - complex expressions will be jQuery selectors 7734 a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ? 7735 selector[i].split(',') : 7736 [ selector[i] ]; 7737 7738 for ( j=0, jen=a.length ; j<jen ; j++ ) { 7739 res = selectFn( typeof a[j] === 'string' ?
vendor: 47,871 bytes, lines 7739-9539
7739$.trim(a[j]) : a[j] ); 7740 7741 if ( res && res.length ) { 7742 out = out.concat( res ); 7743 } 7744 } 7745 } 7746 7747 // selector extensions 7748 var ext = _ext.selector[ type ]; 7749 if ( ext.length ) { 7750 for ( i=0, ien=ext.length ; i<ien ; i++ ) { 7751 out = ext[i]( settings, opts, out ); 7752 } 7753 } 7754 7755 return _unique( out ); 7756 }; 7757 7758 7759 var _selector_opts = function ( opts ) 7760 { 7761 if ( ! opts ) { 7762 opts = {}; 7763 } 7764 7765 // Backwards compatibility for 1.9- which used the terminology filter rather 7766 // than search 7767 if ( opts.filter && opts.search === undefined ) { 7768 opts.search = opts.filter; 7769 } 7770 7771 return $.extend( { 7772 search: 'none', 7773 order: 'current', 7774 page: 'all' 7775 }, opts ); 7776 }; 7777 7778 7779 var _selector_first = function ( inst ) 7780 { 7781 // Reduce the API instance to the first item found 7782 for ( var i=0, ien=inst.length ; i<ien ; i++ ) { 7783 if ( inst[i].length > 0 ) { 7784 // Assign the first element to the first item in the instance 7785 // and truncate the instance and context 7786 inst[0] = inst[i]; 7787 inst[0].length = 1; 7788 inst.length = 1; 7789 inst.context = [ inst.context[i] ]; 7790 7791 return inst; 7792 } 7793 } 7794 7795 // Not found - return an empty instance 7796 inst.length = 0; 7797 return inst; 7798 }; 7799 7800 7801 var _selector_row_indexes = function ( settings, opts ) 7802 { 7803 var 7804 i, ien, tmp, a=[], 7805 displayFiltered = settings.aiDisplay, 7806 displayMaster = settings.aiDisplayMaster; 7807 7808 var 7809 search = opts.search, // none, applied, removed 7810 order = opts.order, // applied, current, index (original - compatibility with 1.9) 7811 page = opts.page; // all, current 7812 7813 if ( _fnDataSource( settings ) == 'ssp' ) { 7814 // In server-side processing mode, most options are irrelevant since 7815 // rows not shown don't exist and the index order is the applied order 7816 // Removed is a special case - for consistency just return an empty 7817 // array 7818 return search === 'removed' ? 7819 [] : 7820 _range( 0, displayMaster.length ); 7821 } 7822 else if ( page == 'current' ) { 7823 // Current page implies that order=current and fitler=applied, since it is 7824 // fairly senseless otherwise, regardless of what order and search actually 7825 // are 7826 for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) { 7827 a.push( displayFiltered[i] ); 7828 } 7829 } 7830 else if ( order == 'current' || order == 'applied' ) { 7831 if ( search == 'none') { 7832 a = displayMaster.slice(); 7833 } 7834 else if ( search == 'applied' ) { 7835 a = displayFiltered.slice(); 7836 } 7837 else if ( search == 'removed' ) { 7838 // O(n+m) solution by creating a hash map 7839 var displayFilteredMap = {}; 7840 7841 for ( var i=0, ien=displayFiltered.length ; i<ien ; i++ ) { 7842 displayFilteredMap[displayFiltered[i]] = null; 7843 } 7844 7845 a = $.map( displayMaster, function (el) { 7846 return ! displayFilteredMap.hasOwnProperty(el) ? 7847 el : 7848 null; 7849 } ); 7850 } 7851 } 7852 else if ( order == 'index' || order == 'original' ) { 7853 for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 7854 if ( search == 'none' ) { 7855 a.push( i ); 7856 } 7857 else { // applied | removed 7858 tmp = $.inArray( i, displayFiltered ); 7859 7860 if ((tmp === -1 && search == 'removed') || 7861 (tmp >= 0 && search == 'applied') ) 7862 { 7863 a.push( i ); 7864 } 7865 } 7866 } 7867 } 7868 7869 return a; 7870 }; 7871 7872 7873 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 7874 * Rows 7875 * 7876 * {} - no selector - use all available rows 7877 * {integer} - row aoData index 7878 * {node} - TR node 7879 * {string} - jQuery selector to apply to the TR elements 7880 * {array} - jQuery array of nodes, or simply an array of TR nodes 7881 * 7882 */ 7883 var __row_selector = function ( settings, selector, opts ) 7884 { 7885 var rows; 7886 var run = function ( sel ) { 7887 var selInt = _intVal( sel ); 7888 var i, ien; 7889 var aoData = settings.aoData; 7890 7891 // Short cut - selector is a number and no options provided (default is 7892 // all records, so no need to check if the index is in there, since it 7893 // must be - dev error if the index doesn't exist). 7894 if ( selInt !== null && ! opts ) { 7895 return [ selInt ]; 7896 } 7897 7898 if ( ! rows ) { 7899 rows = _selector_row_indexes( settings, opts ); 7900 } 7901 7902 if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) { 7903 // Selector - integer 7904 return [ selInt ]; 7905 } 7906 else if ( sel === null || sel === undefined || sel === '' ) { 7907 // Selector - none 7908 return rows; 7909 } 7910 7911 // Selector - function 7912 if ( typeof sel === 'function' ) { 7913 return $.map( rows, function (idx) { 7914 var row = aoData[ idx ]; 7915 return sel( idx, row._aData, row.nTr ) ? idx : null; 7916 } ); 7917 } 7918 7919 // Selector - node 7920 if ( sel.nodeName ) { 7921 var rowIdx = sel._DT_RowIndex; // Property added by DT for fast lookup 7922 var cellIdx = sel._DT_CellIndex; 7923 7924 if ( rowIdx !== undefined ) { 7925 // Make sure that the row is actually still present in the table 7926 return aoData[ rowIdx ] && aoData[ rowIdx ].nTr === sel ? 7927 [ rowIdx ] : 7928 []; 7929 } 7930 else if ( cellIdx ) { 7931 return aoData[ cellIdx.row ] && aoData[ cellIdx.row ].nTr === sel ? 7932 [ cellIdx.row ] : 7933 []; 7934 } 7935 else { 7936 var host = $(sel).closest('*[data-dt-row]'); 7937 return host.length ? 7938 [ host.data('dt-row') ] : 7939 []; 7940 } 7941 } 7942 7943 // ID selector. Want to always be able to select rows by id, regardless 7944 // of if the tr element has been created or not, so can't rely upon 7945 // jQuery here - hence a custom implementation. This does not match 7946 // Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything, 7947 // but to select it using a CSS selector engine (like Sizzle or 7948 // querySelect) it would need to need to be escaped for some characters. 7949 // DataTables simplifies this for row selectors since you can select 7950 // only a row. A # indicates an id any anything that follows is the id - 7951 // unescaped. 7952 if ( typeof sel === 'string' && sel.charAt(0) === '#' ) { 7953 // get row index from id 7954 var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ]; 7955 if ( rowObj !== undefined ) { 7956 return [ rowObj.idx ]; 7957 } 7958 7959 // need to fall through to jQuery in case there is DOM id that 7960 // matches 7961 } 7962 7963 // Get nodes in the order from the `rows` array with null values removed 7964 var nodes = _removeEmpty( 7965 _pluck_order( settings.aoData, rows, 'nTr' ) 7966 ); 7967 7968 // Selector - jQuery selector string, array of nodes or jQuery object/ 7969 // As jQuery's .filter() allows jQuery objects to be passed in filter, 7970 // it also allows arrays, so this will cope with all three options 7971 return $(nodes) 7972 .filter( sel ) 7973 .map( function () { 7974 return this._DT_RowIndex; 7975 } ) 7976 .toArray(); 7977 }; 7978 7979 return _selector_run( 'row', selector, run, settings, opts ); 7980 }; 7981 7982 7983 _api_register( 'rows()', function ( selector, opts ) { 7984 // argument shifting 7985 if ( selector === undefined ) { 7986 selector = ''; 7987 } 7988 else if ( $.isPlainObject( selector ) ) { 7989 opts = selector; 7990 selector = ''; 7991 } 7992 7993 opts = _selector_opts( opts ); 7994 7995 var inst = this.iterator( 'table', function ( settings ) { 7996 return __row_selector( settings, selector, opts ); 7997 }, 1 ); 7998 7999 // Want argument shifting here and in __row_selector? 8000 inst.selector.rows = selector; 8001 inst.selector.opts = opts; 8002 8003 return inst; 8004 } ); 8005 8006 _api_register( 'rows().nodes()', function () { 8007 return this.iterator( 'row', function ( settings, row ) { 8008 return settings.aoData[ row ].nTr || undefined; 8009 }, 1 ); 8010 } ); 8011 8012 _api_register( 'rows().data()', function () { 8013 return this.iterator( true, 'rows', function ( settings, rows ) { 8014 return _pluck_order( settings.aoData, rows, '_aData' ); 8015 }, 1 ); 8016 } ); 8017 8018 _api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) { 8019 return this.iterator( 'row', function ( settings, row ) { 8020 var r = settings.aoData[ row ]; 8021 return type === 'search' ? r._aFilterData : r._aSortData; 8022 }, 1 ); 8023 } ); 8024 8025 _api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) { 8026 return this.iterator( 'row', function ( settings, row ) { 8027 _fnInvalidate( settings, row, src ); 8028 } ); 8029 } ); 8030 8031 _api_registerPlural( 'rows().indexes()', 'row().index()', function () { 8032 return this.iterator( 'row', function ( settings, row ) { 8033 return row; 8034 }, 1 ); 8035 } ); 8036 8037 _api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) { 8038 var a = []; 8039 var context = this.context; 8040 8041 // `iterator` will drop undefined values, but in this case we want them 8042 for ( var i=0, ien=context.length ; i<ien ; i++ ) { 8043 for ( var j=0, jen=this[i].length ; j<jen ; j++ ) { 8044 var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData ); 8045 a.push( (hash === true ? '#' : '' )+ id ); 8046 } 8047 } 8048 8049 return new _Api( context, a ); 8050 } ); 8051 8052 _api_registerPlural( 'rows().remove()', 'row().remove()', function () { 8053 var that = this; 8054 8055 this.iterator( 'row', function ( settings, row, thatIdx ) { 8056 var data = settings.aoData; 8057 var rowData = data[ row ]; 8058 var i, ien, j, jen; 8059 var loopRow, loopCells; 8060 8061 data.splice( row, 1 ); 8062 8063 // Update the cached indexes 8064 for ( i=0, ien=data.length ; i<ien ; i++ ) { 8065 loopRow = data[i]; 8066 loopCells = loopRow.anCells; 8067 8068 // Rows 8069 if ( loopRow.nTr !== null ) { 8070 loopRow.nTr._DT_RowIndex = i; 8071 } 8072 8073 // Cells 8074 if ( loopCells !== null ) { 8075 for ( j=0, jen=loopCells.length ; j<jen ; j++ ) { 8076 loopCells[j]._DT_CellIndex.row = i; 8077 } 8078 } 8079 } 8080 8081 // Delete from the display arrays 8082 _fnDeleteIndex( settings.aiDisplayMaster, row ); 8083 _fnDeleteIndex( settings.aiDisplay, row ); 8084 _fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes 8085 8086 // For server-side processing tables - subtract the deleted row from the count 8087 if ( settings._iRecordsDisplay > 0 ) { 8088 settings._iRecordsDisplay--; 8089 } 8090 8091 // Check for an 'overflow' they case for displaying the table 8092 _fnLengthOverflow( settings ); 8093 8094 // Remove the row's ID reference if there is one 8095 var id = settings.rowIdFn( rowData._aData ); 8096 if ( id !== undefined ) { 8097 delete settings.aIds[ id ]; 8098 } 8099 } ); 8100 8101 this.iterator( 'table', function ( settings ) { 8102 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 8103 settings.aoData[i].idx = i; 8104 } 8105 } ); 8106 8107 return this; 8108 } ); 8109 8110 8111 _api_register( 'rows.add()', function ( rows ) { 8112 var newRows = this.iterator( 'table', function ( settings ) { 8113 var row, i, ien; 8114 var out = []; 8115 8116 for ( i=0, ien=rows.length ; i<ien ; i++ ) { 8117 row = rows[i]; 8118 8119 if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) { 8120 out.push( _fnAddTr( settings, row )[0] ); 8121 } 8122 else { 8123 out.push( _fnAddData( settings, row ) ); 8124 } 8125 } 8126 8127 return out; 8128 }, 1 ); 8129 8130 // Return an Api.rows() extended instance, so rows().nodes() etc can be used 8131 var modRows = this.rows( -1 ); 8132 modRows.pop(); 8133 $.merge( modRows, newRows ); 8134 8135 return modRows; 8136 } ); 8137 8138 8139 8140 8141 8142 /** 8143 * 8144 */ 8145 _api_register( 'row()', function ( selector, opts ) { 8146 return _selector_first( this.rows( selector, opts ) ); 8147 } ); 8148 8149 8150 _api_register( 'row().data()', function ( data ) { 8151 var ctx = this.context; 8152 8153 if ( data === undefined ) { 8154 // Get 8155 return ctx.length && this.length ? 8156 ctx[0].aoData[ this[0] ]._aData : 8157 undefined; 8158 } 8159 8160 // Set 8161 var row = ctx[0].aoData[ this[0] ]; 8162 row._aData = data; 8163 8164 // If the DOM has an id, and the data source is an array 8165 if ( $.isArray( data ) && row.nTr.id ) { 8166 _fnSetObjectDataFn( ctx[0].rowId )( data, row.nTr.id ); 8167 } 8168 8169 // Automatically invalidate 8170 _fnInvalidate( ctx[0], this[0], 'data' ); 8171 8172 return this; 8173 } ); 8174 8175 8176 _api_register( 'row().node()', function () { 8177 var ctx = this.context; 8178 8179 return ctx.length && this.length ? 8180 ctx[0].aoData[ this[0] ].nTr || null : 8181 null; 8182 } ); 8183 8184 8185 _api_register( 'row.add()', function ( row ) { 8186 // Allow a jQuery object to be passed in - only a single row is added from 8187 // it though - the first element in the set 8188 if ( row instanceof $ && row.length ) { 8189 row = row[0]; 8190 } 8191 8192 var rows = this.iterator( 'table', function ( settings ) { 8193 if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) { 8194 return _fnAddTr( settings, row )[0]; 8195 } 8196 return _fnAddData( settings, row ); 8197 } ); 8198 8199 // Return an Api.rows() extended instance, with the newly added row selected 8200 return this.row( rows[0] ); 8201 } ); 8202 8203 8204 8205 var __details_add = function ( ctx, row, data, klass ) 8206 { 8207 // Convert to array of TR elements 8208 var rows = []; 8209 var addRow = function ( r, k ) { 8210 // Recursion to allow for arrays of jQuery objects 8211 if ( $.isArray( r ) || r instanceof $ ) { 8212 for ( var i=0, ien=r.length ; i<ien ; i++ ) { 8213 addRow( r[i], k ); 8214 } 8215 return; 8216 } 8217 8218 // If we get a TR element, then just add it directly - up to the dev 8219 // to add the correct number of columns etc 8220 if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) { 8221 rows.push( r ); 8222 } 8223 else { 8224 // Otherwise create a row with a wrapper 8225 var created = $('<tr><td/></tr>').addClass( k ); 8226 $('td', created) 8227 .addClass( k ) 8228 .html( r ) 8229 [0].colSpan = _fnVisbleColumns( ctx ); 8230 8231 rows.push( created[0] ); 8232 } 8233 }; 8234 8235 addRow( data, klass ); 8236 8237 if ( row._details ) { 8238 row._details.detach(); 8239 } 8240 8241 row._details = $(rows); 8242 8243 // If the children were already shown, that state should be retained 8244 if ( row._detailsShow ) { 8245 row._details.insertAfter( row.nTr ); 8246 } 8247 }; 8248 8249 8250 var __details_remove = function ( api, idx ) 8251 { 8252 var ctx = api.context; 8253 8254 if ( ctx.length ) { 8255 var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ]; 8256 8257 if ( row && row._details ) { 8258 row._details.remove(); 8259 8260 row._detailsShow = undefined; 8261 row._details = undefined; 8262 } 8263 } 8264 }; 8265 8266 8267 var __details_display = function ( api, show ) { 8268 var ctx = api.context; 8269 8270 if ( ctx.length && api.length ) { 8271 var row = ctx[0].aoData[ api[0] ]; 8272 8273 if ( row._details ) { 8274 row._detailsShow = show; 8275 8276 if ( show ) { 8277 row._details.insertAfter( row.nTr ); 8278 } 8279 else { 8280 row._details.detach(); 8281 } 8282 8283 __details_events( ctx[0] ); 8284 } 8285 } 8286 }; 8287 8288 8289 var __details_events = function ( settings ) 8290 { 8291 var api = new _Api( settings ); 8292 var namespace = '.dt.DT_details'; 8293 var drawEvent = 'draw'+namespace; 8294 var colvisEvent = 'column-visibility'+namespace; 8295 var destroyEvent = 'destroy'+namespace; 8296 var data = settings.aoData; 8297 8298 api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent ); 8299 8300 if ( _pluck( data, '_details' ).length > 0 ) { 8301 // On each draw, insert the required elements into the document 8302 api.on( drawEvent, function ( e, ctx ) { 8303 if ( settings !== ctx ) { 8304 return; 8305 } 8306 8307 api.rows( {page:'current'} ).eq(0).each( function (idx) { 8308 // Internal data grab 8309 var row = data[ idx ]; 8310 8311 if ( row._detailsShow ) { 8312 row._details.insertAfter( row.nTr ); 8313 } 8314 } ); 8315 } ); 8316 8317 // Column visibility change - update the colspan 8318 api.on( colvisEvent, function ( e, ctx, idx, vis ) { 8319 if ( settings !== ctx ) { 8320 return; 8321 } 8322 8323 // Update the colspan for the details rows (note, only if it already has 8324 // a colspan) 8325 var row, visible = _fnVisbleColumns( ctx ); 8326 8327 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 8328 row = data[i]; 8329 8330 if ( row._details ) { 8331 row._details.children('td[colspan]').attr('colspan', visible ); 8332 } 8333 } 8334 } ); 8335 8336 // Table destroyed - nuke any child rows 8337 api.on( destroyEvent, function ( e, ctx ) { 8338 if ( settings !== ctx ) { 8339 return; 8340 } 8341 8342 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 8343 if ( data[i]._details ) { 8344 __details_remove( api, i ); 8345 } 8346 } 8347 } ); 8348 } 8349 }; 8350 8351 // Strings for the method names to help minification 8352 var _emp = ''; 8353 var _child_obj = _emp+'row().child'; 8354 var _child_mth = _child_obj+'()'; 8355 8356 // data can be: 8357 // tr 8358 // string 8359 // jQuery or array of any of the above 8360 _api_register( _child_mth, function ( data, klass ) { 8361 var ctx = this.context; 8362 8363 if ( data === undefined ) { 8364 // get 8365 return ctx.length && this.length ? 8366 ctx[0].aoData[ this[0] ]._details : 8367 undefined; 8368 } 8369 else if ( data === true ) { 8370 // show 8371 this.child.show(); 8372 } 8373 else if ( data === false ) { 8374 // remove 8375 __details_remove( this ); 8376 } 8377 else if ( ctx.length && this.length ) { 8378 // set 8379 __details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass ); 8380 } 8381 8382 return this; 8383 } ); 8384 8385 8386 _api_register( [ 8387 _child_obj+'.show()', 8388 _child_mth+'.show()' // only when `child()` was called with parameters (without 8389 ], function ( show ) { // it returns an object and this method is not executed) 8390 __details_display( this, true ); 8391 return this; 8392 } ); 8393 8394 8395 _api_register( [ 8396 _child_obj+'.hide()', 8397 _child_mth+'.hide()' // only when `child()` was called with parameters (without 8398 ], function () { // it returns an object and this method is not executed) 8399 __details_display( this, false ); 8400 return this; 8401 } ); 8402 8403 8404 _api_register( [ 8405 _child_obj+'.remove()', 8406 _child_mth+'.remove()' // only when `child()` was called with parameters (without 8407 ], function () { // it returns an object and this method is not executed) 8408 __details_remove( this ); 8409 return this; 8410 } ); 8411 8412 8413 _api_register( _child_obj+'.isShown()', function () { 8414 var ctx = this.context; 8415 8416 if ( ctx.length && this.length ) { 8417 // _detailsShown as false or undefined will fall through to return false 8418 return ctx[0].aoData[ this[0] ]._detailsShow || false; 8419 } 8420 return false; 8421 } ); 8422 8423 8424 8425 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 8426 * Columns 8427 * 8428 * {integer} - column index (>=0 count from left, <0 count from right) 8429 * "{integer}:visIdx" - visible column index (i.e. translate to column index) (>=0 count from left, <0 count from right) 8430 * "{integer}:visible" - alias for {integer}:visIdx (>=0 count from left, <0 count from right) 8431 * "{string}:name" - column name 8432 * "{string}" - jQuery selector on column header nodes 8433 * 8434 */ 8435 8436 // can be an array of these items, comma separated list, or an array of comma 8437 // separated lists 8438 8439 var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/; 8440 8441 8442 // r1 and r2 are redundant - but it means that the parameters match for the 8443 // iterator callback in columns().data() 8444 var __columnData = function ( settings, column, r1, r2, rows ) { 8445 var a = []; 8446 for ( var row=0, ien=rows.length ; row<ien ; row++ ) { 8447 a.push( _fnGetCellData( settings, rows[row], column ) ); 8448 } 8449 return a; 8450 }; 8451 8452 8453 var __column_selector = function ( settings, selector, opts ) 8454 { 8455 var 8456 columns = settings.aoColumns, 8457 names = _pluck( columns, 'sName' ), 8458 nodes = _pluck( columns, 'nTh' ); 8459 8460 var run = function ( s ) { 8461 var selInt = _intVal( s ); 8462 8463 // Selector - all 8464 if ( s === '' ) { 8465 return _range( columns.length ); 8466 } 8467 8468 // Selector - index 8469 if ( selInt !== null ) { 8470 return [ selInt >= 0 ? 8471 selInt : // Count from left 8472 columns.length + selInt // Count from right (+ because its a negative value) 8473 ]; 8474 } 8475 8476 // Selector = function 8477 if ( typeof s === 'function' ) { 8478 var rows = _selector_row_indexes( settings, opts ); 8479 8480 return $.map( columns, function (col, idx) { 8481 return s( 8482 idx, 8483 __columnData( settings, idx, 0, 0, rows ), 8484 nodes[ idx ] 8485 ) ? idx : null; 8486 } ); 8487 } 8488 8489 // jQuery or string selector 8490 var match = typeof s === 'string' ? 8491 s.match( __re_column_selector ) : 8492 ''; 8493 8494 if ( match ) { 8495 switch( match[2] ) { 8496 case 'visIdx': 8497 case 'visible': 8498 var idx = parseInt( match[1], 10 ); 8499 // Visible index given, convert to column index 8500 if ( idx < 0 ) { 8501 // Counting from the right 8502 var visColumns = $.map( columns, function (col,i) { 8503 return col.bVisible ? i : null; 8504 } ); 8505 return [ visColumns[ visColumns.length + idx ] ]; 8506 } 8507 // Counting from the left 8508 return [ _fnVisibleToColumnIndex( settings, idx ) ]; 8509 8510 case 'name': 8511 // match by name. `names` is column index complete and in order 8512 return $.map( names, function (name, i) { 8513 return name === match[1] ? i : null; 8514 } ); 8515 8516 default: 8517 return []; 8518 } 8519 } 8520 8521 // Cell in the table body 8522 if ( s.nodeName && s._DT_CellIndex ) { 8523 return [ s._DT_CellIndex.column ]; 8524 } 8525 8526 // jQuery selector on the TH elements for the columns 8527 var jqResult = $( nodes ) 8528 .filter( s ) 8529 .map( function () { 8530 return $.inArray( this, nodes ); // `nodes` is column index complete and in order 8531 } ) 8532 .toArray(); 8533 8534 if ( jqResult.length || ! s.nodeName ) { 8535 return jqResult; 8536 } 8537 8538 // Otherwise a node which might have a `dt-column` data attribute, or be 8539 // a child or such an element 8540 var host = $(s).closest('*[data-dt-column]'); 8541 return host.length ? 8542 [ host.data('dt-column') ] : 8543 []; 8544 }; 8545 8546 return _selector_run( 'column', selector, run, settings, opts ); 8547 }; 8548 8549 8550 var __setColumnVis = function ( settings, column, vis ) { 8551 var 8552 cols = settings.aoColumns, 8553 col = cols[ column ], 8554 data = settings.aoData, 8555 row, cells, i, ien, tr; 8556 8557 // Get 8558 if ( vis === undefined ) { 8559 return col.bVisible; 8560 } 8561 8562 // Set 8563 // No change 8564 if ( col.bVisible === vis ) { 8565 return; 8566 } 8567 8568 if ( vis ) { 8569 // Insert column 8570 // Need to decide if we should use appendChild or insertBefore 8571 var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 ); 8572 8573 for ( i=0, ien=data.length ; i<ien ; i++ ) { 8574 tr = data[i].nTr; 8575 cells = data[i].anCells; 8576 8577 if ( tr ) { 8578 // insertBefore can act like appendChild if 2nd arg is null 8579 tr.insertBefore( cells[ column ], cells[ insertBefore ] || null ); 8580 } 8581 } 8582 } 8583 else { 8584 // Remove column 8585 $( _pluck( settings.aoData, 'anCells', column ) ).detach(); 8586 } 8587 8588 // Common actions 8589 col.bVisible = vis; 8590 _fnDrawHead( settings, settings.aoHeader ); 8591 _fnDrawHead( settings, settings.aoFooter ); 8592 8593 // Update colspan for no records display. Child rows and extensions will use their own 8594 // listeners to do this - only need to update the empty table item here 8595 if ( ! settings.aiDisplay.length ) { 8596 $(settings.nTBody).find('td[colspan]').attr('colspan', _fnVisbleColumns(settings)); 8597 } 8598 8599 _fnSaveState( settings ); 8600 }; 8601 8602 8603 _api_register( 'columns()', function ( selector, opts ) { 8604 // argument shifting 8605 if ( selector === undefined ) { 8606 selector = ''; 8607 } 8608 else if ( $.isPlainObject( selector ) ) { 8609 opts = selector; 8610 selector = ''; 8611 } 8612 8613 opts = _selector_opts( opts ); 8614 8615 var inst = this.iterator( 'table', function ( settings ) { 8616 return __column_selector( settings, selector, opts ); 8617 }, 1 ); 8618 8619 // Want argument shifting here and in _row_selector? 8620 inst.selector.cols = selector; 8621 inst.selector.opts = opts; 8622 8623 return inst; 8624 } ); 8625 8626 _api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) { 8627 return this.iterator( 'column', function ( settings, column ) { 8628 return settings.aoColumns[column].nTh; 8629 }, 1 ); 8630 } ); 8631 8632 _api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) { 8633 return this.iterator( 'column', function ( settings, column ) { 8634 return settings.aoColumns[column].nTf; 8635 }, 1 ); 8636 } ); 8637 8638 _api_registerPlural( 'columns().data()', 'column().data()', function () { 8639 return this.iterator( 'column-rows', __columnData, 1 ); 8640 } ); 8641 8642 _api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () { 8643 return this.iterator( 'column', function ( settings, column ) { 8644 return settings.aoColumns[column].mData; 8645 }, 1 ); 8646 } ); 8647 8648 _api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) { 8649 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) { 8650 return _pluck_order( settings.aoData, rows, 8651 type === 'search' ? '_aFilterData' : '_aSortData', column 8652 ); 8653 }, 1 ); 8654 } ); 8655 8656 _api_registerPlural( 'columns().nodes()', 'column().nodes()', function () { 8657 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) { 8658 return _pluck_order( settings.aoData, rows, 'anCells', column ) ; 8659 }, 1 ); 8660 } ); 8661 8662 _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) { 8663 var ret = this.iterator( 'column', function ( settings, column ) { 8664 if ( vis === undefined ) { 8665 return settings.aoColumns[ column ].bVisible; 8666 } // else 8667 __setColumnVis( settings, column, vis ); 8668 } ); 8669 8670 // Group the column visibility changes 8671 if ( vis !== undefined ) { 8672 // Second loop once the first is done for events 8673 this.iterator( 'column', function ( settings, column ) { 8674 _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] ); 8675 } ); 8676 8677 if ( calc === undefined || calc ) { 8678 this.columns.adjust(); 8679 } 8680 } 8681 8682 return ret; 8683 } ); 8684 8685 _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) { 8686 return this.iterator( 'column', function ( settings, column ) { 8687 return type === 'visible' ? 8688 _fnColumnIndexToVisible( settings, column ) : 8689 column; 8690 }, 1 ); 8691 } ); 8692 8693 _api_register( 'columns.adjust()', function () { 8694 return this.iterator( 'table', function ( settings ) { 8695 _fnAdjustColumnSizing( settings ); 8696 }, 1 ); 8697 } ); 8698 8699 _api_register( 'column.index()', function ( type, idx ) { 8700 if ( this.context.length !== 0 ) { 8701 var ctx = this.context[0]; 8702 8703 if ( type === 'fromVisible' || type === 'toData' ) { 8704 return _fnVisibleToColumnIndex( ctx, idx ); 8705 } 8706 else if ( type === 'fromData' || type === 'toVisible' ) { 8707 return _fnColumnIndexToVisible( ctx, idx ); 8708 } 8709 } 8710 } ); 8711 8712 _api_register( 'column()', function ( selector, opts ) { 8713 return _selector_first( this.columns( selector, opts ) ); 8714 } ); 8715 8716 8717 8718 var __cell_selector = function ( settings, selector, opts ) 8719 { 8720 var data = settings.aoData; 8721 var rows = _selector_row_indexes( settings, opts ); 8722 var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) ); 8723 var allCells = $( [].concat.apply([], cells) ); 8724 var row; 8725 var columns = settings.aoColumns.length; 8726 var a, i, ien, j, o, host; 8727 8728 var run = function ( s ) { 8729 var fnSelector = typeof s === 'function'; 8730 8731 if ( s === null || s === undefined || fnSelector ) { 8732 // All cells and function selectors 8733 a = []; 8734 8735 for ( i=0, ien=rows.length ; i<ien ; i++ ) { 8736 row = rows[i]; 8737 8738 for ( j=0 ; j<columns ; j++ ) { 8739 o = { 8740 row: row, 8741 column: j 8742 }; 8743 8744 if ( fnSelector ) { 8745 // Selector - function 8746 host = data[ row ]; 8747 8748 if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) { 8749 a.push( o ); 8750 } 8751 } 8752 else { 8753 // Selector - all 8754 a.push( o ); 8755 } 8756 } 8757 } 8758 8759 return a; 8760 } 8761 8762 // Selector - index 8763 if ( $.isPlainObject( s ) ) { 8764 // Valid cell index and its in the array of selectable rows 8765 return s.column !== undefined && s.row !== undefined && $.inArray( s.row, rows ) !== -1 ? 8766 [s] : 8767 []; 8768 } 8769 8770 // Selector - jQuery filtered cells 8771 var jqResult = allCells 8772 .filter( s ) 8773 .map( function (i, el) { 8774 return { // use a new object, in case someone changes the values 8775 row: el._DT_CellIndex.row, 8776 column: el._DT_CellIndex.column 8777 }; 8778 } ) 8779 .toArray(); 8780 8781 if ( jqResult.length || ! s.nodeName ) { 8782 return jqResult; 8783 } 8784 8785 // Otherwise the selector is a node, and there is one last option - the 8786 // element might be a child of an element which has dt-row and dt-column 8787 // data attributes 8788 host = $(s).closest('*[data-dt-row]'); 8789 return host.length ? 8790 [ { 8791 row: host.data('dt-row'), 8792 column: host.data('dt-column') 8793 } ] : 8794 []; 8795 }; 8796 8797 return _selector_run( 'cell', selector, run, settings, opts ); 8798 }; 8799 8800 8801 8802 8803 _api_register( 'cells()', function ( rowSelector, columnSelector, opts ) { 8804 // Argument shifting 8805 if ( $.isPlainObject( rowSelector ) ) { 8806 // Indexes 8807 if ( rowSelector.row === undefined ) { 8808 // Selector options in first parameter 8809 opts = rowSelector; 8810 rowSelector = null; 8811 } 8812 else { 8813 // Cell index objects in first parameter 8814 opts = columnSelector; 8815 columnSelector = null; 8816 } 8817 } 8818 if ( $.isPlainObject( columnSelector ) ) { 8819 opts = columnSelector; 8820 columnSelector = null; 8821 } 8822 8823 // Cell selector 8824 if ( columnSelector === null || columnSelector === undefined ) { 8825 return this.iterator( 'table', function ( settings ) { 8826 return __cell_selector( settings, rowSelector, _selector_opts( opts ) ); 8827 } ); 8828 } 8829 8830 // Row + column selector 8831 var columns = this.columns( columnSelector ); 8832 var rows = this.rows( rowSelector ); 8833 var a, i, ien, j, jen; 8834 8835 this.iterator( 'table', function ( settings, idx ) { 8836 a = []; 8837 8838 for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) { 8839 for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) { 8840 a.push( { 8841 row: rows[idx][i], 8842 column: columns[idx][j] 8843 } ); 8844 } 8845 } 8846 }, 1 ); 8847 8848 // Now pass through the cell selector for options 8849 var cells = this.cells( a, opts ); 8850 8851 $.extend( cells.selector, { 8852 cols: columnSelector, 8853 rows: rowSelector, 8854 opts: opts 8855 } ); 8856 8857 return cells; 8858 } ); 8859 8860 8861 _api_registerPlural( 'cells().nodes()', 'cell().node()', function () { 8862 return this.iterator( 'cell', function ( settings, row, column ) { 8863 var data = settings.aoData[ row ]; 8864 8865 return data && data.anCells ? 8866 data.anCells[ column ] : 8867 undefined; 8868 }, 1 ); 8869 } ); 8870 8871 8872 _api_register( 'cells().data()', function () { 8873 return this.iterator( 'cell', function ( settings, row, column ) { 8874 return _fnGetCellData( settings, row, column ); 8875 }, 1 ); 8876 } ); 8877 8878 8879 _api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) { 8880 type = type === 'search' ? '_aFilterData' : '_aSortData'; 8881 8882 return this.iterator( 'cell', function ( settings, row, column ) { 8883 return settings.aoData[ row ][ type ][ column ]; 8884 }, 1 ); 8885 } ); 8886 8887 8888 _api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) { 8889 return this.iterator( 'cell', function ( settings, row, column ) { 8890 return _fnGetCellData( settings, row, column, type ); 8891 }, 1 ); 8892 } ); 8893 8894 8895 _api_registerPlural( 'cells().indexes()', 'cell().index()', function () { 8896 return this.iterator( 'cell', function ( settings, row, column ) { 8897 return { 8898 row: row, 8899 column: column, 8900 columnVisible: _fnColumnIndexToVisible( settings, column ) 8901 }; 8902 }, 1 ); 8903 } ); 8904 8905 8906 _api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) { 8907 return this.iterator( 'cell', function ( settings, row, column ) { 8908 _fnInvalidate( settings, row, src, column ); 8909 } ); 8910 } ); 8911 8912 8913 8914 _api_register( 'cell()', function ( rowSelector, columnSelector, opts ) { 8915 return _selector_first( this.cells( rowSelector, columnSelector, opts ) ); 8916 } ); 8917 8918 8919 _api_register( 'cell().data()', function ( data ) { 8920 var ctx = this.context; 8921 var cell = this[0]; 8922 8923 if ( data === undefined ) { 8924 // Get 8925 return ctx.length && cell.length ? 8926 _fnGetCellData( ctx[0], cell[0].row, cell[0].column ) : 8927 undefined; 8928 } 8929 8930 // Set 8931 _fnSetCellData( ctx[0], cell[0].row, cell[0].column, data ); 8932 _fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column ); 8933 8934 return this; 8935 } ); 8936 8937 8938 8939 /** 8940 * Get current ordering (sorting) that has been applied to the table. 8941 * 8942 * @returns {array} 2D array containing the sorting information for the first 8943 * table in the current context. Each element in the parent array represents 8944 * a column being sorted upon (i.e. multi-sorting with two columns would have 8945 * 2 inner arrays). The inner arrays may have 2 or 3 elements. The first is 8946 * the column index that the sorting condition applies to, the second is the 8947 * direction of the sort (`desc` or `asc`) and, optionally, the third is the 8948 * index of the sorting order from the `column.sorting` initialisation array. 8949 *//** 8950 * Set the ordering for the table. 8951 * 8952 * @param {integer} order Column index to sort upon. 8953 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`) 8954 * @returns {DataTables.Api} this 8955 *//** 8956 * Set the ordering for the table. 8957 * 8958 * @param {array} order 1D array of sorting information to be applied. 8959 * @param {array} [...] Optional additional sorting conditions 8960 * @returns {DataTables.Api} this 8961 *//** 8962 * Set the ordering for the table. 8963 * 8964 * @param {array} order 2D array of sorting information to be applied. 8965 * @returns {DataTables.Api} this 8966 */ 8967 _api_register( 'order()', function ( order, dir ) { 8968 var ctx = this.context; 8969 8970 if ( order === undefined ) { 8971 // get 8972 return ctx.length !== 0 ? 8973 ctx[0].aaSorting : 8974 undefined; 8975 } 8976 8977 // set 8978 if ( typeof order === 'number' ) { 8979 // Simple column / direction passed in 8980 order = [ [ order, dir ] ]; 8981 } 8982 else if ( order.length && ! $.isArray( order[0] ) ) { 8983 // Arguments passed in (list of 1D arrays) 8984 order = Array.prototype.slice.call( arguments ); 8985 } 8986 // otherwise a 2D array was passed in 8987 8988 return this.iterator( 'table', function ( settings ) { 8989 settings.aaSorting = order.slice(); 8990 } ); 8991 } ); 8992 8993 8994 /** 8995 * Attach a sort listener to an element for a given column 8996 * 8997 * @param {node|jQuery|string} node Identifier for the element(s) to attach the 8998 * listener to. This can take the form of a single DOM node, a jQuery 8999 * collection of nodes or a jQuery selector which will identify the node(s). 9000 * @param {integer} column the column that a click on this node will sort on 9001 * @param {function} [callback] callback function when sort is run 9002 * @returns {DataTables.Api} this 9003 */ 9004 _api_register( 'order.listener()', function ( node, column, callback ) { 9005 return this.iterator( 'table', function ( settings ) { 9006 _fnSortAttachListener( settings, node, column, callback ); 9007 } ); 9008 } ); 9009 9010 9011 _api_register( 'order.fixed()', function ( set ) { 9012 if ( ! set ) { 9013 var ctx = this.context; 9014 var fixed = ctx.length ? 9015 ctx[0].aaSortingFixed : 9016 undefined; 9017 9018 return $.isArray( fixed ) ? 9019 { pre: fixed } : 9020 fixed; 9021 } 9022 9023 return this.iterator( 'table', function ( settings ) { 9024 settings.aaSortingFixed = $.extend( true, {}, set ); 9025 } ); 9026 } ); 9027 9028 9029 // Order by the selected column(s) 9030 _api_register( [ 9031 'columns().order()', 9032 'column().order()' 9033 ], function ( dir ) { 9034 var that = this; 9035 9036 return this.iterator( 'table', function ( settings, i ) { 9037 var sort = []; 9038 9039 $.each( that[i], function (j, col) { 9040 sort.push( [ col, dir ] ); 9041 } ); 9042 9043 settings.aaSorting = sort; 9044 } ); 9045 } ); 9046 9047 9048 9049 _api_register( 'search()', function ( input, regex, smart, caseInsen ) { 9050 var ctx = this.context; 9051 9052 if ( input === undefined ) { 9053 // get 9054 return ctx.length !== 0 ? 9055 ctx[0].oPreviousSearch.sSearch : 9056 undefined; 9057 } 9058 9059 // set 9060 return this.iterator( 'table', function ( settings ) { 9061 if ( ! settings.oFeatures.bFilter ) { 9062 return; 9063 } 9064 9065 _fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, { 9066 "sSearch": input+"", 9067 "bRegex": regex === null ? false : regex, 9068 "bSmart": smart === null ? true : smart, 9069 "bCaseInsensitive": caseInsen === null ? true : caseInsen 9070 } ), 1 ); 9071 } ); 9072 } ); 9073 9074 9075 _api_registerPlural( 9076 'columns().search()', 9077 'column().search()', 9078 function ( input, regex, smart, caseInsen ) { 9079 return this.iterator( 'column', function ( settings, column ) { 9080 var preSearch = settings.aoPreSearchCols; 9081 9082 if ( input === undefined ) { 9083 // get 9084 return preSearch[ column ].sSearch; 9085 } 9086 9087 // set 9088 if ( ! settings.oFeatures.bFilter ) { 9089 return; 9090 } 9091 9092 $.extend( preSearch[ column ], { 9093 "sSearch": input+"", 9094 "bRegex": regex === null ? false : regex, 9095 "bSmart": smart === null ? true : smart, 9096 "bCaseInsensitive": caseInsen === null ? true : caseInsen 9097 } ); 9098 9099 _fnFilterComplete( settings, settings.oPreviousSearch, 1 ); 9100 } ); 9101 } 9102 ); 9103 9104 /* 9105 * State API methods 9106 */ 9107 9108 _api_register( 'state()', function () { 9109 return this.context.length ? 9110 this.context[0].oSavedState : 9111 null; 9112 } ); 9113 9114 9115 _api_register( 'state.clear()', function () { 9116 return this.iterator( 'table', function ( settings ) { 9117 // Save an empty object 9118 settings.fnStateSaveCallback.call( settings.oInstance, settings, {} ); 9119 } ); 9120 } ); 9121 9122 9123 _api_register( 'state.loaded()', function () { 9124 return this.context.length ? 9125 this.context[0].oLoadedState : 9126 null; 9127 } ); 9128 9129 9130 _api_register( 'state.save()', function () { 9131 return this.iterator( 'table', function ( settings ) { 9132 _fnSaveState( settings ); 9133 } ); 9134 } ); 9135 9136 9137 9138 /** 9139 * Provide a common method for plug-ins to check the version of DataTables being 9140 * used, in order to ensure compatibility. 9141 * 9142 * @param {string} version Version string to check for, in the format "X.Y.Z". 9143 * Note that the formats "X" and "X.Y" are also acceptable. 9144 * @returns {boolean} true if this version of DataTables is greater or equal to 9145 * the required version, or false if this version of DataTales is not 9146 * suitable 9147 * @static 9148 * @dtopt API-Static 9149 * 9150 * @example 9151 * alert( $.fn.dataTable.versionCheck( '1.9.0' ) ); 9152 */ 9153 DataTable.versionCheck = DataTable.fnVersionCheck = function( version ) 9154 { 9155 var aThis = DataTable.version.split('.'); 9156 var aThat = version.split('.'); 9157 var iThis, iThat; 9158 9159 for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) { 9160 iThis = parseInt( aThis[i], 10 ) || 0; 9161 iThat = parseInt( aThat[i], 10 ) || 0; 9162 9163 // Parts are the same, keep comparing 9164 if (iThis === iThat) { 9165 continue; 9166 } 9167 9168 // Parts are different, return immediately 9169 return iThis > iThat; 9170 } 9171 9172 return true; 9173 }; 9174 9175 9176 /** 9177 * Check if a `<table>` node is a DataTable table already or not. 9178 * 9179 * @param {node|jquery|string} table Table node, jQuery object or jQuery 9180 * selector for the table to test. Note that if more than more than one 9181 * table is passed on, only the first will be checked 9182 * @returns {boolean} true the table given is a DataTable, or false otherwise 9183 * @static 9184 * @dtopt API-Static 9185 * 9186 * @example 9187 * if ( ! $.fn.DataTable.isDataTable( '#example' ) ) { 9188 * $('#example').dataTable(); 9189 * } 9190 */ 9191 DataTable.isDataTable = DataTable.fnIsDataTable = function ( table ) 9192 { 9193 var t = $(table).get(0); 9194 var is = false; 9195 9196 if ( table instanceof DataTable.Api ) { 9197 return true; 9198 } 9199 9200 $.each( DataTable.settings, function (i, o) { 9201 var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null; 9202 var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null; 9203 9204 if ( o.nTable === t || head === t || foot === t ) { 9205 is = true; 9206 } 9207 } ); 9208 9209 return is; 9210 }; 9211 9212 9213 /** 9214 * Get all DataTable tables that have been initialised - optionally you can 9215 * select to get only currently visible tables. 9216 * 9217 * @param {boolean} [visible=false] Flag to indicate if you want all (default) 9218 * or visible tables only. 9219 * @returns {array} Array of `table` nodes (not DataTable instances) which are 9220 * DataTables 9221 * @static 9222 * @dtopt API-Static 9223 * 9224 * @example 9225 * $.each( $.fn.dataTable.tables(true), function () { 9226 * $(table).DataTable().columns.adjust(); 9227 * } ); 9228 */ 9229 DataTable.tables = DataTable.fnTables = function ( visible ) 9230 { 9231 var api = false; 9232 9233 if ( $.isPlainObject( visible ) ) { 9234 api = visible.api; 9235 visible = visible.visible; 9236 } 9237 9238 var a = $.map( DataTable.settings, function (o) { 9239 if ( !visible || (visible && $(o.nTable).is(':visible')) ) { 9240 return o.nTable; 9241 } 9242 } ); 9243 9244 return api ? 9245 new _Api( a ) : 9246 a; 9247 }; 9248 9249 9250 /** 9251 * Convert from camel case parameters to Hungarian notation. This is made public 9252 * for the extensions to provide the same ability as DataTables core to accept 9253 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase 9254 * parameters. 9255 * 9256 * @param {object} src The model object which holds all parameters that can be 9257 * mapped. 9258 * @param {object} user The object to convert from camel case to Hungarian. 9259 * @param {boolean} force When set to `true`, properties which already have a 9260 * Hungarian value in the `user` object will be overwritten. Otherwise they 9261 * won't be. 9262 */ 9263 DataTable.camelToHungarian = _fnCamelToHungarian; 9264 9265 9266 9267 /** 9268 * 9269 */ 9270 _api_register( '$()', function ( selector, opts ) { 9271 var 9272 rows = this.rows( opts ).nodes(), // Get all rows 9273 jqRows = $(rows); 9274 9275 return $( [].concat( 9276 jqRows.filter( selector ).toArray(), 9277 jqRows.find( selector ).toArray() 9278 ) ); 9279 } ); 9280 9281 9282 // jQuery functions to operate on the tables 9283 $.each( [ 'on', 'one', 'off' ], function (i, key) { 9284 _api_register( key+'()', function ( /* event, handler */ ) { 9285 var args = Array.prototype.slice.call(arguments); 9286 9287 // Add the `dt` namespace automatically if it isn't already present 9288 args[0] = $.map( args[0].split( /\s/ ), function ( e ) { 9289 return ! e.match(/\.dt\b/) ? 9290 e+'.dt' : 9291 e; 9292 } ).join( ' ' ); 9293 9294 var inst = $( this.tables().nodes() ); 9295 inst[key].apply( inst, args ); 9296 return this; 9297 } ); 9298 } ); 9299 9300 9301 _api_register( 'clear()', function () { 9302 return this.iterator( 'table', function ( settings ) { 9303 _fnClearTable( settings ); 9304 } ); 9305 } ); 9306 9307 9308 _api_register( 'settings()', function () { 9309 return new _Api( this.context, this.context ); 9310 } ); 9311 9312 9313 _api_register( 'init()', function () { 9314 var ctx = this.context; 9315 return ctx.length ? ctx[0].oInit : null; 9316 } ); 9317 9318 9319 _api_register( 'data()', function () { 9320 return this.iterator( 'table', function ( settings ) { 9321 return _pluck( settings.aoData, '_aData' ); 9322 } ).flatten(); 9323 } ); 9324 9325 9326 _api_register( 'destroy()', function ( remove ) { 9327 remove = remove || false; 9328 9329 return this.iterator( 'table', function ( settings ) { 9330 var orig = settings.nTableWrapper.parentNode; 9331 var classes = settings.oClasses; 9332 var table = settings.nTable; 9333 var tbody = settings.nTBody; 9334 var thead = settings.nTHead; 9335 var tfoot = settings.nTFoot; 9336 var jqTable = $(table); 9337 var jqTbody = $(tbody); 9338 var jqWrapper = $(settings.nTableWrapper); 9339 var rows = $.map( settings.aoData, function (r) { return r.nTr; } ); 9340 var i, ien; 9341 9342 // Flag to note that the table is currently being destroyed - no action 9343 // should be taken 9344 settings.bDestroying = true; 9345 9346 // Fire off the destroy callbacks for plug-ins etc 9347 _fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] ); 9348 9349 // If not being removed from the document, make all columns visible 9350 if ( ! remove ) { 9351 new _Api( settings ).columns().visible( true ); 9352 } 9353 9354 // Blitz all `DT` namespaced events (these are internal events, the 9355 // lowercase, `dt` events are user subscribed and they are responsible 9356 // for removing them 9357 jqWrapper.off('.DT').find(':not(tbody *)').off('.DT'); 9358 $(window).off('.DT-'+settings.sInstance); 9359 9360 // When scrolling we had to break the table up - restore it 9361 if ( table != thead.parentNode ) { 9362 jqTable.children('thead').detach(); 9363 jqTable.append( thead ); 9364 } 9365 9366 if ( tfoot && table != tfoot.parentNode ) { 9367 jqTable.children('tfoot').detach(); 9368 jqTable.append( tfoot ); 9369 } 9370 9371 settings.aaSorting = []; 9372 settings.aaSortingFixed = []; 9373 _fnSortingClasses( settings ); 9374 9375 $( rows ).removeClass( settings.asStripeClasses.join(' ') ); 9376 9377 $('th, td', thead).removeClass( classes.sSortable+' '+ 9378 classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone 9379 ); 9380 9381 // Add the TR elements back into the table in their original order 9382 jqTbody.children().detach(); 9383 jqTbody.append( rows ); 9384 9385 // Remove the DataTables generated nodes, events and classes 9386 var removedMethod = remove ? 'remove' : 'detach'; 9387 jqTable[ removedMethod ](); 9388 jqWrapper[ removedMethod ](); 9389 9390 // If we need to reattach the table to the document 9391 if ( ! remove && orig ) { 9392 // insertBefore acts like appendChild if !arg[1] 9393 orig.insertBefore( table, settings.nTableReinsertBefore ); 9394 9395 // Restore the width of the original table - was read from the style property, 9396 // so we can restore directly to that 9397 jqTable 9398 .css( 'width', settings.sDestroyWidth ) 9399 .removeClass( classes.sTable ); 9400 9401 // If the were originally stripe classes - then we add them back here. 9402 // Note this is not fool proof (for example if not all rows had stripe 9403 // classes - but it's a good effort without getting carried away 9404 ien = settings.asDestroyStripes.length; 9405 9406 if ( ien ) { 9407 jqTbody.children().each( function (i) { 9408 $(this).addClass( settings.asDestroyStripes[i % ien] ); 9409 } ); 9410 } 9411 } 9412 9413 /* Remove the settings object from the settings array */ 9414 var idx = $.inArray( settings, DataTable.settings ); 9415 if ( idx !== -1 ) { 9416 DataTable.settings.splice( idx, 1 ); 9417 } 9418 } ); 9419 } ); 9420 9421 9422 // Add the `every()` method for rows, columns and cells in a compact form 9423 $.each( [ 'column', 'row', 'cell' ], function ( i, type ) { 9424 _api_register( type+'s().every()', function ( fn ) { 9425 var opts = this.selector.opts; 9426 var api = this; 9427 9428 return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) { 9429 // Rows and columns: 9430 // arg1 - index 9431 // arg2 - table counter 9432 // arg3 - loop counter 9433 // arg4 - undefined 9434 // Cells: 9435 // arg1 - row index 9436 // arg2 - column index 9437 // arg3 - table counter 9438 // arg4 - loop counter 9439 fn.call( 9440 api[ type ]( 9441 arg1, 9442 type==='cell' ? arg2 : opts, 9443 type==='cell' ? opts : undefined 9444 ), 9445 arg1, arg2, arg3, arg4 9446 ); 9447 } ); 9448 } ); 9449 } ); 9450 9451 9452 // i18n method for extensions to be able to use the language object from the 9453 // DataTable 9454 _api_register( 'i18n()', function ( token, def, plural ) { 9455 var ctx = this.context[0]; 9456 var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage ); 9457 9458 if ( resolved === undefined ) { 9459 resolved = def; 9460 } 9461 9462 if ( plural !== undefined && $.isPlainObject( resolved ) ) { 9463 resolved = resolved[ plural ] !== undefined ? 9464 resolved[ plural ] : 9465 resolved._; 9466 } 9467 9468 return resolved.replace( '%d', plural ); // nb: plural might be undefined, 9469 } ); 9470 9471 /** 9472 * Version string for plug-ins to check compatibility. Allowed format is 9473 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used 9474 * only for non-release builds. See http://semver.org/ for more information. 9475 * @member 9476 * @type string 9477 * @default Version number 9478 */ 9479 DataTable.version = "1.10.18"; 9480 9481 /** 9482 * Private data store, containing all of the settings objects that are 9483 * created for the tables on a given page. 9484 * 9485 * Note that the `DataTable.settings` object is aliased to 9486 * `jQuery.fn.dataTableExt` through which it may be accessed and 9487 * manipulated, or `jQuery.fn.dataTable.settings`. 9488 * @member 9489 * @type array 9490 * @default [] 9491 * @private 9492 */ 9493 DataTable.settings = []; 9494 9495 /** 9496 * Object models container, for the various models that DataTables has 9497 * available to it. These models define the objects that are used to hold 9498 * the active state and configuration of the table. 9499 * @namespace 9500 */ 9501 DataTable.models = {}; 9502 9503 9504 9505 /** 9506 * Template object for the way in which DataTables holds information about 9507 * search information for the global filter and individual column filters. 9508 * @namespace 9509 */ 9510 DataTable.models.oSearch = { 9511 /** 9512 * Flag to indicate if the filtering should be case insensitive or not 9513 * @type boolean 9514 * @default true 9515 */ 9516 "bCaseInsensitive": true, 9517 9518 /** 9519 * Applied search term 9520 * @type string 9521 * @default <i>Empty string</i> 9522 */ 9523 "sSearch": "", 9524 9525 /** 9526 * Flag to indicate if the search term should be interpreted as a 9527 * regular expression (true) or not (false) and therefore and special 9528 * regex characters escaped. 9529 * @type boolean 9530 * @default false 9531 */ 9532 "bRegex": false, 9533 9534 /** 9535 * Flag to indicate if DataTables is to use its smart filtering or not. 9536 * @type boolean 9537 * @default true 9538 */ 9539 "bSmart": tru
vendor: 11,217 bytes, lines 9539-9897
9539e 9540 }; 9541 9542 9543 9544 9545 /** 9546 * Template object for the way in which DataTables holds information about 9547 * each individual row. This is the object format used for the settings 9548 * aoData array. 9549 * @namespace 9550 */ 9551 DataTable.models.oRow = { 9552 /** 9553 * TR element for the row 9554 * @type node 9555 * @default null 9556 */ 9557 "nTr": null, 9558 9559 /** 9560 * Array of TD elements for each row. This is null until the row has been 9561 * created. 9562 * @type array nodes 9563 * @default [] 9564 */ 9565 "anCells": null, 9566 9567 /** 9568 * Data object from the original data source for the row. This is either 9569 * an array if using the traditional form of DataTables, or an object if 9570 * using mData options. The exact type will depend on the passed in 9571 * data from the data source, or will be an array if using DOM a data 9572 * source. 9573 * @type array|object 9574 * @default [] 9575 */ 9576 "_aData": [], 9577 9578 /** 9579 * Sorting data cache - this array is ostensibly the same length as the 9580 * number of columns (although each index is generated only as it is 9581 * needed), and holds the data that is used for sorting each column in the 9582 * row. We do this cache generation at the start of the sort in order that 9583 * the formatting of the sort data need be done only once for each cell 9584 * per sort. This array should not be read from or written to by anything 9585 * other than the master sorting methods. 9586 * @type array 9587 * @default null 9588 * @private 9589 */ 9590 "_aSortData": null, 9591 9592 /** 9593 * Per cell filtering data cache. As per the sort data cache, used to 9594 * increase the performance of the filtering in DataTables 9595 * @type array 9596 * @default null 9597 * @private 9598 */ 9599 "_aFilterData": null, 9600 9601 /** 9602 * Filtering data cache. This is the same as the cell filtering cache, but 9603 * in this case a string rather than an array. This is easily computed with 9604 * a join on `_aFilterData`, but is provided as a cache so the join isn't 9605 * needed on every search (memory traded for performance) 9606 * @type array 9607 * @default null 9608 * @private 9609 */ 9610 "_sFilterRow": null, 9611 9612 /** 9613 * Cache of the class name that DataTables has applied to the row, so we 9614 * can quickly look at this variable rather than needing to do a DOM check 9615 * on className for the nTr property. 9616 * @type string 9617 * @default <i>Empty string</i> 9618 * @private 9619 */ 9620 "_sRowStripe": "", 9621 9622 /** 9623 * Denote if the original data source was from the DOM, or the data source 9624 * object. This is used for invalidating data, so DataTables can 9625 * automatically read data from the original source, unless uninstructed 9626 * otherwise. 9627 * @type string 9628 * @default null 9629 * @private 9630 */ 9631 "src": null, 9632 9633 /** 9634 * Index in the aoData array. This saves an indexOf lookup when we have the 9635 * object, but want to know the index 9636 * @type integer 9637 * @default -1 9638 * @private 9639 */ 9640 "idx": -1 9641 }; 9642 9643 9644 /** 9645 * Template object for the column information object in DataTables. This object 9646 * is held in the settings aoColumns array and contains all the information that 9647 * DataTables needs about each individual column. 9648 * 9649 * Note that this object is related to {@link DataTable.defaults.column} 9650 * but this one is the internal data store for DataTables's cache of columns. 9651 * It should NOT be manipulated outside of DataTables. Any configuration should 9652 * be done through the initialisation options. 9653 * @namespace 9654 */ 9655 DataTable.models.oColumn = { 9656 /** 9657 * Column index. This could be worked out on-the-fly with $.inArray, but it 9658 * is faster to just hold it as a variable 9659 * @type integer 9660 * @default null 9661 */ 9662 "idx": null, 9663 9664 /** 9665 * A list of the columns that sorting should occur on when this column 9666 * is sorted. That this property is an array allows multi-column sorting 9667 * to be defined for a column (for example first name / last name columns 9668 * would benefit from this). The values are integers pointing to the 9669 * columns to be sorted on (typically it will be a single integer pointing 9670 * at itself, but that doesn't need to be the case). 9671 * @type array 9672 */ 9673 "aDataSort": null, 9674 9675 /** 9676 * Define the sorting directions that are applied to the column, in sequence 9677 * as the column is repeatedly sorted upon - i.e. the first value is used 9678 * as the sorting direction when the column if first sorted (clicked on). 9679 * Sort it again (click again) and it will move on to the next index. 9680 * Repeat until loop. 9681 * @type array 9682 */ 9683 "asSorting": null, 9684 9685 /** 9686 * Flag to indicate if the column is searchable, and thus should be included 9687 * in the filtering or not. 9688 * @type boolean 9689 */ 9690 "bSearchable": null, 9691 9692 /** 9693 * Flag to indicate if the column is sortable or not. 9694 * @type boolean 9695 */ 9696 "bSortable": null, 9697 9698 /** 9699 * Flag to indicate if the column is currently visible in the table or not 9700 * @type boolean 9701 */ 9702 "bVisible": null, 9703 9704 /** 9705 * Store for manual type assignment using the `column.type` option. This 9706 * is held in store so we can manipulate the column's `sType` property. 9707 * @type string 9708 * @default null 9709 * @private 9710 */ 9711 "_sManualType": null, 9712 9713 /** 9714 * Flag to indicate if HTML5 data attributes should be used as the data 9715 * source for filtering or sorting. True is either are. 9716 * @type boolean 9717 * @default false 9718 * @private 9719 */ 9720 "_bAttrSrc": false, 9721 9722 /** 9723 * Developer definable function that is called whenever a cell is created (Ajax source, 9724 * etc) or processed for input (DOM source). This can be used as a compliment to mRender 9725 * allowing you to modify the DOM element (add background colour for example) when the 9726 * element is available. 9727 * @type function 9728 * @param {element} nTd The TD node that has been created 9729 * @param {*} sData The Data for the cell 9730 * @param {array|object} oData The data for the whole row 9731 * @param {int} iRow The row index for the aoData data store 9732 * @default null 9733 */ 9734 "fnCreatedCell": null, 9735 9736 /** 9737 * Function to get data from a cell in a column. You should <b>never</b> 9738 * access data directly through _aData internally in DataTables - always use 9739 * the method attached to this property. It allows mData to function as 9740 * required. This function is automatically assigned by the column 9741 * initialisation method 9742 * @type function 9743 * @param {array|object} oData The data array/object for the array 9744 * (i.e. aoData[]._aData) 9745 * @param {string} sSpecific The specific data type you want to get - 9746 * 'display', 'type' 'filter' 'sort' 9747 * @returns {*} The data for the cell from the given row's data 9748 * @default null 9749 */ 9750 "fnGetData": null, 9751 9752 /** 9753 * Function to set data for a cell in the column. You should <b>never</b> 9754 * set the data directly to _aData internally in DataTables - always use 9755 * this method. It allows mData to function as required. This function 9756 * is automatically assigned by the column initialisation method 9757 * @type function 9758 * @param {array|object} oData The data array/object for the array 9759 * (i.e. aoData[]._aData) 9760 * @param {*} sValue Value to set 9761 * @default null 9762 */ 9763 "fnSetData": null, 9764 9765 /** 9766 * Property to read the value for the cells in the column from the data 9767 * source array / object. If null, then the default content is used, if a 9768 * function is given then the return from the function is used. 9769 * @type function|int|string|null 9770 * @default null 9771 */ 9772 "mData": null, 9773 9774 /** 9775 * Partner property to mData which is used (only when defined) to get 9776 * the data - i.e. it is basically the same as mData, but without the 9777 * 'set' option, and also the data fed to it is the result from mData. 9778 * This is the rendering method to match the data method of mData. 9779 * @type function|int|string|null 9780 * @default null 9781 */ 9782 "mRender": null, 9783 9784 /** 9785 * Unique header TH/TD element for this column - this is what the sorting 9786 * listener is attached to (if sorting is enabled.) 9787 * @type node 9788 * @default null 9789 */ 9790 "nTh": null, 9791 9792 /** 9793 * Unique footer TH/TD element for this column (if there is one). Not used 9794 * in DataTables as such, but can be used for plug-ins to reference the 9795 * footer for each column. 9796 * @type node 9797 * @default null 9798 */ 9799 "nTf": null, 9800 9801 /** 9802 * The class to apply to all TD elements in the table's TBODY for the column 9803 * @type string 9804 * @default null 9805 */ 9806 "sClass": null, 9807 9808 /** 9809 * When DataTables calculates the column widths to assign to each column, 9810 * it finds the longest string in each column and then constructs a 9811 * temporary table and reads the widths from that. The problem with this 9812 * is that "mmm" is much wider then "iiii", but the latter is a longer 9813 * string - thus the calculation can go wrong (doing it properly and putting 9814 * it into an DOM object and measuring that is horribly(!) slow). Thus as 9815 * a "work around" we provide this option. It will append its value to the 9816 * text that is found to be the longest string for the column - i.e. padding. 9817 * @type string 9818 */ 9819 "sContentPadding": null, 9820 9821 /** 9822 * Allows a default value to be given for a column's data, and will be used 9823 * whenever a null data source is encountered (this can be because mData 9824 * is set to null, or because the data source itself is null). 9825 * @type string 9826 * @default null 9827 */ 9828 "sDefaultContent": null, 9829 9830 /** 9831 * Name for the column, allowing reference to the column by name as well as 9832 * by index (needs a lookup to work by name). 9833 * @type string 9834 */ 9835 "sName": null, 9836 9837 /** 9838 * Custom sorting data type - defines which of the available plug-ins in 9839 * afnSortData the custom sorting will use - if any is defined. 9840 * @type string 9841 * @default std 9842 */ 9843 "sSortDataType": 'std', 9844 9845 /** 9846 * Class to be applied to the header element when sorting on this column 9847 * @type string 9848 * @default null 9849 */ 9850 "sSortingClass": null, 9851 9852 /** 9853 * Class to be applied to the header element when sorting on this column - 9854 * when jQuery UI theming is used. 9855 * @type string 9856 * @default null 9857 */ 9858 "sSortingClassJUI": null, 9859 9860 /** 9861 * Title of the column - what is seen in the TH element (nTh). 9862 * @type string 9863 */ 9864 "sTitle": null, 9865 9866 /** 9867 * Column sorting and filtering type 9868 * @type string 9869 * @default null 9870 */ 9871 "sType": null, 9872 9873 /** 9874 * Width of the column 9875 * @type string 9876 * @default null 9877 */ 9878 "sWidth": null, 9879 9880 /** 9881 * Width of the column when it was first "encountered" 9882 * @type string 9883 * @default null 9884 */ 9885 "sWidthOrig": null 9886 }; 9887 9888 9889 /* 9890 * Developer note: The properties of the object below are given in Hungarian 9891 * notation, that was used as the interface for DataTables prior to v1.10, however 9892 * from v1.10 onwards the primary interface is camel case. In order to avoid 9893 * breaking backwards compatibility utterly with this change, the Hungarian 9894 * version is still, internally the primary interface, but is is not documented 9895 * - hence the @name tags in each doc comment. This allows a Javascript function 9896 * to create a map from Hungarian notation to camel case (going the other direction 9897 * would require each property to be listed, which would a
9897t around 3K to the size 9898 * of DataTables, while this method is about a 0.5K hit
vendor: 57,087 bytes, lines 9898-11674
9898. 9899 * 9900 * Ultimately this does pave the way for Hungarian notation to be dropped 9901 * completely, but that is a massive amount of work and will break current 9902 * installs (therefore is on-hold until v2). 9903 */ 9904 9905 /** 9906 * Initialisation options that can be given to DataTables at initialisation 9907 * time. 9908 * @namespace 9909 */ 9910 DataTable.defaults = { 9911 /** 9912 * An array of data to use for the table, passed in at initialisation which 9913 * will be used in preference to any data which is already in the DOM. This is 9914 * particularly useful for constructing tables purely in Javascript, for 9915 * example with a custom Ajax call. 9916 * @type array 9917 * @default null 9918 * 9919 * @dtopt Option 9920 * @name DataTable.defaults.data 9921 * 9922 * @example 9923 * // Using a 2D array data source 9924 * $(document).ready( function () { 9925 * $('#example').dataTable( { 9926 * "data": [ 9927 * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'], 9928 * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'], 9929 * ], 9930 * "columns": [ 9931 * { "title": "Engine" }, 9932 * { "title": "Browser" }, 9933 * { "title": "Platform" }, 9934 * { "title": "Version" }, 9935 * { "title": "Grade" } 9936 * ] 9937 * } ); 9938 * } ); 9939 * 9940 * @example 9941 * // Using an array of objects as a data source (`data`) 9942 * $(document).ready( function () { 9943 * $('#example').dataTable( { 9944 * "data": [ 9945 * { 9946 * "engine": "Trident", 9947 * "browser": "Internet Explorer 4.0", 9948 * "platform": "Win 95+", 9949 * "version": 4, 9950 * "grade": "X" 9951 * }, 9952 * { 9953 * "engine": "Trident", 9954 * "browser": "Internet Explorer 5.0", 9955 * "platform": "Win 95+", 9956 * "version": 5, 9957 * "grade": "C" 9958 * } 9959 * ], 9960 * "columns": [ 9961 * { "title": "Engine", "data": "engine" }, 9962 * { "title": "Browser", "data": "browser" }, 9963 * { "title": "Platform", "data": "platform" }, 9964 * { "title": "Version", "data": "version" }, 9965 * { "title": "Grade", "data": "grade" } 9966 * ] 9967 * } ); 9968 * } ); 9969 */ 9970 "aaData": null, 9971 9972 9973 /** 9974 * If ordering is enabled, then DataTables will perform a first pass sort on 9975 * initialisation. You can define which column(s) the sort is performed 9976 * upon, and the sorting direction, with this variable. The `sorting` array 9977 * should contain an array for each column to be sorted initially containing 9978 * the column's index and a direction string ('asc' or 'desc'). 9979 * @type array 9980 * @default [[0,'asc']] 9981 * 9982 * @dtopt Option 9983 * @name DataTable.defaults.order 9984 * 9985 * @example 9986 * // Sort by 3rd column first, and then 4th column 9987 * $(document).ready( function() { 9988 * $('#example').dataTable( { 9989 * "order": [[2,'asc'], [3,'desc']] 9990 * } ); 9991 * } ); 9992 * 9993 * // No initial sorting 9994 * $(document).ready( function() { 9995 * $('#example').dataTable( { 9996 * "order": [] 9997 * } ); 9998 * } ); 9999 */ 10000 "aaSorting": [[0,'asc']], 10001 10002 10003 /** 10004 * This parameter is basically identical to the `sorting` parameter, but 10005 * cannot be overridden by user interaction with the table. What this means 10006 * is that you could have a column (visible or hidden) which the sorting 10007 * will always be forced on first - any sorting after that (from the user) 10008 * will then be performed as required. This can be useful for grouping rows 10009 * together. 10010 * @type array 10011 * @default null 10012 * 10013 * @dtopt Option 10014 * @name DataTable.defaults.orderFixed 10015 * 10016 * @example 10017 * $(document).ready( function() { 10018 * $('#example').dataTable( { 10019 * "orderFixed": [[0,'asc']] 10020 * } ); 10021 * } ) 10022 */ 10023 "aaSortingFixed": [], 10024 10025 10026 /** 10027 * DataTables can be instructed to load data to display in the table from a 10028 * Ajax source. This option defines how that Ajax call is made and where to. 10029 * 10030 * The `ajax` property has three different modes of operation, depending on 10031 * how it is defined. These are: 10032 * 10033 * * `string` - Set the URL from where the data should be loaded from. 10034 * * `object` - Define properties for `jQuery.ajax`. 10035 * * `function` - Custom data get function 10036 * 10037 * `string` 10038 * -------- 10039 * 10040 * As a string, the `ajax` property simply defines the URL from which 10041 * DataTables will load data. 10042 * 10043 * `object` 10044 * -------- 10045 * 10046 * As an object, the parameters in the object are passed to 10047 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control 10048 * of the Ajax request. DataTables has a number of default parameters which 10049 * you can override using this option. Please refer to the jQuery 10050 * documentation for a full description of the options available, although 10051 * the following parameters provide additional options in DataTables or 10052 * require special consideration: 10053 * 10054 * * `data` - As with jQuery, `data` can be provided as an object, but it 10055 * can also be used as a function to manipulate the data DataTables sends 10056 * to the server. The function takes a single parameter, an object of 10057 * parameters with the values that DataTables has readied for sending. An 10058 * object may be returned which will be merged into the DataTables 10059 * defaults, or you can add the items to the object that was passed in and 10060 * not return anything from the function. This supersedes `fnServerParams` 10061 * from DataTables 1.9-. 10062 * 10063 * * `dataSrc` - By default DataTables will look for the property `data` (or 10064 * `aaData` for compatibility with DataTables 1.9-) when obtaining data 10065 * from an Ajax source or for server-side processing - this parameter 10066 * allows that property to be changed. You can use Javascript dotted 10067 * object notation to get a data source for multiple levels of nesting, or 10068 * it my be used as a function. As a function it takes a single parameter, 10069 * the JSON returned from the server, which can be manipulated as 10070 * required, with the returned value being that used by DataTables as the 10071 * data source for the table. This supersedes `sAjaxDataProp` from 10072 * DataTables 1.9-. 10073 * 10074 * * `success` - Should not be overridden it is used internally in 10075 * DataTables. To manipulate / transform the data returned by the server 10076 * use `ajax.dataSrc`, or use `ajax` as a function (see below). 10077 * 10078 * `function` 10079 * ---------- 10080 * 10081 * As a function, making the Ajax call is left up to yourself allowing 10082 * complete control of the Ajax request. Indeed, if desired, a method other 10083 * than Ajax could be used to obtain the required data, such as Web storage 10084 * or an AIR database. 10085 * 10086 * The function is given four parameters and no return is required. The 10087 * parameters are: 10088 * 10089 * 1. _object_ - Data to send to the server 10090 * 2. _function_ - Callback function that must be executed when the required 10091 * data has been obtained. That data should be passed into the callback 10092 * as the only parameter 10093 * 3. _object_ - DataTables settings object for the table 10094 * 10095 * Note that this supersedes `fnServerData` from DataTables 1.9-. 10096 * 10097 * @type string|object|function 10098 * @default null 10099 * 10100 * @dtopt Option 10101 * @name DataTable.defaults.ajax 10102 * @since 1.10.0 10103 * 10104 * @example 10105 * // Get JSON data from a file via Ajax. 10106 * // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default). 10107 * $('#example').dataTable( { 10108 * "ajax": "data.json" 10109 * } ); 10110 * 10111 * @example 10112 * // Get JSON data from a file via Ajax, using `dataSrc` to change 10113 * // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`) 10114 * $('#example').dataTable( { 10115 * "ajax": { 10116 * "url": "data.json", 10117 * "dataSrc": "tableData" 10118 * } 10119 * } ); 10120 * 10121 * @example 10122 * // Get JSON data from a file via Ajax, using `dataSrc` to read data 10123 * // from a plain array rather than an array in an object 10124 * $('#example').dataTable( { 10125 * "ajax": { 10126 * "url": "data.json", 10127 * "dataSrc": "" 10128 * } 10129 * } ); 10130 * 10131 * @example 10132 * // Manipulate the data returned from the server - add a link to data 10133 * // (note this can, should, be done using `render` for the column - this 10134 * // is just a simple example of how the data can be manipulated). 10135 * $('#example').dataTable( { 10136 * "ajax": { 10137 * "url": "data.json", 10138 * "dataSrc": function ( json ) { 10139 * for ( var i=0, ien=json.length ; i<ien ; i++ ) { 10140 * json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>'; 10141 * } 10142 * return json; 10143 * } 10144 * } 10145 * } ); 10146 * 10147 * @example 10148 * // Add data to the request 10149 * $('#example').dataTable( { 10150 * "ajax": { 10151 * "url": "data.json", 10152 * "data": function ( d ) { 10153 * return { 10154 * "extra_search": $('#extra').val() 10155 * }; 10156 * } 10157 * } 10158 * } ); 10159 * 10160 * @example 10161 * // Send request as POST 10162 * $('#example').dataTable( { 10163 * "ajax": { 10164 * "url": "data.json", 10165 * "type": "POST" 10166 * } 10167 * } ); 10168 * 10169 * @example 10170 * // Get the data from localStorage (could interface with a form for 10171 * // adding, editing and removing rows). 10172 * $('#example').dataTable( { 10173 * "ajax": function (data, callback, settings) { 10174 * callback( 10175 * JSON.parse( localStorage.getItem('dataTablesData') ) 10176 * ); 10177 * } 10178 * } ); 10179 */ 10180 "ajax": null, 10181 10182 10183 /** 10184 * This parameter allows you to readily specify the entries in the length drop 10185 * down menu that DataTables shows when pagination is enabled. It can be 10186 * either a 1D array of options which will be used for both the displayed 10187 * option and the value, or a 2D array which will use the array in the first 10188 * position as the value, and the array in the second position as the 10189 * displayed options (useful for language strings such as 'All'). 10190 * 10191 * Note that the `pageLength` property will be automatically set to the 10192 * first value given in this array, unless `pageLength` is also provided. 10193 * @type array 10194 * @default [ 10, 25, 50, 100 ] 10195 * 10196 * @dtopt Option 10197 * @name DataTable.defaults.lengthMenu 10198 * 10199 * @example 10200 * $(document).ready( function() { 10201 * $('#example').dataTable( { 10202 * "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]] 10203 * } ); 10204 * } ); 10205 */ 10206 "aLengthMenu": [ 10, 25, 50, 100 ], 10207 10208 10209 /** 10210 * The `columns` option in the initialisation parameter allows you to define 10211 * details about the way individual columns behave. For a full list of 10212 * column options that can be set, please see 10213 * {@link DataTable.defaults.column}. Note that if you use `columns` to 10214 * define your columns, you must have an entry in the array for every single 10215 * column that you have in your table (these can be null if you don't which 10216 * to specify any options). 10217 * @member 10218 * 10219 * @name DataTable.defaults.column 10220 */ 10221 "aoColumns": null, 10222 10223 /** 10224 * Very similar to `columns`, `columnDefs` allows you to target a specific 10225 * column, multiple columns, or all columns, using the `targets` property of 10226 * each object in the array. This allows great flexibility when creating 10227 * tables, as the `columnDefs` arrays can be of any length, targeting the 10228 * columns you specifically want. `columnDefs` may use any of the column 10229 * options available: {@link DataTable.defaults.column}, but it _must_ 10230 * have `targets` defined in each object in the array. Values in the `targets` 10231 * array may be: 10232 * <ul> 10233 * <li>a string - class name will be matched on the TH for the column</li> 10234 * <li>0 or a positive integer - column index counting from the left</li> 10235 * <li>a negative integer - column index counting from the right</li> 10236 * <li>the string "_all" - all columns (i.e. assign a default)</li> 10237 * </ul> 10238 * @member 10239 * 10240 * @name DataTable.defaults.columnDefs 10241 */ 10242 "aoColumnDefs": null, 10243 10244 10245 /** 10246 * Basically the same as `search`, this parameter defines the individual column 10247 * filtering state at initialisation time. The array must be of the same size 10248 * as the number of columns, and each element be an object with the parameters 10249 * `search` and `escapeRegex` (the latter is optional). 'null' is also 10250 * accepted and the default will be used. 10251 * @type array 10252 * @default [] 10253 * 10254 * @dtopt Option 10255 * @name DataTable.defaults.searchCols 10256 * 10257 * @example 10258 * $(document).ready( function() { 10259 * $('#example').dataTable( { 10260 * "searchCols": [ 10261 * null, 10262 * { "search": "My filter" }, 10263 * null, 10264 * { "search": "^[0-9]", "escapeRegex": false } 10265 * ] 10266 * } ); 10267 * } ) 10268 */ 10269 "aoSearchCols": [], 10270 10271 10272 /** 10273 * An array of CSS classes that should be applied to displayed rows. This 10274 * array may be of any length, and DataTables will apply each class 10275 * sequentially, looping when required. 10276 * @type array 10277 * @default null <i>Will take the values determined by the `oClasses.stripe*` 10278 * options</i> 10279 * 10280 * @dtopt Option 10281 * @name DataTable.defaults.stripeClasses 10282 * 10283 * @example 10284 * $(document).ready( function() { 10285 * $('#example').dataTable( { 10286 * "stripeClasses": [ 'strip1', 'strip2', 'strip3' ] 10287 * } ); 10288 * } ) 10289 */ 10290 "asStripeClasses": null, 10291 10292 10293 /** 10294 * Enable or disable automatic column width calculation. This can be disabled 10295 * as an optimisation (it takes some time to calculate the widths) if the 10296 * tables widths are passed in using `columns`. 10297 * @type boolean 10298 * @default true 10299 * 10300 * @dtopt Features 10301 * @name DataTable.defaults.autoWidth 10302 * 10303 * @example 10304 * $(document).ready( function () { 10305 * $('#example').dataTable( { 10306 * "autoWidth": false 10307 * } ); 10308 * } ); 10309 */ 10310 "bAutoWidth": true, 10311 10312 10313 /** 10314 * Deferred rendering can provide DataTables with a huge speed boost when you 10315 * are using an Ajax or JS data source for the table. This option, when set to 10316 * true, will cause DataTables to defer the creation of the table elements for 10317 * each row until they are needed for a draw - saving a significant amount of 10318 * time. 10319 * @type boolean 10320 * @default false 10321 * 10322 * @dtopt Features 10323 * @name DataTable.defaults.deferRender 10324 * 10325 * @example 10326 * $(document).ready( function() { 10327 * $('#example').dataTable( { 10328 * "ajax": "sources/arrays.txt", 10329 * "deferRender": true 10330 * } ); 10331 * } ); 10332 */ 10333 "bDeferRender": false, 10334 10335 10336 /** 10337 * Replace a DataTable which matches the given selector and replace it with 10338 * one which has the properties of the new initialisation object passed. If no 10339 * table matches the selector, then the new DataTable will be constructed as 10340 * per normal. 10341 * @type boolean 10342 * @default false 10343 * 10344 * @dtopt Options 10345 * @name DataTable.defaults.destroy 10346 * 10347 * @example 10348 * $(document).ready( function() { 10349 * $('#example').dataTable( { 10350 * "srollY": "200px", 10351 * "paginate": false 10352 * } ); 10353 * 10354 * // Some time later.... 10355 * $('#example').dataTable( { 10356 * "filter": false, 10357 * "destroy": true 10358 * } ); 10359 * } ); 10360 */ 10361 "bDestroy": false, 10362 10363 10364 /** 10365 * Enable or disable filtering of data. Filtering in DataTables is "smart" in 10366 * that it allows the end user to input multiple words (space separated) and 10367 * will match a row containing those words, even if not in the order that was 10368 * specified (this allow matching across multiple columns). Note that if you 10369 * wish to use filtering in DataTables this must remain 'true' - to remove the 10370 * default filtering input box and retain filtering abilities, please use 10371 * {@link DataTable.defaults.dom}. 10372 * @type boolean 10373 * @default true 10374 * 10375 * @dtopt Features 10376 * @name DataTable.defaults.searching 10377 * 10378 * @example 10379 * $(document).ready( function () { 10380 * $('#example').dataTable( { 10381 * "searching": false 10382 * } ); 10383 * } ); 10384 */ 10385 "bFilter": true, 10386 10387 10388 /** 10389 * Enable or disable the table information display. This shows information 10390 * about the data that is currently visible on the page, including information 10391 * about filtered data if that action is being performed. 10392 * @type boolean 10393 * @default true 10394 * 10395 * @dtopt Features 10396 * @name DataTable.defaults.info 10397 * 10398 * @example 10399 * $(document).ready( function () { 10400 * $('#example').dataTable( { 10401 * "info": false 10402 * } ); 10403 * } ); 10404 */ 10405 "bInfo": true, 10406 10407 10408 /** 10409 * Allows the end user to select the size of a formatted page from a select 10410 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`). 10411 * @type boolean 10412 * @default true 10413 * 10414 * @dtopt Features 10415 * @name DataTable.defaults.lengthChange 10416 * 10417 * @example 10418 * $(document).ready( function () { 10419 * $('#example').dataTable( { 10420 * "lengthChange": false 10421 * } ); 10422 * } ); 10423 */ 10424 "bLengthChange": true, 10425 10426 10427 /** 10428 * Enable or disable pagination. 10429 * @type boolean 10430 * @default true 10431 * 10432 * @dtopt Features 10433 * @name DataTable.defaults.paging 10434 * 10435 * @example 10436 * $(document).ready( function () { 10437 * $('#example').dataTable( { 10438 * "paging": false 10439 * } ); 10440 * } ); 10441 */ 10442 "bPaginate": true, 10443 10444 10445 /** 10446 * Enable or disable the display of a 'processing' indicator when the table is 10447 * being processed (e.g. a sort). This is particularly useful for tables with 10448 * large amounts of data where it can take a noticeable amount of time to sort 10449 * the entries. 10450 * @type boolean 10451 * @default false 10452 * 10453 * @dtopt Features 10454 * @name DataTable.defaults.processing 10455 * 10456 * @example 10457 * $(document).ready( function () { 10458 * $('#example').dataTable( { 10459 * "processing": true 10460 * } ); 10461 * } ); 10462 */ 10463 "bProcessing": false, 10464 10465 10466 /** 10467 * Retrieve the DataTables object for the given selector. Note that if the 10468 * table has already been initialised, this parameter will cause DataTables 10469 * to simply return the object that has already been set up - it will not take 10470 * account of any changes you might have made to the initialisation object 10471 * passed to DataTables (setting this parameter to true is an acknowledgement 10472 * that you understand this). `destroy` can be used to reinitialise a table if 10473 * you need. 10474 * @type boolean 10475 * @default false 10476 * 10477 * @dtopt Options 10478 * @name DataTable.defaults.retrieve 10479 * 10480 * @example 10481 * $(document).ready( function() { 10482 * initTable(); 10483 * tableActions(); 10484 * } ); 10485 * 10486 * function initTable () 10487 * { 10488 * return $('#example').dataTable( { 10489 * "scrollY": "200px", 10490 * "paginate": false, 10491 * "retrieve": true 10492 * } ); 10493 * } 10494 * 10495 * function tableActions () 10496 * { 10497 * var table = initTable(); 10498 * // perform API operations with oTable 10499 * } 10500 */ 10501 "bRetrieve": false, 10502 10503 10504 /** 10505 * When vertical (y) scrolling is enabled, DataTables will force the height of 10506 * the table's viewport to the given height at all times (useful for layout). 10507 * However, this can look odd when filtering data down to a small data set, 10508 * and the footer is left "floating" further down. This parameter (when 10509 * enabled) will cause DataTables to collapse the table's viewport down when 10510 * the result set will fit within the given Y height. 10511 * @type boolean 10512 * @default false 10513 * 10514 * @dtopt Options 10515 * @name DataTable.defaults.scrollCollapse 10516 * 10517 * @example 10518 * $(document).ready( function() { 10519 * $('#example').dataTable( { 10520 * "scrollY": "200", 10521 * "scrollCollapse": true 10522 * } ); 10523 * } ); 10524 */ 10525 "bScrollCollapse": false, 10526 10527 10528 /** 10529 * Configure DataTables to use server-side processing. Note that the 10530 * `ajax` parameter must also be given in order to give DataTables a 10531 * source to obtain the required data for each draw. 10532 * @type boolean 10533 * @default false 10534 * 10535 * @dtopt Features 10536 * @dtopt Server-side 10537 * @name DataTable.defaults.serverSide 10538 * 10539 * @example 10540 * $(document).ready( function () { 10541 * $('#example').dataTable( { 10542 * "serverSide": true, 10543 * "ajax": "xhr.php" 10544 * } ); 10545 * } ); 10546 */ 10547 "bServerSide": false, 10548 10549 10550 /** 10551 * Enable or disable sorting of columns. Sorting of individual columns can be 10552 * disabled by the `sortable` option for each column. 10553 * @type boolean 10554 * @default true 10555 * 10556 * @dtopt Features 10557 * @name DataTable.defaults.ordering 10558 * 10559 * @example 10560 * $(document).ready( function () { 10561 * $('#example').dataTable( { 10562 * "ordering": false 10563 * } ); 10564 * } ); 10565 */ 10566 "bSort": true, 10567 10568 10569 /** 10570 * Enable or display DataTables' ability to sort multiple columns at the 10571 * same time (activated by shift-click by the user). 10572 * @type boolean 10573 * @default true 10574 * 10575 * @dtopt Options 10576 * @name DataTable.defaults.orderMulti 10577 * 10578 * @example 10579 * // Disable multiple column sorting ability 10580 * $(document).ready( function () { 10581 * $('#example').dataTable( { 10582 * "orderMulti": false 10583 * } ); 10584 * } ); 10585 */ 10586 "bSortMulti": true, 10587 10588 10589 /** 10590 * Allows control over whether DataTables should use the top (true) unique 10591 * cell that is found for a single column, or the bottom (false - default). 10592 * This is useful when using complex headers. 10593 * @type boolean 10594 * @default false 10595 * 10596 * @dtopt Options 10597 * @name DataTable.defaults.orderCellsTop 10598 * 10599 * @example 10600 * $(document).ready( function() { 10601 * $('#example').dataTable( { 10602 * "orderCellsTop": true 10603 * } ); 10604 * } ); 10605 */ 10606 "bSortCellsTop": false, 10607 10608 10609 /** 10610 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and 10611 * `sorting\_3` to the columns which are currently being sorted on. This is 10612 * presented as a feature switch as it can increase processing time (while 10613 * classes are removed and added) so for large data sets you might want to 10614 * turn this off. 10615 * @type boolean 10616 * @default true 10617 * 10618 * @dtopt Features 10619 * @name DataTable.defaults.orderClasses 10620 * 10621 * @example 10622 * $(document).ready( function () { 10623 * $('#example').dataTable( { 10624 * "orderClasses": false 10625 * } ); 10626 * } ); 10627 */ 10628 "bSortClasses": true, 10629 10630 10631 /** 10632 * Enable or disable state saving. When enabled HTML5 `localStorage` will be 10633 * used to save table display information such as pagination information, 10634 * display length, filtering and sorting. As such when the end user reloads 10635 * the page the display display will match what thy had previously set up. 10636 * 10637 * Due to the use of `localStorage` the default state saving is not supported 10638 * in IE6 or 7. If state saving is required in those browsers, use 10639 * `stateSaveCallback` to provide a storage solution such as cookies. 10640 * @type boolean 10641 * @default false 10642 * 10643 * @dtopt Features 10644 * @name DataTable.defaults.stateSave 10645 * 10646 * @example 10647 * $(document).ready( function () { 10648 * $('#example').dataTable( { 10649 * "stateSave": true 10650 * } ); 10651 * } ); 10652 */ 10653 "bStateSave": false, 10654 10655 10656 /** 10657 * This function is called when a TR element is created (and all TD child 10658 * elements have been inserted), or registered if using a DOM source, allowing 10659 * manipulation of the TR element (adding classes etc). 10660 * @type function 10661 * @param {node} row "TR" element for the current row 10662 * @param {array} data Raw data array for this row 10663 * @param {int} dataIndex The index of this row in the internal aoData array 10664 * 10665 * @dtopt Callbacks 10666 * @name DataTable.defaults.createdRow 10667 * 10668 * @example 10669 * $(document).ready( function() { 10670 * $('#example').dataTable( { 10671 * "createdRow": function( row, data, dataIndex ) { 10672 * // Bold the grade for all 'A' grade browsers 10673 * if ( data[4] == "A" ) 10674 * { 10675 * $('td:eq(4)', row).html( '<b>A</b>' ); 10676 * } 10677 * } 10678 * } ); 10679 * } ); 10680 */ 10681 "fnCreatedRow": null, 10682 10683 10684 /** 10685 * This function is called on every 'draw' event, and allows you to 10686 * dynamically modify any aspect you want about the created DOM. 10687 * @type function 10688 * @param {object} settings DataTables settings object 10689 * 10690 * @dtopt Callbacks 10691 * @name DataTable.defaults.drawCallback 10692 * 10693 * @example 10694 * $(document).ready( function() { 10695 * $('#example').dataTable( { 10696 * "drawCallback": function( settings ) { 10697 * alert( 'DataTables has redrawn the table' ); 10698 * } 10699 * } ); 10700 * } ); 10701 */ 10702 "fnDrawCallback": null, 10703 10704 10705 /** 10706 * Identical to fnHeaderCallback() but for the table footer this function 10707 * allows you to modify the table footer on every 'draw' event. 10708 * @type function 10709 * @param {node} foot "TR" element for the footer 10710 * @param {array} data Full table data (as derived from the original HTML) 10711 * @param {int} start Index for the current display starting point in the 10712 * display array 10713 * @param {int} end Index for the current display ending point in the 10714 * display array 10715 * @param {array int} display Index array to translate the visual position 10716 * to the full data array 10717 * 10718 * @dtopt Callbacks 10719 * @name DataTable.defaults.footerCallback 10720 * 10721 * @example 10722 * $(document).ready( function() { 10723 * $('#example').dataTable( { 10724 * "footerCallback": function( tfoot, data, start, end, display ) { 10725 * tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start; 10726 * } 10727 * } ); 10728 * } ) 10729 */ 10730 "fnFooterCallback": null, 10731 10732 10733 /** 10734 * When rendering large numbers in the information element for the table 10735 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers 10736 * to have a comma separator for the 'thousands' units (e.g. 1 million is 10737 * rendered as "1,000,000") to help readability for the end user. This 10738 * function will override the default method DataTables uses. 10739 * @type function 10740 * @member 10741 * @param {int} toFormat number to be formatted 10742 * @returns {string} formatted string for DataTables to show the number 10743 * 10744 * @dtopt Callbacks 10745 * @name DataTable.defaults.formatNumber 10746 * 10747 * @example 10748 * // Format a number using a single quote for the separator (note that 10749 * // this can also be done with the language.thousands option) 10750 * $(document).ready( function() { 10751 * $('#example').dataTable( { 10752 * "formatNumber": function ( toFormat ) { 10753 * return toFormat.toString().replace( 10754 * /\B(?=(\d{3})+(?!\d))/g, "'" 10755 * ); 10756 * }; 10757 * } ); 10758 * } ); 10759 */ 10760 "fnFormatNumber": function ( toFormat ) { 10761 return toFormat.toString().replace( 10762 /\B(?=(\d{3})+(?!\d))/g, 10763 this.oLanguage.sThousands 10764 ); 10765 }, 10766 10767 10768 /** 10769 * This function is called on every 'draw' event, and allows you to 10770 * dynamically modify the header row. This can be used to calculate and 10771 * display useful information about the table. 10772 * @type function 10773 * @param {node} head "TR" element for the header 10774 * @param {array} data Full table data (as derived from the original HTML) 10775 * @param {int} start Index for the current display starting point in the 10776 * display array 10777 * @param {int} end Index for the current display ending point in the 10778 * display array 10779 * @param {array int} display Index array to translate the visual position 10780 * to the full data array 10781 * 10782 * @dtopt Callbacks 10783 * @name DataTable.defaults.headerCallback 10784 * 10785 * @example 10786 * $(document).ready( function() { 10787 * $('#example').dataTable( { 10788 * "fheaderCallback": function( head, data, start, end, display ) { 10789 * head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records"; 10790 * } 10791 * } ); 10792 * } ) 10793 */ 10794 "fnHeaderCallback": null, 10795 10796 10797 /** 10798 * The information element can be used to convey information about the current 10799 * state of the table. Although the internationalisation options presented by 10800 * DataTables are quite capable of dealing with most customisations, there may 10801 * be times where you wish to customise the string further. This callback 10802 * allows you to do exactly that. 10803 * @type function 10804 * @param {object} oSettings DataTables settings object 10805 * @param {int} start Starting position in data for the draw 10806 * @param {int} end End position in data for the draw 10807 * @param {int} max Total number of rows in the table (regardless of 10808 * filtering) 10809 * @param {int} total Total number of rows in the data set, after filtering 10810 * @param {string} pre The string that DataTables has formatted using it's 10811 * own rules 10812 * @returns {string} The string to be displayed in the information element. 10813 * 10814 * @dtopt Callbacks 10815 * @name DataTable.defaults.infoCallback 10816 * 10817 * @example 10818 * $('#example').dataTable( { 10819 * "infoCallback": function( settings, start, end, max, total, pre ) { 10820 * return start +" to "+ end; 10821 * } 10822 * } ); 10823 */ 10824 "fnInfoCallback": null, 10825 10826 10827 /** 10828 * Called when the table has been initialised. Normally DataTables will 10829 * initialise sequentially and there will be no need for this function, 10830 * however, this does not hold true when using external language information 10831 * since that is obtained using an async XHR call. 10832 * @type function 10833 * @param {object} settings DataTables settings object 10834 * @param {object} json The JSON object request from the server - only 10835 * present if client-side Ajax sourced data is used 10836 * 10837 * @dtopt Callbacks 10838 * @name DataTable.defaults.initComplete 10839 * 10840 * @example 10841 * $(document).ready( function() { 10842 * $('#example').dataTable( { 10843 * "initComplete": function(settings, json) { 10844 * alert( 'DataTables has finished its initialisation.' ); 10845 * } 10846 * } ); 10847 * } ) 10848 */ 10849 "fnInitComplete": null, 10850 10851 10852 /** 10853 * Called at the very start of each table draw and can be used to cancel the 10854 * draw by returning false, any other return (including undefined) results in 10855 * the full draw occurring). 10856 * @type function 10857 * @param {object} settings DataTables settings object 10858 * @returns {boolean} False will cancel the draw, anything else (including no 10859 * return) will allow it to complete. 10860 * 10861 * @dtopt Callbacks 10862 * @name DataTable.defaults.preDrawCallback 10863 * 10864 * @example 10865 * $(document).ready( function() { 10866 * $('#example').dataTable( { 10867 * "preDrawCallback": function( settings ) { 10868 * if ( $('#test').val() == 1 ) { 10869 * return false; 10870 * } 10871 * } 10872 * } ); 10873 * } ); 10874 */ 10875 "fnPreDrawCallback": null, 10876 10877 10878 /** 10879 * This function allows you to 'post process' each row after it have been 10880 * generated for each table draw, but before it is rendered on screen. This 10881 * function might be used for setting the row class name etc. 10882 * @type function 10883 * @param {node} row "TR" element for the current row 10884 * @param {array} data Raw data array for this row 10885 * @param {int} displayIndex The display index for the current table draw 10886 * @param {int} displayIndexFull The index of the data in the full list of 10887 * rows (after filtering) 10888 * 10889 * @dtopt Callbacks 10890 * @name DataTable.defaults.rowCallback 10891 * 10892 * @example 10893 * $(document).ready( function() { 10894 * $('#example').dataTable( { 10895 * "rowCallback": function( row, data, displayIndex, displayIndexFull ) { 10896 * // Bold the grade for all 'A' grade browsers 10897 * if ( data[4] == "A" ) { 10898 * $('td:eq(4)', row).html( '<b>A</b>' ); 10899 * } 10900 * } 10901 * } ); 10902 * } ); 10903 */ 10904 "fnRowCallback": null, 10905 10906 10907 /** 10908 * __Deprecated__ The functionality provided by this parameter has now been 10909 * superseded by that provided through `ajax`, which should be used instead. 10910 * 10911 * This parameter allows you to override the default function which obtains 10912 * the data from the server so something more suitable for your application. 10913 * For example you could use POST data, or pull information from a Gears or 10914 * AIR database. 10915 * @type function 10916 * @member 10917 * @param {string} source HTTP source to obtain the data from (`ajax`) 10918 * @param {array} data A key/value pair object containing the data to send 10919 * to the server 10920 * @param {function} callback to be called on completion of the data get 10921 * process that will draw the data on the page. 10922 * @param {object} settings DataTables settings object 10923 * 10924 * @dtopt Callbacks 10925 * @dtopt Server-side 10926 * @name DataTable.defaults.serverData 10927 * 10928 * @deprecated 1.10. Please use `ajax` for this functionality now. 10929 */ 10930 "fnServerData": null, 10931 10932 10933 /** 10934 * __Deprecated__ The functionality provided by this parameter has now been 10935 * superseded by that provided through `ajax`, which should be used instead. 10936 * 10937 * It is often useful to send extra data to the server when making an Ajax 10938 * request - for example custom filtering information, and this callback 10939 * function makes it trivial to send extra information to the server. The 10940 * passed in parameter is the data set that has been constructed by 10941 * DataTables, and you can add to this or modify it as you require. 10942 * @type function 10943 * @param {array} data Data array (array of objects which are name/value 10944 * pairs) that has been constructed by DataTables and will be sent to the 10945 * server. In the case of Ajax sourced data with server-side processing 10946 * this will be an empty array, for server-side processing there will be a 10947 * significant number of parameters! 10948 * @returns {undefined} Ensure that you modify the data array passed in, 10949 * as this is passed by reference. 10950 * 10951 * @dtopt Callbacks 10952 * @dtopt Server-side 10953 * @name DataTable.defaults.serverParams 10954 * 10955 * @deprecated 1.10. Please use `ajax` for this functionality now. 10956 */ 10957 "fnServerParams": null, 10958 10959 10960 /** 10961 * Load the table state. With this function you can define from where, and how, the 10962 * state of a table is loaded. By default DataTables will load from `localStorage` 10963 * but you might wish to use a server-side database or cookies. 10964 * @type function 10965 * @member 10966 * @param {object} settings DataTables settings object 10967 * @param {object} callback Callback that can be executed when done. It 10968 * should be passed the loaded state object. 10969 * @return {object} The DataTables state object to be loaded 10970 * 10971 * @dtopt Callbacks 10972 * @name DataTable.defaults.stateLoadCallback 10973 * 10974 * @example 10975 * $(document).ready( function() { 10976 * $('#example').dataTable( { 10977 * "stateSave": true, 10978 * "stateLoadCallback": function (settings, callback) { 10979 * $.ajax( { 10980 * "url": "/state_load", 10981 * "dataType": "json", 10982 * "success": function (json) { 10983 * callback( json ); 10984 * } 10985 * } ); 10986 * } 10987 * } ); 10988 * } ); 10989 */ 10990 "fnStateLoadCallback": function ( settings ) { 10991 try { 10992 return JSON.parse( 10993 (settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem( 10994 'DataTables_'+settings.sInstance+'_'+location.pathname 10995 ) 10996 ); 10997 } catch (e) {} 10998 }, 10999 11000 11001 /** 11002 * Callback which allows modification of the saved state prior to loading that state. 11003 * This callback is called when the table is loading state from the stored data, but 11004 * prior to the settings object being modified by the saved state. Note that for 11005 * plug-in authors, you should use the `stateLoadParams` event to load parameters for 11006 * a plug-in. 11007 * @type function 11008 * @param {object} settings DataTables settings object 11009 * @param {object} data The state object that is to be loaded 11010 * 11011 * @dtopt Callbacks 11012 * @name DataTable.defaults.stateLoadParams 11013 * 11014 * @example 11015 * // Remove a saved filter, so filtering is never loaded 11016 * $(document).ready( function() { 11017 * $('#example').dataTable( { 11018 * "stateSave": true, 11019 * "stateLoadParams": function (settings, data) { 11020 * data.oSearch.sSearch = ""; 11021 * } 11022 * } ); 11023 * } ); 11024 * 11025 * @example 11026 * // Disallow state loading by returning false 11027 * $(document).ready( function() { 11028 * $('#example').dataTable( { 11029 * "stateSave": true, 11030 * "stateLoadParams": function (settings, data) { 11031 * return false; 11032 * } 11033 * } ); 11034 * } ); 11035 */ 11036 "fnStateLoadParams": null, 11037 11038 11039 /** 11040 * Callback that is called when the state has been loaded from the state saving method 11041 * and the DataTables settings object has been modified as a result of the loaded state. 11042 * @type function 11043 * @param {object} settings DataTables settings object 11044 * @param {object} data The state object that was loaded 11045 * 11046 * @dtopt Callbacks 11047 * @name DataTable.defaults.stateLoaded 11048 * 11049 * @example 11050 * // Show an alert with the filtering value that was saved 11051 * $(document).ready( function() { 11052 * $('#example').dataTable( { 11053 * "stateSave": true, 11054 * "stateLoaded": function (settings, data) { 11055 * alert( 'Saved filter was: '+data.oSearch.sSearch ); 11056 * } 11057 * } ); 11058 * } ); 11059 */ 11060 "fnStateLoaded": null, 11061 11062 11063 /** 11064 * Save the table state. This function allows you to define where and how the state 11065 * information for the table is stored By default DataTables will use `localStorage` 11066 * but you might wish to use a server-side database or cookies. 11067 * @type function 11068 * @member 11069 * @param {object} settings DataTables settings object 11070 * @param {object} data The state object to be saved 11071 * 11072 * @dtopt Callbacks 11073 * @name DataTable.defaults.stateSaveCallback 11074 * 11075 * @example 11076 * $(document).ready( function() { 11077 * $('#example').dataTable( { 11078 * "stateSave": true, 11079 * "stateSaveCallback": function (settings, data) { 11080 * // Send an Ajax request to the server with the state object 11081 * $.ajax( { 11082 * "url": "/state_save", 11083 * "data": data, 11084 * "dataType": "json", 11085 * "method": "POST" 11086 * "success": function () {} 11087 * } ); 11088 * } 11089 * } ); 11090 * } ); 11091 */ 11092 "fnStateSaveCallback": function ( settings, data ) { 11093 try { 11094 (settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem( 11095 'DataTables_'+settings.sInstance+'_'+location.pathname, 11096 JSON.stringify( data ) 11097 ); 11098 } catch (e) {} 11099 }, 11100 11101 11102 /** 11103 * Callback which allows modification of the state to be saved. Called when the table 11104 * has changed state a new state save is required. This method allows modification of 11105 * the state saving object prior to actually doing the save, including addition or 11106 * other state properties or modification. Note that for plug-in authors, you should 11107 * use the `stateSaveParams` event to save parameters for a plug-in. 11108 * @type function 11109 * @param {object} settings DataTables settings object 11110 * @param {object} data The state object to be saved 11111 * 11112 * @dtopt Callbacks 11113 * @name DataTable.defaults.stateSaveParams 11114 * 11115 * @example 11116 * // Remove a saved filter, so filtering is never saved 11117 * $(document).ready( function() { 11118 * $('#example').dataTable( { 11119 * "stateSave": true, 11120 * "stateSaveParams": function (settings, data) { 11121 * data.oSearch.sSearch = ""; 11122 * } 11123 * } ); 11124 * } ); 11125 */ 11126 "fnStateSaveParams": null, 11127 11128 11129 /** 11130 * Duration for which the saved state information is considered valid. After this period 11131 * has elapsed the state will be returned to the default. 11132 * Value is given in seconds. 11133 * @type int 11134 * @default 7200 <i>(2 hours)</i> 11135 * 11136 * @dtopt Options 11137 * @name DataTable.defaults.stateDuration 11138 * 11139 * @example 11140 * $(document).ready( function() { 11141 * $('#example').dataTable( { 11142 * "stateDuration": 60*60*24; // 1 day 11143 * } ); 11144 * } ) 11145 */ 11146 "iStateDuration": 7200, 11147 11148 11149 /** 11150 * When enabled DataTables will not make a request to the server for the first 11151 * page draw - rather it will use the data already on the page (no sorting etc 11152 * will be applied to it), thus saving on an XHR at load time. `deferLoading` 11153 * is used to indicate that deferred loading is required, but it is also used 11154 * to tell DataTables how many records there are in the full table (allowing 11155 * the information element and pagination to be displayed correctly). In the case 11156 * where a filtering is applied to the table on initial load, this can be 11157 * indicated by giving the parameter as an array, where the first element is 11158 * the number of records available after filtering and the second element is the 11159 * number of records without filtering (allowing the table information element 11160 * to be shown correctly). 11161 * @type int | array 11162 * @default null 11163 * 11164 * @dtopt Options 11165 * @name DataTable.defaults.deferLoading 11166 * 11167 * @example 11168 * // 57 records available in the table, no filtering applied 11169 * $(document).ready( function() { 11170 * $('#example').dataTable( { 11171 * "serverSide": true, 11172 * "ajax": "scripts/server_processing.php", 11173 * "deferLoading": 57 11174 * } ); 11175 * } ); 11176 * 11177 * @example 11178 * // 57 records after filtering, 100 without filtering (an initial filter applied) 11179 * $(document).ready( function() { 11180 * $('#example').dataTable( { 11181 * "serverSide": true, 11182 * "ajax": "scripts/server_processing.php", 11183 * "deferLoading": [ 57, 100 ], 11184 * "search": { 11185 * "search": "my_filter" 11186 * } 11187 * } ); 11188 * } ); 11189 */ 11190 "iDeferLoading": null, 11191 11192 11193 /** 11194 * Number of rows to display on a single page when using pagination. If 11195 * feature enabled (`lengthChange`) then the end user will be able to override 11196 * this to a custom setting using a pop-up menu. 11197 * @type int 11198 * @default 10 11199 * 11200 * @dtopt Options 11201 * @name DataTable.defaults.pageLength 11202 * 11203 * @example 11204 * $(document).ready( function() { 11205 * $('#example').dataTable( { 11206 * "pageLength": 50 11207 * } ); 11208 * } ) 11209 */ 11210 "iDisplayLength": 10, 11211 11212 11213 /** 11214 * Define the starting point for data display when using DataTables with 11215 * pagination. Note that this parameter is the number of records, rather than 11216 * the page number, so if you have 10 records per page and want to start on 11217 * the third page, it should be "20". 11218 * @type int 11219 * @default 0 11220 * 11221 * @dtopt Options 11222 * @name DataTable.defaults.displayStart 11223 * 11224 * @example 11225 * $(document).ready( function() { 11226 * $('#example').dataTable( { 11227 * "displayStart": 20 11228 * } ); 11229 * } ) 11230 */ 11231 "iDisplayStart": 0, 11232 11233 11234 /** 11235 * By default DataTables allows keyboard navigation of the table (sorting, paging, 11236 * and filtering) by adding a `tabindex` attribute to the required elements. This 11237 * allows you to tab through the controls and press the enter key to activate them. 11238 * The tabindex is default 0, meaning that the tab follows the flow of the document. 11239 * You can overrule this using this parameter if you wish. Use a value of -1 to 11240 * disable built-in keyboard navigation. 11241 * @type int 11242 * @default 0 11243 * 11244 * @dtopt Options 11245 * @name DataTable.defaults.tabIndex 11246 * 11247 * @example 11248 * $(document).ready( function() { 11249 * $('#example').dataTable( { 11250 * "tabIndex": 1 11251 * } ); 11252 * } ); 11253 */ 11254 "iTabIndex": 0, 11255 11256 11257 /** 11258 * Classes that DataTables assigns to the various components and features 11259 * that it adds to the HTML table. This allows classes to be configured 11260 * during initialisation in addition to through the static 11261 * {@link DataTable.ext.oStdClasses} object). 11262 * @namespace 11263 * @name DataTable.defaults.classes 11264 */ 11265 "oClasses": {}, 11266 11267 11268 /** 11269 * All strings that DataTables uses in the user interface that it creates 11270 * are defined in this object, allowing you to modified them individually or 11271 * completely replace them all as required. 11272 * @namespace 11273 * @name DataTable.defaults.language 11274 */ 11275 "oLanguage": { 11276 /** 11277 * Strings that are used for WAI-ARIA labels and controls only (these are not 11278 * actually visible on the page, but will be read by screenreaders, and thus 11279 * must be internationalised as well). 11280 * @namespace 11281 * @name DataTable.defaults.language.aria 11282 */ 11283 "oAria": { 11284 /** 11285 * ARIA label that is added to the table headers when the column may be 11286 * sorted ascending by activing the column (click or return when focused). 11287 * Note that the column header is prefixed to this string. 11288 * @type string 11289 * @default : activate to sort column ascending 11290 * 11291 * @dtopt Language 11292 * @name DataTable.defaults.language.aria.sortAscending 11293 * 11294 * @example 11295 * $(document).ready( function() { 11296 * $('#example').dataTable( { 11297 * "language": { 11298 * "aria": { 11299 * "sortAscending": " - click/return to sort ascending" 11300 * } 11301 * } 11302 * } ); 11303 * } ); 11304 */ 11305 "sSortAscending": ": activate to sort column ascending", 11306 11307 /** 11308 * ARIA label that is added to the table headers when the column may be 11309 * sorted descending by activing the column (click or return when focused). 11310 * Note that the column header is prefixed to this string. 11311 * @type string 11312 * @default : activate to sort column ascending 11313 * 11314 * @dtopt Language 11315 * @name DataTable.defaults.language.aria.sortDescending 11316 * 11317 * @example 11318 * $(document).ready( function() { 11319 * $('#example').dataTable( { 11320 * "language": { 11321 * "aria": { 11322 * "sortDescending": " - click/return to sort descending" 11323 * } 11324 * } 11325 * } ); 11326 * } ); 11327 */ 11328 "sSortDescending": ": activate to sort column descending" 11329 }, 11330 11331 /** 11332 * Pagination string used by DataTables for the built-in pagination 11333 * control types. 11334 * @namespace 11335 * @name DataTable.defaults.language.paginate 11336 */ 11337 "oPaginate": { 11338 /** 11339 * Text to use when using the 'full_numbers' type of pagination for the 11340 * button to take the user to the first page. 11341 * @type string 11342 * @default First 11343 * 11344 * @dtopt Language 11345 * @name DataTable.defaults.language.paginate.first 11346 * 11347 * @example 11348 * $(document).ready( function() { 11349 * $('#example').dataTable( { 11350 * "language": { 11351 * "paginate": { 11352 * "first": "First page" 11353 * } 11354 * } 11355 * } ); 11356 * } ); 11357 */ 11358 "sFirst": "First", 11359 11360 11361 /** 11362 * Text to use when using the 'full_numbers' type of pagination for the 11363 * button to take the user to the last page. 11364 * @type string 11365 * @default Last 11366 * 11367 * @dtopt Language 11368 * @name DataTable.defaults.language.paginate.last 11369 * 11370 * @example 11371 * $(document).ready( function() { 11372 * $('#example').dataTable( { 11373 * "language": { 11374 * "paginate": { 11375 * "last": "Last page" 11376 * } 11377 * } 11378 * } ); 11379 * } ); 11380 */ 11381 "sLast": "Last", 11382 11383 11384 /** 11385 * Text to use for the 'next' pagination button (to take the user to the 11386 * next page). 11387 * @type string 11388 * @default Next 11389 * 11390 * @dtopt Language 11391 * @name DataTable.defaults.language.paginate.next 11392 * 11393 * @example 11394 * $(document).ready( function() { 11395 * $('#example').dataTable( { 11396 * "language": { 11397 * "paginate": { 11398 * "next": "Next page" 11399 * } 11400 * } 11401 * } ); 11402 * } ); 11403 */ 11404 "sNext": "Next", 11405 11406 11407 /** 11408 * Text to use for the 'previous' pagination button (to take the user to 11409 * the previous page). 11410 * @type string 11411 * @default Previous 11412 * 11413 * @dtopt Language 11414 * @name DataTable.defaults.language.paginate.previous 11415 * 11416 * @example 11417 * $(document).ready( function() { 11418 * $('#example').dataTable( { 11419 * "language": { 11420 * "paginate": { 11421 * "previous": "Previous page" 11422 * } 11423 * } 11424 * } ); 11425 * } ); 11426 */ 11427 "sPrevious": "Previous" 11428 }, 11429 11430 /** 11431 * This string is shown in preference to `zeroRecords` when the table is 11432 * empty of data (regardless of filtering). Note that this is an optional 11433 * parameter - if it is not given, the value of `zeroRecords` will be used 11434 * instead (either the default or given value). 11435 * @type string 11436 * @default No data available in table 11437 * 11438 * @dtopt Language 11439 * @name DataTable.defaults.language.emptyTable 11440 * 11441 * @example 11442 * $(document).ready( function() { 11443 * $('#example').dataTable( { 11444 * "language": { 11445 * "emptyTable": "No data available in table" 11446 * } 11447 * } ); 11448 * } ); 11449 */ 11450 "sEmptyTable": "No data available in table", 11451 11452 11453 /** 11454 * This string gives information to the end user about the information 11455 * that is current on display on the page. The following tokens can be 11456 * used in the string and will be dynamically replaced as the table 11457 * display updates. This tokens can be placed anywhere in the string, or 11458 * removed as needed by the language requires: 11459 * 11460 * * `\_START\_` - Display index of the first record on the current page 11461 * * `\_END\_` - Display index of the last record on the current page 11462 * * `\_TOTAL\_` - Number of records in the table after filtering 11463 * * `\_MAX\_` - Number of records in the table without filtering 11464 * * `\_PAGE\_` - Current page number 11465 * * `\_PAGES\_` - Total number of pages of data in the table 11466 * 11467 * @type string 11468 * @default Showing _START_ to _END_ of _TOTAL_ entries 11469 * 11470 * @dtopt Language 11471 * @name DataTable.defaults.language.info 11472 * 11473 * @example 11474 * $(document).ready( function() { 11475 * $('#example').dataTable( { 11476 * "language": { 11477 * "info": "Showing page _PAGE_ of _PAGES_" 11478 * } 11479 * } ); 11480 * } ); 11481 */ 11482 "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries", 11483 11484 11485 /** 11486 * Display information string for when the table is empty. Typically the 11487 * format of this string should match `info`. 11488 * @type string 11489 * @default Showing 0 to 0 of 0 entries 11490 * 11491 * @dtopt Language 11492 * @name DataTable.defaults.language.infoEmpty 11493 * 11494 * @example 11495 * $(document).ready( function() { 11496 * $('#example').dataTable( { 11497 * "language": { 11498 * "infoEmpty": "No entries to show" 11499 * } 11500 * } ); 11501 * } ); 11502 */ 11503 "sInfoEmpty": "Showing 0 to 0 of 0 entries", 11504 11505 11506 /** 11507 * When a user filters the information in a table, this string is appended 11508 * to the information (`info`) to give an idea of how strong the filtering 11509 * is. The variable _MAX_ is dynamically updated. 11510 * @type string 11511 * @default (filtered from _MAX_ total entries) 11512 * 11513 * @dtopt Language 11514 * @name DataTable.defaults.language.infoFiltered 11515 * 11516 * @example 11517 * $(document).ready( function() { 11518 * $('#example').dataTable( { 11519 * "language": { 11520 * "infoFiltered": " - filtering from _MAX_ records" 11521 * } 11522 * } ); 11523 * } ); 11524 */ 11525 "sInfoFiltered": "(filtered from _MAX_ total entries)", 11526 11527 11528 /** 11529 * If can be useful to append extra information to the info string at times, 11530 * and this variable does exactly that. This information will be appended to 11531 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are 11532 * being used) at all times. 11533 * @type string 11534 * @default <i>Empty string</i> 11535 * 11536 * @dtopt Language 11537 * @name DataTable.defaults.language.infoPostFix 11538 * 11539 * @example 11540 * $(document).ready( function() { 11541 * $('#example').dataTable( { 11542 * "language": { 11543 * "infoPostFix": "All records shown are derived from real information." 11544 * } 11545 * } ); 11546 * } ); 11547 */ 11548 "sInfoPostFix": "", 11549 11550 11551 /** 11552 * This decimal place operator is a little different from the other 11553 * language options since DataTables doesn't output floating point 11554 * numbers, so it won't ever use this for display of a number. Rather, 11555 * what this parameter does is modify the sort methods of the table so 11556 * that numbers which are in a format which has a character other than 11557 * a period (`.`) as a decimal place will be sorted numerically. 11558 * 11559 * Note that numbers with different decimal places cannot be shown in 11560 * the same table and still be sortable, the table must be consistent. 11561 * However, multiple different tables on the page can use different 11562 * decimal place characters. 11563 * @type string 11564 * @default 11565 * 11566 * @dtopt Language 11567 * @name DataTable.defaults.language.decimal 11568 * 11569 * @example 11570 * $(document).ready( function() { 11571 * $('#example').dataTable( { 11572 * "language": { 11573 * "decimal": "," 11574 * "thousands": "." 11575 * } 11576 * } ); 11577 * } ); 11578 */ 11579 "sDecimal": "", 11580 11581 11582 /** 11583 * DataTables has a build in number formatter (`formatNumber`) which is 11584 * used to format large numbers that are used in the table information. 11585 * By default a comma is used, but this can be trivially changed to any 11586 * character you wish with this parameter. 11587 * @type string 11588 * @default , 11589 * 11590 * @dtopt Language 11591 * @name DataTable.defaults.language.thousands 11592 * 11593 * @example 11594 * $(document).ready( function() { 11595 * $('#example').dataTable( { 11596 * "language": { 11597 * "thousands": "'" 11598 * } 11599 * } ); 11600 * } ); 11601 */ 11602 "sThousands": ",", 11603 11604 11605 /** 11606 * Detail the action that will be taken when the drop down menu for the 11607 * pagination length option is changed. The '_MENU_' variable is replaced 11608 * with a default select list of 10, 25, 50 and 100, and can be replaced 11609 * with a custom select box if required. 11610 * @type string 11611 * @default Show _MENU_ entries 11612 * 11613 * @dtopt Language 11614 * @name DataTable.defaults.language.lengthMenu 11615 * 11616 * @example 11617 * // Language change only 11618 * $(document).ready( function() { 11619 * $('#example').dataTable( { 11620 * "language": { 11621 * "lengthMenu": "Display _MENU_ records" 11622 * } 11623 * } ); 11624 * } ); 11625 * 11626 * @example 11627 * // Language and options change 11628 * $(document).ready( function() { 11629 * $('#example').dataTable( { 11630 * "language": { 11631 * "lengthMenu": 'Display <select>'+ 11632 * '<option value="10">10</option>'+ 11633 * '<option value="20">20</option>'+ 11634 * '<option value="30">30</option>'+ 11635 * '<option value="40">40</option>'+ 11636 * '<option value="50">50</option>'+ 11637 * '<option value="-1">All</option>'+ 11638 * '</select> records' 11639 * } 11640 * } ); 11641 * } ); 11642 */ 11643 "sLengthMenu": "Show _MENU_ entries", 11644 11645 11646 /** 11647 * When using Ajax sourced data and during the first draw when DataTables is 11648 * gathering the data, this message is shown in an empty row in the table to 11649 * indicate to the end user the the data is being loaded. Note that this 11650 * parameter is not used when loading data by server-side processing, just 11651 * Ajax sourced data with client-side processing. 11652 * @type string 11653 * @default Loading... 11654 * 11655 * @dtopt Language 11656 * @name DataTable.defaults.language.loadingRecords 11657 * 11658 * @example 11659 * $(document).ready( function() { 11660 * $('#example').dataTable( { 11661 * "language": { 11662 * "loadingRecords": "Please wait - loading..." 11663 * } 11664 * } ); 11665 * } ); 11666 */ 11667 "sLoadingRecords": "Loading...", 11668 11669 11670 /** 11671 * Text which is displayed when the table is processing a user action 11672 * (usually a sort command or similar). 11673 * @type string 11674 *
11674 @default Processing... 11675 * 11676 * @dtopt Language 11677 * @name DataTable.defaults.language.processing 11678 * 11679 * @example 11680 * $(document).ready( function() { 11681 * $('#example').dataTable( { 11682 * "language": { 11683 * "processing": "DataTables is currently busy" 11684 * } 11685 * } ); 11686 * } ); 11687 */ 11688 "sProcessing": "Processing...
vendor: 42,942 bytes, lines 11688-12982
11688", 11689 11690 11691 /** 11692 * Details the actions that will be taken when the user types into the 11693 * filtering input text box. The variable "_INPUT_", if used in the string, 11694 * is replaced with the HTML text box for the filtering input allowing 11695 * control over where it appears in the string. If "_INPUT_" is not given 11696 * then the input box is appended to the string automatically. 11697 * @type string 11698 * @default Search: 11699 * 11700 * @dtopt Language 11701 * @name DataTable.defaults.language.search 11702 * 11703 * @example 11704 * // Input text box will be appended at the end automatically 11705 * $(document).ready( function() { 11706 * $('#example').dataTable( { 11707 * "language": { 11708 * "search": "Filter records:" 11709 * } 11710 * } ); 11711 * } ); 11712 * 11713 * @example 11714 * // Specify where the filter should appear 11715 * $(document).ready( function() { 11716 * $('#example').dataTable( { 11717 * "language": { 11718 * "search": "Apply filter _INPUT_ to table" 11719 * } 11720 * } ); 11721 * } ); 11722 */ 11723 "sSearch": "Search:", 11724 11725 11726 /** 11727 * Assign a `placeholder` attribute to the search `input` element 11728 * @type string 11729 * @default 11730 * 11731 * @dtopt Language 11732 * @name DataTable.defaults.language.searchPlaceholder 11733 */ 11734 "sSearchPlaceholder": "", 11735 11736 11737 /** 11738 * All of the language information can be stored in a file on the 11739 * server-side, which DataTables will look up if this parameter is passed. 11740 * It must store the URL of the language file, which is in a JSON format, 11741 * and the object has the same properties as the oLanguage object in the 11742 * initialiser object (i.e. the above parameters). Please refer to one of 11743 * the example language files to see how this works in action. 11744 * @type string 11745 * @default <i>Empty string - i.e. disabled</i> 11746 * 11747 * @dtopt Language 11748 * @name DataTable.defaults.language.url 11749 * 11750 * @example 11751 * $(document).ready( function() { 11752 * $('#example').dataTable( { 11753 * "language": { 11754 * "url": "http://www.sprymedia.co.uk/dataTables/lang.txt" 11755 * } 11756 * } ); 11757 * } ); 11758 */ 11759 "sUrl": "", 11760 11761 11762 /** 11763 * Text shown inside the table records when the is no information to be 11764 * displayed after filtering. `emptyTable` is shown when there is simply no 11765 * information in the table at all (regardless of filtering). 11766 * @type string 11767 * @default No matching records found 11768 * 11769 * @dtopt Language 11770 * @name DataTable.defaults.language.zeroRecords 11771 * 11772 * @example 11773 * $(document).ready( function() { 11774 * $('#example').dataTable( { 11775 * "language": { 11776 * "zeroRecords": "No records to display" 11777 * } 11778 * } ); 11779 * } ); 11780 */ 11781 "sZeroRecords": "No matching records found" 11782 }, 11783 11784 11785 /** 11786 * This parameter allows you to have define the global filtering state at 11787 * initialisation time. As an object the `search` parameter must be 11788 * defined, but all other parameters are optional. When `regex` is true, 11789 * the search string will be treated as a regular expression, when false 11790 * (default) it will be treated as a straight string. When `smart` 11791 * DataTables will use it's smart filtering methods (to word match at 11792 * any point in the data), when false this will not be done. 11793 * @namespace 11794 * @extends DataTable.models.oSearch 11795 * 11796 * @dtopt Options 11797 * @name DataTable.defaults.search 11798 * 11799 * @example 11800 * $(document).ready( function() { 11801 * $('#example').dataTable( { 11802 * "search": {"search": "Initial search"} 11803 * } ); 11804 * } ) 11805 */ 11806 "oSearch": $.extend( {}, DataTable.models.oSearch ), 11807 11808 11809 /** 11810 * __Deprecated__ The functionality provided by this parameter has now been 11811 * superseded by that provided through `ajax`, which should be used instead. 11812 * 11813 * By default DataTables will look for the property `data` (or `aaData` for 11814 * compatibility with DataTables 1.9-) when obtaining data from an Ajax 11815 * source or for server-side processing - this parameter allows that 11816 * property to be changed. You can use Javascript dotted object notation to 11817 * get a data source for multiple levels of nesting. 11818 * @type string 11819 * @default data 11820 * 11821 * @dtopt Options 11822 * @dtopt Server-side 11823 * @name DataTable.defaults.ajaxDataProp 11824 * 11825 * @deprecated 1.10. Please use `ajax` for this functionality now. 11826 */ 11827 "sAjaxDataProp": "data", 11828 11829 11830 /** 11831 * __Deprecated__ The functionality provided by this parameter has now been 11832 * superseded by that provided through `ajax`, which should be used instead. 11833 * 11834 * You can instruct DataTables to load data from an external 11835 * source using this parameter (use aData if you want to pass data in you 11836 * already have). Simply provide a url a JSON object can be obtained from. 11837 * @type string 11838 * @default null 11839 * 11840 * @dtopt Options 11841 * @dtopt Server-side 11842 * @name DataTable.defaults.ajaxSource 11843 * 11844 * @deprecated 1.10. Please use `ajax` for this functionality now. 11845 */ 11846 "sAjaxSource": null, 11847 11848 11849 /** 11850 * This initialisation variable allows you to specify exactly where in the 11851 * DOM you want DataTables to inject the various controls it adds to the page 11852 * (for example you might want the pagination controls at the top of the 11853 * table). DIV elements (with or without a custom class) can also be added to 11854 * aid styling. The follow syntax is used: 11855 * <ul> 11856 * <li>The following options are allowed: 11857 * <ul> 11858 * <li>'l' - Length changing</li> 11859 * <li>'f' - Filtering input</li> 11860 * <li>'t' - The table!</li> 11861 * <li>'i' - Information</li> 11862 * <li>'p' - Pagination</li> 11863 * <li>'r' - pRocessing</li> 11864 * </ul> 11865 * </li> 11866 * <li>The following constants are allowed: 11867 * <ul> 11868 * <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li> 11869 * <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li> 11870 * </ul> 11871 * </li> 11872 * <li>The following syntax is expected: 11873 * <ul> 11874 * <li>'<' and '>' - div elements</li> 11875 * <li>'<"class" and '>' - div with a class</li> 11876 * <li>'<"#id" and '>' - div with an ID</li> 11877 * </ul> 11878 * </li> 11879 * <li>Examples: 11880 * <ul> 11881 * <li>'<"wrapper"flipt>'</li> 11882 * <li>'<lf<t>ip>'</li> 11883 * </ul> 11884 * </li> 11885 * </ul> 11886 * @type string 11887 * @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b> 11888 * <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i> 11889 * 11890 * @dtopt Options 11891 * @name DataTable.defaults.dom 11892 * 11893 * @example 11894 * $(document).ready( function() { 11895 * $('#example').dataTable( { 11896 * "dom": '<"top"i>rt<"bottom"flp><"clear">' 11897 * } ); 11898 * } ); 11899 */ 11900 "sDom": "lfrtip", 11901 11902 11903 /** 11904 * Search delay option. This will throttle full table searches that use the 11905 * DataTables provided search input element (it does not effect calls to 11906 * `dt-api search()`, providing a delay before the search is made. 11907 * @type integer 11908 * @default 0 11909 * 11910 * @dtopt Options 11911 * @name DataTable.defaults.searchDelay 11912 * 11913 * @example 11914 * $(document).ready( function() { 11915 * $('#example').dataTable( { 11916 * "searchDelay": 200 11917 * } ); 11918 * } ) 11919 */ 11920 "searchDelay": null, 11921 11922 11923 /** 11924 * DataTables features six different built-in options for the buttons to 11925 * display for pagination control: 11926 * 11927 * * `numbers` - Page number buttons only 11928 * * `simple` - 'Previous' and 'Next' buttons only 11929 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers 11930 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons 11931 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers 11932 * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers 11933 * 11934 * Further methods can be added using {@link DataTable.ext.oPagination}. 11935 * @type string 11936 * @default simple_numbers 11937 * 11938 * @dtopt Options 11939 * @name DataTable.defaults.pagingType 11940 * 11941 * @example 11942 * $(document).ready( function() { 11943 * $('#example').dataTable( { 11944 * "pagingType": "full_numbers" 11945 * } ); 11946 * } ) 11947 */ 11948 "sPaginationType": "simple_numbers", 11949 11950 11951 /** 11952 * Enable horizontal scrolling. When a table is too wide to fit into a 11953 * certain layout, or you have a large number of columns in the table, you 11954 * can enable x-scrolling to show the table in a viewport, which can be 11955 * scrolled. This property can be `true` which will allow the table to 11956 * scroll horizontally when needed, or any CSS unit, or a number (in which 11957 * case it will be treated as a pixel measurement). Setting as simply `true` 11958 * is recommended. 11959 * @type boolean|string 11960 * @default <i>blank string - i.e. disabled</i> 11961 * 11962 * @dtopt Features 11963 * @name DataTable.defaults.scrollX 11964 * 11965 * @example 11966 * $(document).ready( function() { 11967 * $('#example').dataTable( { 11968 * "scrollX": true, 11969 * "scrollCollapse": true 11970 * } ); 11971 * } ); 11972 */ 11973 "sScrollX": "", 11974 11975 11976 /** 11977 * This property can be used to force a DataTable to use more width than it 11978 * might otherwise do when x-scrolling is enabled. For example if you have a 11979 * table which requires to be well spaced, this parameter is useful for 11980 * "over-sizing" the table, and thus forcing scrolling. This property can by 11981 * any CSS unit, or a number (in which case it will be treated as a pixel 11982 * measurement). 11983 * @type string 11984 * @default <i>blank string - i.e. disabled</i> 11985 * 11986 * @dtopt Options 11987 * @name DataTable.defaults.scrollXInner 11988 * 11989 * @example 11990 * $(document).ready( function() { 11991 * $('#example').dataTable( { 11992 * "scrollX": "100%", 11993 * "scrollXInner": "110%" 11994 * } ); 11995 * } ); 11996 */ 11997 "sScrollXInner": "", 11998 11999 12000 /** 12001 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable 12002 * to the given height, and enable scrolling for any data which overflows the 12003 * current viewport. This can be used as an alternative to paging to display 12004 * a lot of data in a small area (although paging and scrolling can both be 12005 * enabled at the same time). This property can be any CSS unit, or a number 12006 * (in which case it will be treated as a pixel measurement). 12007 * @type string 12008 * @default <i>blank string - i.e. disabled</i> 12009 * 12010 * @dtopt Features 12011 * @name DataTable.defaults.scrollY 12012 * 12013 * @example 12014 * $(document).ready( function() { 12015 * $('#example').dataTable( { 12016 * "scrollY": "200px", 12017 * "paginate": false 12018 * } ); 12019 * } ); 12020 */ 12021 "sScrollY": "", 12022 12023 12024 /** 12025 * __Deprecated__ The functionality provided by this parameter has now been 12026 * superseded by that provided through `ajax`, which should be used instead. 12027 * 12028 * Set the HTTP method that is used to make the Ajax call for server-side 12029 * processing or Ajax sourced data. 12030 * @type string 12031 * @default GET 12032 * 12033 * @dtopt Options 12034 * @dtopt Server-side 12035 * @name DataTable.defaults.serverMethod 12036 * 12037 * @deprecated 1.10. Please use `ajax` for this functionality now. 12038 */ 12039 "sServerMethod": "GET", 12040 12041 12042 /** 12043 * DataTables makes use of renderers when displaying HTML elements for 12044 * a table. These renderers can be added or modified by plug-ins to 12045 * generate suitable mark-up for a site. For example the Bootstrap 12046 * integration plug-in for DataTables uses a paging button renderer to 12047 * display pagination buttons in the mark-up required by Bootstrap. 12048 * 12049 * For further information about the renderers available see 12050 * DataTable.ext.renderer 12051 * @type string|object 12052 * @default null 12053 * 12054 * @name DataTable.defaults.renderer 12055 * 12056 */ 12057 "renderer": null, 12058 12059 12060 /** 12061 * Set the data property name that DataTables should use to get a row's id 12062 * to set as the `id` property in the node. 12063 * @type string 12064 * @default DT_RowId 12065 * 12066 * @name DataTable.defaults.rowId 12067 */ 12068 "rowId": "DT_RowId" 12069 }; 12070 12071 _fnHungarianMap( DataTable.defaults ); 12072 12073 12074 12075 /* 12076 * Developer note - See note in model.defaults.js about the use of Hungarian 12077 * notation and camel case. 12078 */ 12079 12080 /** 12081 * Column options that can be given to DataTables at initialisation time. 12082 * @namespace 12083 */ 12084 DataTable.defaults.column = { 12085 /** 12086 * Define which column(s) an order will occur on for this column. This 12087 * allows a column's ordering to take multiple columns into account when 12088 * doing a sort or use the data from a different column. For example first 12089 * name / last name columns make sense to do a multi-column sort over the 12090 * two columns. 12091 * @type array|int 12092 * @default null <i>Takes the value of the column index automatically</i> 12093 * 12094 * @name DataTable.defaults.column.orderData 12095 * @dtopt Columns 12096 * 12097 * @example 12098 * // Using `columnDefs` 12099 * $(document).ready( function() { 12100 * $('#example').dataTable( { 12101 * "columnDefs": [ 12102 * { "orderData": [ 0, 1 ], "targets": [ 0 ] }, 12103 * { "orderData": [ 1, 0 ], "targets": [ 1 ] }, 12104 * { "orderData": 2, "targets": [ 2 ] } 12105 * ] 12106 * } ); 12107 * } ); 12108 * 12109 * @example 12110 * // Using `columns` 12111 * $(document).ready( function() { 12112 * $('#example').dataTable( { 12113 * "columns": [ 12114 * { "orderData": [ 0, 1 ] }, 12115 * { "orderData": [ 1, 0 ] }, 12116 * { "orderData": 2 }, 12117 * null, 12118 * null 12119 * ] 12120 * } ); 12121 * } ); 12122 */ 12123 "aDataSort": null, 12124 "iDataSort": -1, 12125 12126 12127 /** 12128 * You can control the default ordering direction, and even alter the 12129 * behaviour of the sort handler (i.e. only allow ascending ordering etc) 12130 * using this parameter. 12131 * @type array 12132 * @default [ 'asc', 'desc' ] 12133 * 12134 * @name DataTable.defaults.column.orderSequence 12135 * @dtopt Columns 12136 * 12137 * @example 12138 * // Using `columnDefs` 12139 * $(document).ready( function() { 12140 * $('#example').dataTable( { 12141 * "columnDefs": [ 12142 * { "orderSequence": [ "asc" ], "targets": [ 1 ] }, 12143 * { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] }, 12144 * { "orderSequence": [ "desc" ], "targets": [ 3 ] } 12145 * ] 12146 * } ); 12147 * } ); 12148 * 12149 * @example 12150 * // Using `columns` 12151 * $(document).ready( function() { 12152 * $('#example').dataTable( { 12153 * "columns": [ 12154 * null, 12155 * { "orderSequence": [ "asc" ] }, 12156 * { "orderSequence": [ "desc", "asc", "asc" ] }, 12157 * { "orderSequence": [ "desc" ] }, 12158 * null 12159 * ] 12160 * } ); 12161 * } ); 12162 */ 12163 "asSorting": [ 'asc', 'desc' ], 12164 12165 12166 /** 12167 * Enable or disable filtering on the data in this column. 12168 * @type boolean 12169 * @default true 12170 * 12171 * @name DataTable.defaults.column.searchable 12172 * @dtopt Columns 12173 * 12174 * @example 12175 * // Using `columnDefs` 12176 * $(document).ready( function() { 12177 * $('#example').dataTable( { 12178 * "columnDefs": [ 12179 * { "searchable": false, "targets": [ 0 ] } 12180 * ] } ); 12181 * } ); 12182 * 12183 * @example 12184 * // Using `columns` 12185 * $(document).ready( function() { 12186 * $('#example').dataTable( { 12187 * "columns": [ 12188 * { "searchable": false }, 12189 * null, 12190 * null, 12191 * null, 12192 * null 12193 * ] } ); 12194 * } ); 12195 */ 12196 "bSearchable": true, 12197 12198 12199 /** 12200 * Enable or disable ordering on this column. 12201 * @type boolean 12202 * @default true 12203 * 12204 * @name DataTable.defaults.column.orderable 12205 * @dtopt Columns 12206 * 12207 * @example 12208 * // Using `columnDefs` 12209 * $(document).ready( function() { 12210 * $('#example').dataTable( { 12211 * "columnDefs": [ 12212 * { "orderable": false, "targets": [ 0 ] } 12213 * ] } ); 12214 * } ); 12215 * 12216 * @example 12217 * // Using `columns` 12218 * $(document).ready( function() { 12219 * $('#example').dataTable( { 12220 * "columns": [ 12221 * { "orderable": false }, 12222 * null, 12223 * null, 12224 * null, 12225 * null 12226 * ] } ); 12227 * } ); 12228 */ 12229 "bSortable": true, 12230 12231 12232 /** 12233 * Enable or disable the display of this column. 12234 * @type boolean 12235 * @default true 12236 * 12237 * @name DataTable.defaults.column.visible 12238 * @dtopt Columns 12239 * 12240 * @example 12241 * // Using `columnDefs` 12242 * $(document).ready( function() { 12243 * $('#example').dataTable( { 12244 * "columnDefs": [ 12245 * { "visible": false, "targets": [ 0 ] } 12246 * ] } ); 12247 * } ); 12248 * 12249 * @example 12250 * // Using `columns` 12251 * $(document).ready( function() { 12252 * $('#example').dataTable( { 12253 * "columns": [ 12254 * { "visible": false }, 12255 * null, 12256 * null, 12257 * null, 12258 * null 12259 * ] } ); 12260 * } ); 12261 */ 12262 "bVisible": true, 12263 12264 12265 /** 12266 * Developer definable function that is called whenever a cell is created (Ajax source, 12267 * etc) or processed for input (DOM source). This can be used as a compliment to mRender 12268 * allowing you to modify the DOM element (add background colour for example) when the 12269 * element is available. 12270 * @type function 12271 * @param {element} td The TD node that has been created 12272 * @param {*} cellData The Data for the cell 12273 * @param {array|object} rowData The data for the whole row 12274 * @param {int} row The row index for the aoData data store 12275 * @param {int} col The column index for aoColumns 12276 * 12277 * @name DataTable.defaults.column.createdCell 12278 * @dtopt Columns 12279 * 12280 * @example 12281 * $(document).ready( function() { 12282 * $('#example').dataTable( { 12283 * "columnDefs": [ { 12284 * "targets": [3], 12285 * "createdCell": function (td, cellData, rowData, row, col) { 12286 * if ( cellData == "1.7" ) { 12287 * $(td).css('color', 'blue') 12288 * } 12289 * } 12290 * } ] 12291 * }); 12292 * } ); 12293 */ 12294 "fnCreatedCell": null, 12295 12296 12297 /** 12298 * This parameter has been replaced by `data` in DataTables to ensure naming 12299 * consistency. `dataProp` can still be used, as there is backwards 12300 * compatibility in DataTables for this option, but it is strongly 12301 * recommended that you use `data` in preference to `dataProp`. 12302 * @name DataTable.defaults.column.dataProp 12303 */ 12304 12305 12306 /** 12307 * This property can be used to read data from any data source property, 12308 * including deeply nested objects / properties. `data` can be given in a 12309 * number of different ways which effect its behaviour: 12310 * 12311 * * `integer` - treated as an array index for the data source. This is the 12312 * default that DataTables uses (incrementally increased for each column). 12313 * * `string` - read an object property from the data source. There are 12314 * three 'special' options that can be used in the string to alter how 12315 * DataTables reads the data from the source object: 12316 * * `.` - Dotted Javascript notation. Just as you use a `.` in 12317 * Javascript to read from nested objects, so to can the options 12318 * specified in `data`. For example: `browser.version` or 12319 * `browser.name`. If your object parameter name contains a period, use 12320 * `\\` to escape it - i.e. `first\\.name`. 12321 * * `[]` - Array notation. DataTables can automatically combine data 12322 * from and array source, joining the data with the characters provided 12323 * between the two brackets. For example: `name[, ]` would provide a 12324 * comma-space separated list from the source array. If no characters 12325 * are provided between the brackets, the original array source is 12326 * returned. 12327 * * `()` - Function notation. Adding `()` to the end of a parameter will 12328 * execute a function of the name given. For example: `browser()` for a 12329 * simple function on the data source, `browser.version()` for a 12330 * function in a nested property or even `browser().version` to get an 12331 * object property if the function called returns an object. Note that 12332 * function notation is recommended for use in `render` rather than 12333 * `data` as it is much simpler to use as a renderer. 12334 * * `null` - use the original data source for the row rather than plucking 12335 * data directly from it. This action has effects on two other 12336 * initialisation options: 12337 * * `defaultContent` - When null is given as the `data` option and 12338 * `defaultContent` is specified for the column, the value defined by 12339 * `defaultContent` will be used for the cell. 12340 * * `render` - When null is used for the `data` option and the `render` 12341 * option is specified for the column, the whole data source for the 12342 * row is used for the renderer. 12343 * * `function` - the function given will be executed whenever DataTables 12344 * needs to set or get the data for a cell in the column. The function 12345 * takes three parameters: 12346 * * Parameters: 12347 * * `{array|object}` The data source for the row 12348 * * `{string}` The type call data requested - this will be 'set' when 12349 * setting data or 'filter', 'display', 'type', 'sort' or undefined 12350 * when gathering data. Note that when `undefined` is given for the 12351 * type DataTables expects to get the raw data for the object back< 12352 * * `{*}` Data to set when the second parameter is 'set'. 12353 * * Return: 12354 * * The return value from the function is not required when 'set' is 12355 * the type of call, but otherwise the return is what will be used 12356 * for the data requested. 12357 * 12358 * Note that `data` is a getter and setter option. If you just require 12359 * formatting of data for output, you will likely want to use `render` which 12360 * is simply a getter and thus simpler to use. 12361 * 12362 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The 12363 * name change reflects the flexibility of this property and is consistent 12364 * with the naming of mRender. If 'mDataProp' is given, then it will still 12365 * be used by DataTables, as it automatically maps the old name to the new 12366 * if required. 12367 * 12368 * @type string|int|function|null 12369 * @default null <i>Use automatically calculated column index</i> 12370 * 12371 * @name DataTable.defaults.column.data 12372 * @dtopt Columns 12373 * 12374 * @example 12375 * // Read table data from objects 12376 * // JSON structure for each row: 12377 * // { 12378 * // "engine": {value}, 12379 * // "browser": {value}, 12380 * // "platform": {value}, 12381 * // "version": {value}, 12382 * // "grade": {value} 12383 * // } 12384 * $(document).ready( function() { 12385 * $('#example').dataTable( { 12386 * "ajaxSource": "sources/objects.txt", 12387 * "columns": [ 12388 * { "data": "engine" }, 12389 * { "data": "browser" }, 12390 * { "data": "platform" }, 12391 * { "data": "version" }, 12392 * { "data": "grade" } 12393 * ] 12394 * } ); 12395 * } ); 12396 * 12397 * @example 12398 * // Read information from deeply nested objects 12399 * // JSON structure for each row: 12400 * // { 12401 * // "engine": {value}, 12402 * // "browser": {value}, 12403 * // "platform": { 12404 * // "inner": {value} 12405 * // }, 12406 * // "details": [ 12407 * // {value}, {value} 12408 * // ] 12409 * // } 12410 * $(document).ready( function() { 12411 * $('#example').dataTable( { 12412 * "ajaxSource": "sources/deep.txt", 12413 * "columns": [ 12414 * { "data": "engine" }, 12415 * { "data": "browser" }, 12416 * { "data": "platform.inner" }, 12417 * { "data": "details.0" }, 12418 * { "data": "details.1" } 12419 * ] 12420 * } ); 12421 * } ); 12422 * 12423 * @example 12424 * // Using `data` as a function to provide different information for 12425 * // sorting, filtering and display. In this case, currency (price) 12426 * $(document).ready( function() { 12427 * $('#example').dataTable( { 12428 * "columnDefs": [ { 12429 * "targets": [ 0 ], 12430 * "data": function ( source, type, val ) { 12431 * if (type === 'set') { 12432 * source.price = val; 12433 * // Store the computed dislay and filter values for efficiency 12434 * source.price_display = val=="" ? "" : "$"+numberFormat(val); 12435 * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val; 12436 * return; 12437 * } 12438 * else if (type === 'display') { 12439 * return source.price_display; 12440 * } 12441 * else if (type === 'filter') { 12442 * return source.price_filter; 12443 * } 12444 * // 'sort', 'type' and undefined all just use the integer 12445 * return source.price; 12446 * } 12447 * } ] 12448 * } ); 12449 * } ); 12450 * 12451 * @example 12452 * // Using default content 12453 * $(document).ready( function() { 12454 * $('#example').dataTable( { 12455 * "columnDefs": [ { 12456 * "targets": [ 0 ], 12457 * "data": null, 12458 * "defaultContent": "Click to edit" 12459 * } ] 12460 * } ); 12461 * } ); 12462 * 12463 * @example 12464 * // Using array notation - outputting a list from an array 12465 * $(document).ready( function() { 12466 * $('#example').dataTable( { 12467 * "columnDefs": [ { 12468 * "targets": [ 0 ], 12469 * "data": "name[, ]" 12470 * } ] 12471 * } ); 12472 * } ); 12473 * 12474 */ 12475 "mData": null, 12476 12477 12478 /** 12479 * This property is the rendering partner to `data` and it is suggested that 12480 * when you want to manipulate data for display (including filtering, 12481 * sorting etc) without altering the underlying data for the table, use this 12482 * property. `render` can be considered to be the the read only companion to 12483 * `data` which is read / write (then as such more complex). Like `data` 12484 * this option can be given in a number of different ways to effect its 12485 * behaviour: 12486 * 12487 * * `integer` - treated as an array index for the data source. This is the 12488 * default that DataTables uses (incrementally increased for each column). 12489 * * `string` - read an object property from the data source. There are 12490 * three 'special' options that can be used in the string to alter how 12491 * DataTables reads the data from the source object: 12492 * * `.` - Dotted Javascript notation. Just as you use a `.` in 12493 * Javascript to read from nested objects, so to can the options 12494 * specified in `data`. For example: `browser.version` or 12495 * `browser.name`. If your object parameter name contains a period, use 12496 * `\\` to escape it - i.e. `first\\.name`. 12497 * * `[]` - Array notation. DataTables can automatically combine data 12498 * from and array source, joining the data with the characters provided 12499 * between the two brackets. For example: `name[, ]` would provide a 12500 * comma-space separated list from the source array. If no characters 12501 * are provided between the brackets, the original array source is 12502 * returned. 12503 * * `()` - Function notation. Adding `()` to the end of a parameter will 12504 * execute a function of the name given. For example: `browser()` for a 12505 * simple function on the data source, `browser.version()` for a 12506 * function in a nested property or even `browser().version` to get an 12507 * object property if the function called returns an object. 12508 * * `object` - use different data for the different data types requested by 12509 * DataTables ('filter', 'display', 'type' or 'sort'). The property names 12510 * of the object is the data type the property refers to and the value can 12511 * defined using an integer, string or function using the same rules as 12512 * `render` normally does. Note that an `_` option _must_ be specified. 12513 * This is the default value to use if you haven't specified a value for 12514 * the data type requested by DataTables. 12515 * * `function` - the function given will be executed whenever DataTables 12516 * needs to set or get the data for a cell in the column. The function 12517 * takes three parameters: 12518 * * Parameters: 12519 * * {array|object} The data source for the row (based on `data`) 12520 * * {string} The type call data requested - this will be 'filter', 12521 * 'display', 'type' or 'sort'. 12522 * * {array|object} The full data source for the row (not based on 12523 * `data`) 12524 * * Return: 12525 * * The return value from the function is what will be used for the 12526 * data requested. 12527 * 12528 * @type string|int|function|object|null 12529 * @default null Use the data source value. 12530 * 12531 * @name DataTable.defaults.column.render 12532 * @dtopt Columns 12533 * 12534 * @example 12535 * // Create a comma separated list from an array of objects 12536 * $(document).ready( function() { 12537 * $('#example').dataTable( { 12538 * "ajaxSource": "sources/deep.txt", 12539 * "columns": [ 12540 * { "data": "engine" }, 12541 * { "data": "browser" }, 12542 * { 12543 * "data": "platform", 12544 * "render": "[, ].name" 12545 * } 12546 * ] 12547 * } ); 12548 * } ); 12549 * 12550 * @example 12551 * // Execute a function to obtain data 12552 * $(document).ready( function() { 12553 * $('#example').dataTable( { 12554 * "columnDefs": [ { 12555 * "targets": [ 0 ], 12556 * "data": null, // Use the full data source object for the renderer's source 12557 * "render": "browserName()" 12558 * } ] 12559 * } ); 12560 * } ); 12561 * 12562 * @example 12563 * // As an object, extracting different data for the different types 12564 * // This would be used with a data source such as: 12565 * // { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" } 12566 * // Here the `phone` integer is used for sorting and type detection, while `phone_filter` 12567 * // (which has both forms) is used for filtering for if a user inputs either format, while 12568 * // the formatted phone number is the one that is shown in the table. 12569 * $(document).ready( function() { 12570 * $('#example').dataTable( { 12571 * "columnDefs": [ { 12572 * "targets": [ 0 ], 12573 * "data": null, // Use the full data source object for the renderer's source 12574 * "render": { 12575 * "_": "phone", 12576 * "filter": "phone_filter", 12577 * "display": "phone_display" 12578 * } 12579 * } ] 12580 * } ); 12581 * } ); 12582 * 12583 * @example 12584 * // Use as a function to create a link from the data source 12585 * $(document).ready( function() { 12586 * $('#example').dataTable( { 12587 * "columnDefs": [ { 12588 * "targets": [ 0 ], 12589 * "data": "download_link", 12590 * "render": function ( data, type, full ) { 12591 * return '<a href="'+data+'">Download</a>'; 12592 * } 12593 * } ] 12594 * } ); 12595 * } ); 12596 */ 12597 "mRender": null, 12598 12599 12600 /** 12601 * Change the cell type created for the column - either TD cells or TH cells. This 12602 * can be useful as TH cells have semantic meaning in the table body, allowing them 12603 * to act as a header for a row (you may wish to add scope='row' to the TH elements). 12604 * @type string 12605 * @default td 12606 * 12607 * @name DataTable.defaults.column.cellType 12608 * @dtopt Columns 12609 * 12610 * @example 12611 * // Make the first column use TH cells 12612 * $(document).ready( function() { 12613 * $('#example').dataTable( { 12614 * "columnDefs": [ { 12615 * "targets": [ 0 ], 12616 * "cellType": "th" 12617 * } ] 12618 * } ); 12619 * } ); 12620 */ 12621 "sCellType": "td", 12622 12623 12624 /** 12625 * Class to give to each cell in this column. 12626 * @type string 12627 * @default <i>Empty string</i> 12628 * 12629 * @name DataTable.defaults.column.class 12630 * @dtopt Columns 12631 * 12632 * @example 12633 * // Using `columnDefs` 12634 * $(document).ready( function() { 12635 * $('#example').dataTable( { 12636 * "columnDefs": [ 12637 * { "class": "my_class", "targets": [ 0 ] } 12638 * ] 12639 * } ); 12640 * } ); 12641 * 12642 * @example 12643 * // Using `columns` 12644 * $(document).ready( function() { 12645 * $('#example').dataTable( { 12646 * "columns": [ 12647 * { "class": "my_class" }, 12648 * null, 12649 * null, 12650 * null, 12651 * null 12652 * ] 12653 * } ); 12654 * } ); 12655 */ 12656 "sClass": "", 12657 12658 /** 12659 * When DataTables calculates the column widths to assign to each column, 12660 * it finds the longest string in each column and then constructs a 12661 * temporary table and reads the widths from that. The problem with this 12662 * is that "mmm" is much wider then "iiii", but the latter is a longer 12663 * string - thus the calculation can go wrong (doing it properly and putting 12664 * it into an DOM object and measuring that is horribly(!) slow). Thus as 12665 * a "work around" we provide this option. It will append its value to the 12666 * text that is found to be the longest string for the column - i.e. padding. 12667 * Generally you shouldn't need this! 12668 * @type string 12669 * @default <i>Empty string<i> 12670 * 12671 * @name DataTable.defaults.column.contentPadding 12672 * @dtopt Columns 12673 * 12674 * @example 12675 * // Using `columns` 12676 * $(document).ready( function() { 12677 * $('#example').dataTable( { 12678 * "columns": [ 12679 * null, 12680 * null, 12681 * null, 12682 * { 12683 * "contentPadding": "mmm" 12684 * } 12685 * ] 12686 * } ); 12687 * } ); 12688 */ 12689 "sContentPadding": "", 12690 12691 12692 /** 12693 * Allows a default value to be given for a column's data, and will be used 12694 * whenever a null data source is encountered (this can be because `data` 12695 * is set to null, or because the data source itself is null). 12696 * @type string 12697 * @default null 12698 * 12699 * @name DataTable.defaults.column.defaultContent 12700 * @dtopt Columns 12701 * 12702 * @example 12703 * // Using `columnDefs` 12704 * $(document).ready( function() { 12705 * $('#example').dataTable( { 12706 * "columnDefs": [ 12707 * { 12708 * "data": null, 12709 * "defaultContent": "Edit", 12710 * "targets": [ -1 ] 12711 * } 12712 * ] 12713 * } ); 12714 * } ); 12715 * 12716 * @example 12717 * // Using `columns` 12718 * $(document).ready( function() { 12719 * $('#example').dataTable( { 12720 * "columns": [ 12721 * null, 12722 * null, 12723 * null, 12724 * { 12725 * "data": null, 12726 * "defaultContent": "Edit" 12727 * } 12728 * ] 12729 * } ); 12730 * } ); 12731 */ 12732 "sDefaultContent": null, 12733 12734 12735 /** 12736 * This parameter is only used in DataTables' server-side processing. It can 12737 * be exceptionally useful to know what columns are being displayed on the 12738 * client side, and to map these to database fields. When defined, the names 12739 * also allow DataTables to reorder information from the server if it comes 12740 * back in an unexpected order (i.e. if you switch your columns around on the 12741 * client-side, your server-side code does not also need updating). 12742 * @type string 12743 * @default <i>Empty string</i> 12744 * 12745 * @name DataTable.defaults.column.name 12746 * @dtopt Columns 12747 * 12748 * @example 12749 * // Using `columnDefs` 12750 * $(document).ready( function() { 12751 * $('#example').dataTable( { 12752 * "columnDefs": [ 12753 * { "name": "engine", "targets": [ 0 ] }, 12754 * { "name": "browser", "targets": [ 1 ] }, 12755 * { "name": "platform", "targets": [ 2 ] }, 12756 * { "name": "version", "targets": [ 3 ] }, 12757 * { "name": "grade", "targets": [ 4 ] } 12758 * ] 12759 * } ); 12760 * } ); 12761 * 12762 * @example 12763 * // Using `columns` 12764 * $(document).ready( function() { 12765 * $('#example').dataTable( { 12766 * "columns": [ 12767 * { "name": "engine" }, 12768 * { "name": "browser" }, 12769 * { "name": "platform" }, 12770 * { "name": "version" }, 12771 * { "name": "grade" } 12772 * ] 12773 * } ); 12774 * } ); 12775 */ 12776 "sName": "", 12777 12778 12779 /** 12780 * Defines a data source type for the ordering which can be used to read 12781 * real-time information from the table (updating the internally cached 12782 * version) prior to ordering. This allows ordering to occur on user 12783 * editable elements such as form inputs. 12784 * @type string 12785 * @default std 12786 * 12787 * @name DataTable.defaults.column.orderDataType 12788 * @dtopt Columns 12789 * 12790 * @example 12791 * // Using `columnDefs` 12792 * $(document).ready( function() { 12793 * $('#example').dataTable( { 12794 * "columnDefs": [ 12795 * { "orderDataType": "dom-text", "targets": [ 2, 3 ] }, 12796 * { "type": "numeric", "targets": [ 3 ] }, 12797 * { "orderDataType": "dom-select", "targets": [ 4 ] }, 12798 * { "orderDataType": "dom-checkbox", "targets": [ 5 ] } 12799 * ] 12800 * } ); 12801 * } ); 12802 * 12803 * @example 12804 * // Using `columns` 12805 * $(document).ready( function() { 12806 * $('#example').dataTable( { 12807 * "columns": [ 12808 * null, 12809 * null, 12810 * { "orderDataType": "dom-text" }, 12811 * { "orderDataType": "dom-text", "type": "numeric" }, 12812 * { "orderDataType": "dom-select" }, 12813 * { "orderDataType": "dom-checkbox" } 12814 * ] 12815 * } ); 12816 * } ); 12817 */ 12818 "sSortDataType": "std", 12819 12820 12821 /** 12822 * The title of this column. 12823 * @type string 12824 * @default null <i>Derived from the 'TH' value for this column in the 12825 * original HTML table.</i> 12826 * 12827 * @name DataTable.defaults.column.title 12828 * @dtopt Columns 12829 * 12830 * @example 12831 * // Using `columnDefs` 12832 * $(document).ready( function() { 12833 * $('#example').dataTable( { 12834 * "columnDefs": [ 12835 * { "title": "My column title", "targets": [ 0 ] } 12836 * ] 12837 * } ); 12838 * } ); 12839 * 12840 * @example 12841 * // Using `columns` 12842 * $(document).ready( function() { 12843 * $('#example').dataTable( { 12844 * "columns": [ 12845 * { "title": "My column title" }, 12846 * null, 12847 * null, 12848 * null, 12849 * null 12850 * ] 12851 * } ); 12852 * } ); 12853 */ 12854 "sTitle": null, 12855 12856 12857 /** 12858 * The type allows you to specify how the data for this column will be 12859 * ordered. Four types (string, numeric, date and html (which will strip 12860 * HTML tags before ordering)) are currently available. Note that only date 12861 * formats understood by Javascript's Date() object will be accepted as type 12862 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string', 12863 * 'numeric', 'date' or 'html' (by default). Further types can be adding 12864 * through plug-ins. 12865 * @type string 12866 * @default null <i>Auto-detected from raw data</i> 12867 * 12868 * @name DataTable.defaults.column.type 12869 * @dtopt Columns 12870 * 12871 * @example 12872 * // Using `columnDefs` 12873 * $(document).ready( function() { 12874 * $('#example').dataTable( { 12875 * "columnDefs": [ 12876 * { "type": "html", "targets": [ 0 ] } 12877 * ] 12878 * } ); 12879 * } ); 12880 * 12881 * @example 12882 * // Using `columns` 12883 * $(document).ready( function() { 12884 * $('#example').dataTable( { 12885 * "columns": [ 12886 * { "type": "html" }, 12887 * null, 12888 * null, 12889 * null, 12890 * null 12891 * ] 12892 * } ); 12893 * } ); 12894 */ 12895 "sType": null, 12896 12897 12898 /** 12899 * Defining the width of the column, this parameter may take any CSS value 12900 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not 12901 * been given a specific width through this interface ensuring that the table 12902 * remains readable. 12903 * @type string 12904 * @default null <i>Automatic</i> 12905 * 12906 * @name DataTable.defaults.column.width 12907 * @dtopt Columns 12908 * 12909 * @example 12910 * // Using `columnDefs` 12911 * $(document).ready( function() { 12912 * $('#example').dataTable( { 12913 * "columnDefs": [ 12914 * { "width": "20%", "targets": [ 0 ] } 12915 * ] 12916 * } ); 12917 * } ); 12918 * 12919 * @example 12920 * // Using `columns` 12921 * $(document).ready( function() { 12922 * $('#example').dataTable( { 12923 * "columns": [ 12924 * { "width": "20%" }, 12925 * null, 12926 * null, 12927 * null, 12928 * null 12929 * ] 12930 * } ); 12931 * } ); 12932 */ 12933 "sWidth": null 12934 }; 12935 12936 _fnHungarianMap( DataTable.defaults.column ); 12937 12938 12939 12940 /** 12941 * DataTables settings object - this holds all the information needed for a 12942 * given table, including configuration, data and current application of the 12943 * table options. DataTables does not have a single instance for each DataTable 12944 * with the settings attached to that instance, but rather instances of the 12945 * DataTable "class" are created on-the-fly as needed (typically by a 12946 * $().dataTable() call) and the settings object is then applied to that 12947 * instance. 12948 * 12949 * Note that this object is related to {@link DataTable.defaults} but this 12950 * one is the internal data store for DataTables's cache of columns. It should 12951 * NOT be manipulated outside of DataTables. Any configuration should be done 12952 * through the initialisation options. 12953 * @namespace 12954 * @todo Really should attach the settings object to individual instances so we 12955 * don't need to create new instances on each $().dataTable() call (if the 12956 * table already exists). It would also save passing oSettings around and 12957 * into every single function. However, this is a very significant 12958 * architecture change for DataTables and will almost certainly break 12959 * backwards compatibility with older installations. This is something that 12960 * will be done in 2.0. 12961 */ 12962 DataTable.models.oSettings = { 12963 /** 12964 * Primary features of DataTables and their enablement state. 12965 * @namespace 12966 */ 12967 "oFeatures": { 12968 12969 /** 12970 * Flag to say if DataTables should automatically try to calculate the 12971 * optimum table and columns widths (true) or not (false). 12972 * Note that this parameter will be set by the initialisation routine. To 12973 * set a default use {@link DataTable.defaults}. 12974 * @type boolean 12975 */ 12976 "bAutoWidth": null, 12977 12978 /** 12979 * Delay the creation of TR and TD elements until they are actually 12980 * needed by a driven page draw. This can give a significant speed 12981 * increase for Ajax source and Javascript source data, but makes no 12982 * difference at all f
12982ro
vendor: 14,836 bytes, lines 12982-13559
12982 DOM and server-side processing tables. 12983 * Note that this parameter will be set by the initialisation routine. To 12984 * set a default use {@link DataTable.defaults}. 12985 * @type boolean 12986 */ 12987 "bDeferRender": null, 12988 12989 /** 12990 * Enable filtering on the table or not. Note that if this is disabled 12991 * then there is no filtering at all on the table, including fnFilter. 12992 * To just remove the filtering input use sDom and remove the 'f' option. 12993 * Note that this parameter will be set by the initialisation routine. To 12994 * set a default use {@link DataTable.defaults}. 12995 * @type boolean 12996 */ 12997 "bFilter": null, 12998 12999 /** 13000 * Table information element (the 'Showing x of y records' div) enable 13001 * flag. 13002 * Note that this parameter will be set by the initialisation routine. To 13003 * set a default use {@link DataTable.defaults}. 13004 * @type boolean 13005 */ 13006 "bInfo": null, 13007 13008 /** 13009 * Present a user control allowing the end user to change the page size 13010 * when pagination is enabled. 13011 * Note that this parameter will be set by the initialisation routine. To 13012 * set a default use {@link DataTable.defaults}. 13013 * @type boolean 13014 */ 13015 "bLengthChange": null, 13016 13017 /** 13018 * Pagination enabled or not. Note that if this is disabled then length 13019 * changing must also be disabled. 13020 * Note that this parameter will be set by the initialisation routine. To 13021 * set a default use {@link DataTable.defaults}. 13022 * @type boolean 13023 */ 13024 "bPaginate": null, 13025 13026 /** 13027 * Processing indicator enable flag whenever DataTables is enacting a 13028 * user request - typically an Ajax request for server-side processing. 13029 * Note that this parameter will be set by the initialisation routine. To 13030 * set a default use {@link DataTable.defaults}. 13031 * @type boolean 13032 */ 13033 "bProcessing": null, 13034 13035 /** 13036 * Server-side processing enabled flag - when enabled DataTables will 13037 * get all data from the server for every draw - there is no filtering, 13038 * sorting or paging done on the client-side. 13039 * Note that this parameter will be set by the initialisation routine. To 13040 * set a default use {@link DataTable.defaults}. 13041 * @type boolean 13042 */ 13043 "bServerSide": null, 13044 13045 /** 13046 * Sorting enablement flag. 13047 * Note that this parameter will be set by the initialisation routine. To 13048 * set a default use {@link DataTable.defaults}. 13049 * @type boolean 13050 */ 13051 "bSort": null, 13052 13053 /** 13054 * Multi-column sorting 13055 * Note that this parameter will be set by the initialisation routine. To 13056 * set a default use {@link DataTable.defaults}. 13057 * @type boolean 13058 */ 13059 "bSortMulti": null, 13060 13061 /** 13062 * Apply a class to the columns which are being sorted to provide a 13063 * visual highlight or not. This can slow things down when enabled since 13064 * there is a lot of DOM interaction. 13065 * Note that this parameter will be set by the initialisation routine. To 13066 * set a default use {@link DataTable.defaults}. 13067 * @type boolean 13068 */ 13069 "bSortClasses": null, 13070 13071 /** 13072 * State saving enablement flag. 13073 * Note that this parameter will be set by the initialisation routine. To 13074 * set a default use {@link DataTable.defaults}. 13075 * @type boolean 13076 */ 13077 "bStateSave": null 13078 }, 13079 13080 13081 /** 13082 * Scrolling settings for a table. 13083 * @namespace 13084 */ 13085 "oScroll": { 13086 /** 13087 * When the table is shorter in height than sScrollY, collapse the 13088 * table container down to the height of the table (when true). 13089 * Note that this parameter will be set by the initialisation routine. To 13090 * set a default use {@link DataTable.defaults}. 13091 * @type boolean 13092 */ 13093 "bCollapse": null, 13094 13095 /** 13096 * Width of the scrollbar for the web-browser's platform. Calculated 13097 * during table initialisation. 13098 * @type int 13099 * @default 0 13100 */ 13101 "iBarWidth": 0, 13102 13103 /** 13104 * Viewport width for horizontal scrolling. Horizontal scrolling is 13105 * disabled if an empty string. 13106 * Note that this parameter will be set by the initialisation routine. To 13107 * set a default use {@link DataTable.defaults}. 13108 * @type string 13109 */ 13110 "sX": null, 13111 13112 /** 13113 * Width to expand the table to when using x-scrolling. Typically you 13114 * should not need to use this. 13115 * Note that this parameter will be set by the initialisation routine. To 13116 * set a default use {@link DataTable.defaults}. 13117 * @type string 13118 * @deprecated 13119 */ 13120 "sXInner": null, 13121 13122 /** 13123 * Viewport height for vertical scrolling. Vertical scrolling is disabled 13124 * if an empty string. 13125 * Note that this parameter will be set by the initialisation routine. To 13126 * set a default use {@link DataTable.defaults}. 13127 * @type string 13128 */ 13129 "sY": null 13130 }, 13131 13132 /** 13133 * Language information for the table. 13134 * @namespace 13135 * @extends DataTable.defaults.oLanguage 13136 */ 13137 "oLanguage": { 13138 /** 13139 * Information callback function. See 13140 * {@link DataTable.defaults.fnInfoCallback} 13141 * @type function 13142 * @default null 13143 */ 13144 "fnInfoCallback": null 13145 }, 13146 13147 /** 13148 * Browser support parameters 13149 * @namespace 13150 */ 13151 "oBrowser": { 13152 /** 13153 * Indicate if the browser incorrectly calculates width:100% inside a 13154 * scrolling element (IE6/7) 13155 * @type boolean 13156 * @default false 13157 */ 13158 "bScrollOversize": false, 13159 13160 /** 13161 * Determine if the vertical scrollbar is on the right or left of the 13162 * scrolling container - needed for rtl language layout, although not 13163 * all browsers move the scrollbar (Safari). 13164 * @type boolean 13165 * @default false 13166 */ 13167 "bScrollbarLeft": false, 13168 13169 /** 13170 * Flag for if `getBoundingClientRect` is fully supported or not 13171 * @type boolean 13172 * @default false 13173 */ 13174 "bBounding": false, 13175 13176 /** 13177 * Browser scrollbar width 13178 * @type integer 13179 * @default 0 13180 */ 13181 "barWidth": 0 13182 }, 13183 13184 13185 "ajax": null, 13186 13187 13188 /** 13189 * Array referencing the nodes which are used for the features. The 13190 * parameters of this object match what is allowed by sDom - i.e. 13191 * <ul> 13192 * <li>'l' - Length changing</li> 13193 * <li>'f' - Filtering input</li> 13194 * <li>'t' - The table!</li> 13195 * <li>'i' - Information</li> 13196 * <li>'p' - Pagination</li> 13197 * <li>'r' - pRocessing</li> 13198 * </ul> 13199 * @type array 13200 * @default [] 13201 */ 13202 "aanFeatures": [], 13203 13204 /** 13205 * Store data information - see {@link DataTable.models.oRow} for detailed 13206 * information. 13207 * @type array 13208 * @default [] 13209 */ 13210 "aoData": [], 13211 13212 /** 13213 * Array of indexes which are in the current display (after filtering etc) 13214 * @type array 13215 * @default [] 13216 */ 13217 "aiDisplay": [], 13218 13219 /** 13220 * Array of indexes for display - no filtering 13221 * @type array 13222 * @default [] 13223 */ 13224 "aiDisplayMaster": [], 13225 13226 /** 13227 * Map of row ids to data indexes 13228 * @type object 13229 * @default {} 13230 */ 13231 "aIds": {}, 13232 13233 /** 13234 * Store information about each column that is in use 13235 * @type array 13236 * @default [] 13237 */ 13238 "aoColumns": [], 13239 13240 /** 13241 * Store information about the table's header 13242 * @type array 13243 * @default [] 13244 */ 13245 "aoHeader": [], 13246 13247 /** 13248 * Store information about the table's footer 13249 * @type array 13250 * @default [] 13251 */ 13252 "aoFooter": [], 13253 13254 /** 13255 * Store the applied global search information in case we want to force a 13256 * research or compare the old search to a new one. 13257 * Note that this parameter will be set by the initialisation routine. To 13258 * set a default use {@link DataTable.defaults}. 13259 * @namespace 13260 * @extends DataTable.models.oSearch 13261 */ 13262 "oPreviousSearch": {}, 13263 13264 /** 13265 * Store the applied search for each column - see 13266 * {@link DataTable.models.oSearch} for the format that is used for the 13267 * filtering information for each column. 13268 * @type array 13269 * @default [] 13270 */ 13271 "aoPreSearchCols": [], 13272 13273 /** 13274 * Sorting that is applied to the table. Note that the inner arrays are 13275 * used in the following manner: 13276 * <ul> 13277 * <li>Index 0 - column number</li> 13278 * <li>Index 1 - current sorting direction</li> 13279 * </ul> 13280 * Note that this parameter will be set by the initialisation routine. To 13281 * set a default use {@link DataTable.defaults}. 13282 * @type array 13283 * @todo These inner arrays should really be objects 13284 */ 13285 "aaSorting": null, 13286 13287 /** 13288 * Sorting that is always applied to the table (i.e. prefixed in front of 13289 * aaSorting). 13290 * Note that this parameter will be set by the initialisation routine. To 13291 * set a default use {@link DataTable.defaults}. 13292 * @type array 13293 * @default [] 13294 */ 13295 "aaSortingFixed": [], 13296 13297 /** 13298 * Classes to use for the striping of a table. 13299 * Note that this parameter will be set by the initialisation routine. To 13300 * set a default use {@link DataTable.defaults}. 13301 * @type array 13302 * @default [] 13303 */ 13304 "asStripeClasses": null, 13305 13306 /** 13307 * If restoring a table - we should restore its striping classes as well 13308 * @type array 13309 * @default [] 13310 */ 13311 "asDestroyStripes": [], 13312 13313 /** 13314 * If restoring a table - we should restore its width 13315 * @type int 13316 * @default 0 13317 */ 13318 "sDestroyWidth": 0, 13319 13320 /** 13321 * Callback functions array for every time a row is inserted (i.e. on a draw). 13322 * @type array 13323 * @default [] 13324 */ 13325 "aoRowCallback": [], 13326 13327 /** 13328 * Callback functions for the header on each draw. 13329 * @type array 13330 * @default [] 13331 */ 13332 "aoHeaderCallback": [], 13333 13334 /** 13335 * Callback function for the footer on each draw. 13336 * @type array 13337 * @default [] 13338 */ 13339 "aoFooterCallback": [], 13340 13341 /** 13342 * Array of callback functions for draw callback functions 13343 * @type array 13344 * @default [] 13345 */ 13346 "aoDrawCallback": [], 13347 13348 /** 13349 * Array of callback functions for row created function 13350 * @type array 13351 * @default [] 13352 */ 13353 "aoRowCreatedCallback": [], 13354 13355 /** 13356 * Callback functions for just before the table is redrawn. A return of 13357 * false will be used to cancel the draw. 13358 * @type array 13359 * @default [] 13360 */ 13361 "aoPreDrawCallback": [], 13362 13363 /** 13364 * Callback functions for when the table has been initialised. 13365 * @type array 13366 * @default [] 13367 */ 13368 "aoInitComplete": [], 13369 13370 13371 /** 13372 * Callbacks for modifying the settings to be stored for state saving, prior to 13373 * saving state. 13374 * @type array 13375 * @default [] 13376 */ 13377 "aoStateSaveParams": [], 13378 13379 /** 13380 * Callbacks for modifying the settings that have been stored for state saving 13381 * prior to using the stored values to restore the state. 13382 * @type array 13383 * @default [] 13384 */ 13385 "aoStateLoadParams": [], 13386 13387 /** 13388 * Callbacks for operating on the settings object once the saved state has been 13389 * loaded 13390 * @type array 13391 * @default [] 13392 */ 13393 "aoStateLoaded": [], 13394 13395 /** 13396 * Cache the table ID for quick access 13397 * @type string 13398 * @default <i>Empty string</i> 13399 */ 13400 "sTableId": "", 13401 13402 /** 13403 * The TABLE node for the main table 13404 * @type node 13405 * @default null 13406 */ 13407 "nTable": null, 13408 13409 /** 13410 * Permanent ref to the thead element 13411 * @type node 13412 * @default null 13413 */ 13414 "nTHead": null, 13415 13416 /** 13417 * Permanent ref to the tfoot element - if it exists 13418 * @type node 13419 * @default null 13420 */ 13421 "nTFoot": null, 13422 13423 /** 13424 * Permanent ref to the tbody element 13425 * @type node 13426 * @default null 13427 */ 13428 "nTBody": null, 13429 13430 /** 13431 * Cache the wrapper node (contains all DataTables controlled elements) 13432 * @type node 13433 * @default null 13434 */ 13435 "nTableWrapper": null, 13436 13437 /** 13438 * Indicate if when using server-side processing the loading of data 13439 * should be deferred until the second draw. 13440 * Note that this parameter will be set by the initialisation routine. To 13441 * set a default use {@link DataTable.defaults}. 13442 * @type boolean 13443 * @default false 13444 */ 13445 "bDeferLoading": false, 13446 13447 /** 13448 * Indicate if all required information has been read in 13449 * @type boolean 13450 * @default false 13451 */ 13452 "bInitialised": false, 13453 13454 /** 13455 * Information about open rows. Each object in the array has the parameters 13456 * 'nTr' and 'nParent' 13457 * @type array 13458 * @default [] 13459 */ 13460 "aoOpenRows": [], 13461 13462 /** 13463 * Dictate the positioning of DataTables' control elements - see 13464 * {@link DataTable.model.oInit.sDom}. 13465 * Note that this parameter will be set by the initialisation routine. To 13466 * set a default use {@link DataTable.defaults}. 13467 * @type string 13468 * @default null 13469 */ 13470 "sDom": null, 13471 13472 /** 13473 * Search delay (in mS) 13474 * @type integer 13475 * @default null 13476 */ 13477 "searchDelay": null, 13478 13479 /** 13480 * Which type of pagination should be used. 13481 * Note that this parameter will be set by the initialisation routine. To 13482 * set a default use {@link DataTable.defaults}. 13483 * @type string 13484 * @default two_button 13485 */ 13486 "sPaginationType": "two_button", 13487 13488 /** 13489 * The state duration (for `stateSave`) in seconds. 13490 * Note that this parameter will be set by the initialisation routine. To 13491 * set a default use {@link DataTable.defaults}. 13492 * @type int 13493 * @default 0 13494 */ 13495 "iStateDuration": 0, 13496 13497 /** 13498 * Array of callback functions for state saving. Each array element is an 13499 * object with the following parameters: 13500 * <ul> 13501 * <li>function:fn - function to call. Takes two parameters, oSettings 13502 * and the JSON string to save that has been thus far created. Returns 13503 * a JSON string to be inserted into a json object 13504 * (i.e. '"param": [ 0, 1, 2]')</li> 13505 * <li>string:sName - name of callback</li> 13506 * </ul> 13507 * @type array 13508 * @default [] 13509 */ 13510 "aoStateSave": [], 13511 13512 /** 13513 * Array of callback functions for state loading. Each array element is an 13514 * object with the following parameters: 13515 * <ul> 13516 * <li>function:fn - function to call. Takes two parameters, oSettings 13517 * and the object stored. May return false to cancel state loading</li> 13518 * <li>string:sName - name of callback</li> 13519 * </ul> 13520 * @type array 13521 * @default [] 13522 */ 13523 "aoStateLoad": [], 13524 13525 /** 13526 * State that was saved. Useful for back reference 13527 * @type object 13528 * @default null 13529 */ 13530 "oSavedState": null, 13531 13532 /** 13533 * State that was loaded. Useful for back reference 13534 * @type object 13535 * @default null 13536 */ 13537 "oLoadedState": null, 13538 13539 /** 13540 * Source url for AJAX data for the table. 13541 * Note that this parameter will be set by the initialisation routine. To 13542 * set a default use {@link DataTable.defaults}. 13543 * @type string 13544 * @default null 13545 */ 13546 "sAjaxSource": null, 13547 13548 /** 13549 * Property from a given object from which to read the table data from. This 13550 * can be an empty string (when not server-side processing), in which case 13551 * it is assumed an an array is given directly. 13552 * Note that this parameter will be set by the initialisation routine. To 13553 * set a default use {@link DataTable.defaults}. 13554 * @type string 13555 */ 13556 "sAjaxDataProp": null, 13557 13558 /** 13559 *
13559Note if draw should be blocked while getting data 13560 * @type boolean 13561 * @default true 13562 */ 13563 "bAjaxDataGet": true, 13564 13565 /** 13566 * The last jQuery XHR object that was used for server-side data gathering. 13567 * This can be used for working with the XHR information in one of the 13568 * callbacks 13569 * @type object 13570 * @default null 13571 */ 13572 "jqXHR": null, 13573 13574 /** 13575 * JSON returned from the server in the last Ajax request 13576 * @type object 13577 * @default undefined 13578 */ 13579 "json": undefined, 13580 13581 /** 13582 * Data submitted as part of the last Ajax request 13583 * @type object 13584 * @default undefined 13585 */ 13586 "oAjaxData": undefined, 13587 13588 /** 13589 * Function to get the server-side data. 13590 * Note that this parameter will be set by the initialisation routine. To 13591 * set a default use {@link DataTable.defaults}. 13592 * @type function 13593 */ 13594 "fnServerData": null, 13595 13596 /** 13597 * Functions which are called prior to sending an Ajax request so extra 13598 * parameters can easily be sent to the server 13599 * @type array 13600 * @default [] 13601 */ 13602 "aoServerParams": [], 13603 13604 /** 13605 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if 13606 * required). 13607 * Note that this parameter will be set by the initialisation routine. To 13608 * set a default use {@link DataTable.defaults}. 13609 * @type string 13610 */ 13611 "sServerMethod": null, 13612 13613 /** 13614 * Format numbers for display. 13615 * Note that this parameter will be set by the initialisation routine. To 13616 * set a default use {@link DataTable.defaults}. 13617 * @type function 13618 */ 13619 "fnFormatNumber": null, 13620 13621 /** 13622 * List of options that can be used for the user selectable length menu. 13623 * Note that this parameter will be set by the initialisation routine. To 13624 * set a default use {@link DataTable.defaults}. 13625 * @type array 13626 * @default [] 13627 */ 13628 "aLengthMenu": null, 13629 13630 /** 13631 * Counter for the draws that the table does. Also used as a tracker for 13632 * server-side processing 13633 * @type int 13634 * @default 0 13635 */ 13636 "iDraw": 0, 13637 13638 /** 13639 * Indicate if a redraw is being done - useful for Ajax 13640 * @type boolean 13641 * @default false 13642 */ 13643 "bDrawing": false, 13644 13645 /** 13646 * Draw index (iDraw) of the last error when parsing the returned data 13647 * @type int 13648 * @default -1 13649 */ 13650 "iDrawError": -1, 13651 13652 /** 13653 * Paging display length 13654 * @type int 13655 * @default 10 13656 */ 13657 "_iDisplayLength": 10, 13658 13659 /** 13660 * Paging start point - aiDisplay index 13661 * @type int 13662 * @default 0 13663 */ 13664 "_iDisplayStart": 0, 13665 13666 /** 13667 * Server-side processing - number of records in the result set 13668 * (i.e. before filtering), Use fnRecordsTotal rather than 13669 * this property to get the value of the number of records, regardless of 13670 * the server-side processing setting. 13671 * @type int 13672 * @default 0 13673 * @private 13674 */ 13675 "_iRecordsTotal": 0, 13676 13677 /** 13678 * Server-side processing - number of records in the current display set 13679 * (i.e. after filtering). Use fnRecordsDisplay rather than 13680 * this property to get the value of the number of records, regardless of 13681 * the server-side processing setting. 13682 * @type boolean 13683 * @default 0 13684 * @private 13685 */ 13686 "_iRecordsDisplay": 0, 13687 13688 /** 13689 * The classes to use for the table 13690 * @type object 13691 * @default {} 13692 */
vendor: 4,822 bytes, lines 13693-13901
13693 "oClasses": {}, 13694 13695 /** 13696 * Flag attached to the settings object so you can check in the draw 13697 * callback if filtering has been done in the draw. Deprecated in favour of 13698 * events. 13699 * @type boolean 13700 * @default false 13701 * @deprecated 13702 */ 13703 "bFiltered": false, 13704 13705 /** 13706 * Flag attached to the settings object so you can check in the draw 13707 * callback if sorting has been done in the draw. Deprecated in favour of 13708 * events. 13709 * @type boolean 13710 * @default false 13711 * @deprecated 13712 */ 13713 "bSorted": false, 13714 13715 /** 13716 * Indicate that if multiple rows are in the header and there is more than 13717 * one unique cell per column, if the top one (true) or bottom one (false) 13718 * should be used for sorting / title by DataTables. 13719 * Note that this parameter will be set by the initialisation routine. To 13720 * set a default use {@link DataTable.defaults}. 13721 * @type boolean 13722 */ 13723 "bSortCellsTop": null, 13724 13725 /** 13726 * Initialisation object that is used for the table 13727 * @type object 13728 * @default null 13729 */ 13730 "oInit": null, 13731 13732 /** 13733 * Destroy callback functions - for plug-ins to attach themselves to the 13734 * destroy so they can clean up markup and events. 13735 * @type array 13736 * @default [] 13737 */ 13738 "aoDestroyCallback": [], 13739 13740 13741 /** 13742 * Get the number of records in the current record set, before filtering 13743 * @type function 13744 */ 13745 "fnRecordsTotal": function () 13746 { 13747 return _fnDataSource( this ) == 'ssp' ? 13748 this._iRecordsTotal * 1 : 13749 this.aiDisplayMaster.length; 13750 }, 13751 13752 /** 13753 * Get the number of records in the current record set, after filtering 13754 * @type function 13755 */ 13756 "fnRecordsDisplay": function () 13757 { 13758 return _fnDataSource( this ) == 'ssp' ? 13759 this._iRecordsDisplay * 1 : 13760 this.aiDisplay.length; 13761 }, 13762 13763 /** 13764 * Get the display end point - aiDisplay index 13765 * @type function 13766 */ 13767 "fnDisplayEnd": function () 13768 { 13769 var 13770 len = this._iDisplayLength, 13771 start = this._iDisplayStart, 13772 calc = start + len, 13773 records = this.aiDisplay.length, 13774 features = this.oFeatures, 13775 paginate = features.bPaginate; 13776 13777 if ( features.bServerSide ) { 13778 return paginate === false || len === -1 ? 13779 start + records : 13780 Math.min( start+len, this._iRecordsDisplay ); 13781 } 13782 else { 13783 return ! paginate || calc>records || len===-1 ? 13784 records : 13785 calc; 13786 } 13787 }, 13788 13789 /** 13790 * The DataTables object for this table 13791 * @type object 13792 * @default null 13793 */ 13794 "oInstance": null, 13795 13796 /** 13797 * Unique identifier for each instance of the DataTables object. If there 13798 * is an ID on the table node, then it takes that value, otherwise an 13799 * incrementing internal counter is used. 13800 * @type string 13801 * @default null 13802 */ 13803 "sInstance": null, 13804 13805 /** 13806 * tabindex attribute value that is added to DataTables control elements, allowing 13807 * keyboard navigation of the table and its controls. 13808 */ 13809 "iTabIndex": 0, 13810 13811 /** 13812 * DIV container for the footer scrolling table if scrolling 13813 */ 13814 "nScrollHead": null, 13815 13816 /** 13817 * DIV container for the footer scrolling table if scrolling 13818 */ 13819 "nScrollFoot": null, 13820 13821 /** 13822 * Last applied sort 13823 * @type array 13824 * @default [] 13825 */ 13826 "aLastSort": [], 13827 13828 /** 13829 * Stored plug-in instances 13830 * @type object 13831 * @default {} 13832 */ 13833 "oPlugins": {}, 13834 13835 /** 13836 * Function used to get a row's id from the row's data 13837 * @type function 13838 * @default null 13839 */ 13840 "rowIdFn": null, 13841 13842 /** 13843 * Data location where to store a row's id 13844 * @type string 13845 * @default null 13846 */ 13847 "rowId": null 13848 }; 13849 13850 /** 13851 * Extension object for DataTables that is used to provide all extension 13852 * options. 13853 * 13854 * Note that the `DataTable.ext` object is available through 13855 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is 13856 * also aliased to `jQuery.fn.dataTableExt` for historic reasons. 13857 * @namespace 13858 * @extends DataTable.models.ext 13859 */ 13860 13861 13862 /** 13863 * DataTables extensions 13864 * 13865 * This namespace acts as a collection area for plug-ins that can be used to 13866 * extend DataTables capabilities. Indeed many of the build in methods 13867 * use this method to provide their own capabilities (sorting methods for 13868 * example). 13869 * 13870 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy 13871 * reasons 13872 * 13873 * @namespace 13874 */ 13875 DataTable.ext = _ext = { 13876 /** 13877 * Buttons. For use with the Buttons extension for DataTables. This is 13878 * defined here so other extensions can define buttons regardless of load 13879 * order. It is _not_ used by DataTables core. 13880 * 13881 * @type object 13882 * @default {} 13883 */ 13884 buttons: {}, 13885 13886 13887 /** 13888 * Element class names 13889 * 13890 * @type object 13891 * @default {} 13892 */ 13893 classes: {}, 13894 13895 13896 /** 13897 * DataTables build type (expanded by the download builder) 13898 * 13899 * @type string 13900 */ 13901 build:"dt/dt-1.10.18
vendor: 15,138 bytes, lines 13901-14347
13901", 13902 13903 13904 /** 13905 * Error reporting. 13906 * 13907 * How should DataTables report an error. Can take the value 'alert', 13908 * 'throw', 'none' or a function. 13909 * 13910 * @type string|function 13911 * @default alert 13912 */ 13913 errMode: "alert", 13914 13915 13916 /** 13917 * Feature plug-ins. 13918 * 13919 * This is an array of objects which describe the feature plug-ins that are 13920 * available to DataTables. These feature plug-ins are then available for 13921 * use through the `dom` initialisation option. 13922 * 13923 * Each feature plug-in is described by an object which must have the 13924 * following properties: 13925 * 13926 * * `fnInit` - function that is used to initialise the plug-in, 13927 * * `cFeature` - a character so the feature can be enabled by the `dom` 13928 * instillation option. This is case sensitive. 13929 * 13930 * The `fnInit` function has the following input parameters: 13931 * 13932 * 1. `{object}` DataTables settings object: see 13933 * {@link DataTable.models.oSettings} 13934 * 13935 * And the following return is expected: 13936 * 13937 * * {node|null} The element which contains your feature. Note that the 13938 * return may also be void if your plug-in does not require to inject any 13939 * DOM elements into DataTables control (`dom`) - for example this might 13940 * be useful when developing a plug-in which allows table control via 13941 * keyboard entry 13942 * 13943 * @type array 13944 * 13945 * @example 13946 * $.fn.dataTable.ext.features.push( { 13947 * "fnInit": function( oSettings ) { 13948 * return new TableTools( { "oDTSettings": oSettings } ); 13949 * }, 13950 * "cFeature": "T" 13951 * } ); 13952 */ 13953 feature: [], 13954 13955 13956 /** 13957 * Row searching. 13958 * 13959 * This method of searching is complimentary to the default type based 13960 * searching, and a lot more comprehensive as it allows you complete control 13961 * over the searching logic. Each element in this array is a function 13962 * (parameters described below) that is called for every row in the table, 13963 * and your logic decides if it should be included in the searching data set 13964 * or not. 13965 * 13966 * Searching functions have the following input parameters: 13967 * 13968 * 1. `{object}` DataTables settings object: see 13969 * {@link DataTable.models.oSettings} 13970 * 2. `{array|object}` Data for the row to be processed (same as the 13971 * original format that was passed in as the data source, or an array 13972 * from a DOM data source 13973 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which 13974 * can be useful to retrieve the `TR` element if you need DOM interaction. 13975 * 13976 * And the following return is expected: 13977 * 13978 * * {boolean} Include the row in the searched result set (true) or not 13979 * (false) 13980 * 13981 * Note that as with the main search ability in DataTables, technically this 13982 * is "filtering", since it is subtractive. However, for consistency in 13983 * naming we call it searching here. 13984 * 13985 * @type array 13986 * @default [] 13987 * 13988 * @example 13989 * // The following example shows custom search being applied to the 13990 * // fourth column (i.e. the data[3] index) based on two input values 13991 * // from the end-user, matching the data in a certain range. 13992 * $.fn.dataTable.ext.search.push( 13993 * function( settings, data, dataIndex ) { 13994 * var min = document.getElementById('min').value * 1; 13995 * var max = document.getElementById('max').value * 1; 13996 * var version = data[3] == "-" ? 0 : data[3]*1; 13997 * 13998 * if ( min == "" && max == "" ) { 13999 * return true; 14000 * } 14001 * else if ( min == "" && version < max ) { 14002 * return true; 14003 * } 14004 * else if ( min < version && "" == max ) { 14005 * return true; 14006 * } 14007 * else if ( min < version && version < max ) { 14008 * return true; 14009 * } 14010 * return false; 14011 * } 14012 * ); 14013 */ 14014 search: [], 14015 14016 14017 /** 14018 * Selector extensions 14019 * 14020 * The `selector` option can be used to extend the options available for the 14021 * selector modifier options (`selector-modifier` object data type) that 14022 * each of the three built in selector types offer (row, column and cell + 14023 * their plural counterparts). For example the Select extension uses this 14024 * mechanism to provide an option to select only rows, columns and cells 14025 * that have been marked as selected by the end user (`{selected: true}`), 14026 * which can be used in conjunction with the existing built in selector 14027 * options. 14028 * 14029 * Each property is an array to which functions can be pushed. The functions 14030 * take three attributes: 14031 * 14032 * * Settings object for the host table 14033 * * Options object (`selector-modifier` object type) 14034 * * Array of selected item indexes 14035 * 14036 * The return is an array of the resulting item indexes after the custom 14037 * selector has been applied. 14038 * 14039 * @type object 14040 */ 14041 selector: { 14042 cell: [], 14043 column: [], 14044 row: [] 14045 }, 14046 14047 14048 /** 14049 * Internal functions, exposed for used in plug-ins. 14050 * 14051 * Please note that you should not need to use the internal methods for 14052 * anything other than a plug-in (and even then, try to avoid if possible). 14053 * The internal function may change between releases. 14054 * 14055 * @type object 14056 * @default {} 14057 */ 14058 internal: {}, 14059 14060 14061 /** 14062 * Legacy configuration options. Enable and disable legacy options that 14063 * are available in DataTables. 14064 * 14065 * @type object 14066 */ 14067 legacy: { 14068 /** 14069 * Enable / disable DataTables 1.9 compatible server-side processing 14070 * requests 14071 * 14072 * @type boolean 14073 * @default null 14074 */ 14075 ajax: null 14076 }, 14077 14078 14079 /** 14080 * Pagination plug-in methods. 14081 * 14082 * Each entry in this object is a function and defines which buttons should 14083 * be shown by the pagination rendering method that is used for the table: 14084 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the 14085 * buttons are displayed in the document, while the functions here tell it 14086 * what buttons to display. This is done by returning an array of button 14087 * descriptions (what each button will do). 14088 * 14089 * Pagination types (the four built in options and any additional plug-in 14090 * options defined here) can be used through the `paginationType` 14091 * initialisation parameter. 14092 * 14093 * The functions defined take two parameters: 14094 * 14095 * 1. `{int} page` The current page index 14096 * 2. `{int} pages` The number of pages in the table 14097 * 14098 * Each function is expected to return an array where each element of the 14099 * array can be one of: 14100 * 14101 * * `first` - Jump to first page when activated 14102 * * `last` - Jump to last page when activated 14103 * * `previous` - Show previous page when activated 14104 * * `next` - Show next page when activated 14105 * * `{int}` - Show page of the index given 14106 * * `{array}` - A nested array containing the above elements to add a 14107 * containing 'DIV' element (might be useful for styling). 14108 * 14109 * Note that DataTables v1.9- used this object slightly differently whereby 14110 * an object with two functions would be defined for each plug-in. That 14111 * ability is still supported by DataTables 1.10+ to provide backwards 14112 * compatibility, but this option of use is now decremented and no longer 14113 * documented in DataTables 1.10+. 14114 * 14115 * @type object 14116 * @default {} 14117 * 14118 * @example 14119 * // Show previous, next and current page buttons only 14120 * $.fn.dataTableExt.oPagination.current = function ( page, pages ) { 14121 * return [ 'previous', page, 'next' ]; 14122 * }; 14123 */ 14124 pager: {}, 14125 14126 14127 renderer: { 14128 pageButton: {}, 14129 header: {} 14130 }, 14131 14132 14133 /** 14134 * Ordering plug-ins - custom data source 14135 * 14136 * The extension options for ordering of data available here is complimentary 14137 * to the default type based ordering that DataTables typically uses. It 14138 * allows much greater control over the the data that is being used to 14139 * order a column, but is necessarily therefore more complex. 14140 * 14141 * This type of ordering is useful if you want to do ordering based on data 14142 * live from the DOM (for example the contents of an 'input' element) rather 14143 * than just the static string that DataTables knows of. 14144 * 14145 * The way these plug-ins work is that you create an array of the values you 14146 * wish to be ordering for the column in question and then return that 14147 * array. The data in the array much be in the index order of the rows in 14148 * the table (not the currently ordering order!). Which order data gathering 14149 * function is run here depends on the `dt-init columns.orderDataType` 14150 * parameter that is used for the column (if any). 14151 * 14152 * The functions defined take two parameters: 14153 * 14154 * 1. `{object}` DataTables settings object: see 14155 * {@link DataTable.models.oSettings} 14156 * 2. `{int}` Target column index 14157 * 14158 * Each function is expected to return an array: 14159 * 14160 * * `{array}` Data for the column to be ordering upon 14161 * 14162 * @type array 14163 * 14164 * @example 14165 * // Ordering using `input` node values 14166 * $.fn.dataTable.ext.order['dom-text'] = function ( settings, col ) 14167 * { 14168 * return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) { 14169 * return $('input', td).val(); 14170 * } ); 14171 * } 14172 */ 14173 order: {}, 14174 14175 14176 /** 14177 * Type based plug-ins. 14178 * 14179 * Each column in DataTables has a type assigned to it, either by automatic 14180 * detection or by direct assignment using the `type` option for the column. 14181 * The type of a column will effect how it is ordering and search (plug-ins 14182 * can also make use of the column type if required). 14183 * 14184 * @namespace 14185 */ 14186 type: { 14187 /** 14188 * Type detection functions. 14189 * 14190 * The functions defined in this object are used to automatically detect 14191 * a column's type, making initialisation of DataTables super easy, even 14192 * when complex data is in the table. 14193 * 14194 * The functions defined take two parameters: 14195 * 14196 * 1. `{*}` Data from the column cell to be analysed 14197 * 2. `{settings}` DataTables settings object. This can be used to 14198 * perform context specific type detection - for example detection 14199 * based on language settings such as using a comma for a decimal 14200 * place. Generally speaking the options from the settings will not 14201 * be required 14202 * 14203 * Each function is expected to return: 14204 * 14205 * * `{string|null}` Data type detected, or null if unknown (and thus 14206 * pass it on to the other type detection functions. 14207 * 14208 * @type array 14209 * 14210 * @example 14211 * // Currency type detection plug-in: 14212 * $.fn.dataTable.ext.type.detect.push( 14213 * function ( data, settings ) { 14214 * // Check the numeric part 14215 * if ( ! data.substring(1).match(/[0-9]/) ) { 14216 * return null; 14217 * } 14218 * 14219 * // Check prefixed by currency 14220 * if ( data.charAt(0) == '$' || data.charAt(0) == '£' ) { 14221 * return 'currency'; 14222 * } 14223 * return null; 14224 * } 14225 * ); 14226 */ 14227 detect: [], 14228 14229 14230 /** 14231 * Type based search formatting. 14232 * 14233 * The type based searching functions can be used to pre-format the 14234 * data to be search on. For example, it can be used to strip HTML 14235 * tags or to de-format telephone numbers for numeric only searching. 14236 * 14237 * Note that is a search is not defined for a column of a given type, 14238 * no search formatting will be performed. 14239 * 14240 * Pre-processing of searching data plug-ins - When you assign the sType 14241 * for a column (or have it automatically detected for you by DataTables 14242 * or a type detection plug-in), you will typically be using this for 14243 * custom sorting, but it can also be used to provide custom searching 14244 * by allowing you to pre-processing the data and returning the data in 14245 * the format that should be searched upon. This is done by adding 14246 * functions this object with a parameter name which matches the sType 14247 * for that target column. This is the corollary of <i>afnSortData</i> 14248 * for searching data. 14249 * 14250 * The functions defined take a single parameter: 14251 * 14252 * 1. `{*}` Data from the column cell to be prepared for searching 14253 * 14254 * Each function is expected to return: 14255 * 14256 * * `{string|null}` Formatted string that will be used for the searching. 14257 * 14258 * @type object 14259 * @default {} 14260 * 14261 * @example 14262 * $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) { 14263 * return d.replace(/\n/g," ").replace( /<.*?>/g, "" ); 14264 * } 14265 */ 14266 search: {}, 14267 14268 14269 /** 14270 * Type based ordering. 14271 * 14272 * The column type tells DataTables what ordering to apply to the table 14273 * when a column is sorted upon. The order for each type that is defined, 14274 * is defined by the functions available in this object. 14275 * 14276 * Each ordering option can be described by three properties added to 14277 * this object: 14278 * 14279 * * `{type}-pre` - Pre-formatting function 14280 * * `{type}-asc` - Ascending order function 14281 * * `{type}-desc` - Descending order function 14282 * 14283 * All three can be used together, only `{type}-pre` or only 14284 * `{type}-asc` and `{type}-desc` together. It is generally recommended 14285 * that only `{type}-pre` is used, as this provides the optimal 14286 * implementation in terms of speed, although the others are provided 14287 * for compatibility with existing Javascript sort functions. 14288 * 14289 * `{type}-pre`: Functions defined take a single parameter: 14290 * 14291 * 1. `{*}` Data from the column cell to be prepared for ordering 14292 * 14293 * And return: 14294 * 14295 * * `{*}` Data to be sorted upon 14296 * 14297 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort 14298 * functions, taking two parameters: 14299 * 14300 * 1. `{*}` Data to compare to the second parameter 14301 * 2. `{*}` Data to compare to the first parameter 14302 * 14303 * And returning: 14304 * 14305 * * `{*}` Ordering match: <0 if first parameter should be sorted lower 14306 * than the second parameter, ===0 if the two parameters are equal and 14307 * >0 if the first parameter should be sorted height than the second 14308 * parameter. 14309 * 14310 * @type object 14311 * @default {} 14312 * 14313 * @example 14314 * // Numeric ordering of formatted numbers with a pre-formatter 14315 * $.extend( $.fn.dataTable.ext.type.order, { 14316 * "string-pre": function(x) { 14317 * a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" ); 14318 * return parseFloat( a ); 14319 * } 14320 * } ); 14321 * 14322 * @example 14323 * // Case-sensitive string ordering, with no pre-formatting method 14324 * $.extend( $.fn.dataTable.ext.order, { 14325 * "string-case-asc": function(x,y) { 14326 * return ((x < y) ? -1 : ((x > y) ? 1 : 0)); 14327 * }, 14328 * "string-case-desc": function(x,y) { 14329 * return ((x < y) ? 1 : ((x > y) ? -1 : 0)); 14330 * } 14331 * } ); 14332 */ 14333 order: {} 14334 }, 14335 14336 /** 14337 * Unique DataTables instance counter 14338 * 14339 * @type int 14340 * @private 14341 */ 14342 _unique: 0, 14343 14344 14345 // 14346 // Depreciated 14347 // The following properties are retained for backwards compatib
vendor: 3,173 bytes, lines 14347-14484
14347lity only. 14348 // The should not be used in new projects and will be removed in a future 14349 // version 14350 // 14351 14352 /** 14353 * Version check function. 14354 * @type function 14355 * @depreciated Since 1.10 14356 */ 14357 fnVersionCheck: DataTable.fnVersionCheck, 14358 14359 14360 /** 14361 * Index for what 'this' index API functions should use 14362 * @type int 14363 * @deprecated Since v1.10 14364 */ 14365 iApiIndex: 0, 14366 14367 14368 /** 14369 * jQuery UI class container 14370 * @type object 14371 * @deprecated Since v1.10 14372 */ 14373 oJUIClasses: {}, 14374 14375 14376 /** 14377 * Software version 14378 * @type string 14379 * @deprecated Since v1.10 14380 */ 14381 sVersion: DataTable.version 14382 }; 14383 14384 14385 // 14386 // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts 14387 // 14388 $.extend( _ext, { 14389 afnFiltering: _ext.search, 14390 aTypes: _ext.type.detect, 14391 ofnSearch: _ext.type.search, 14392 oSort: _ext.type.order, 14393 afnSortData: _ext.order, 14394 aoFeatures: _ext.feature, 14395 oApi: _ext.internal, 14396 oStdClasses: _ext.classes, 14397 oPagination: _ext.pager 14398 } ); 14399 14400 14401 $.extend( DataTable.ext.classes, { 14402 "sTable": "dataTable", 14403 "sNoFooter": "no-footer", 14404 14405 /* Paging buttons */ 14406 "sPageButton": "paginate_button", 14407 "sPageButtonActive": "current", 14408 "sPageButtonDisabled": "disabled hide", 14409 14410 /* Striping classes */ 14411 "sStripeOdd": "odd", 14412 "sStripeEven": "even", 14413 14414 /* Empty row */ 14415 "sRowEmpty": "dataTables_empty", 14416 14417 /* Features */ 14418 "sWrapper": "dataTables_wrapper", 14419 "sFilter": "dataTables_filter", 14420 "sInfo": "dataTables_info", 14421 "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */ 14422 "sLength": "dataTables_length", 14423 "sProcessing": "dataTables_processing", 14424 14425 /* Sorting */ 14426 "sSortAsc": "sorting_asc", 14427 "sSortDesc": "sorting_desc", 14428 "sSortable": "sorting", /* Sortable in both directions */ 14429 "sSortableAsc": "sorting_asc_disabled", 14430 "sSortableDesc": "sorting_desc_disabled", 14431 "sSortableNone": "sorting_disabled", 14432 "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */ 14433 14434 /* Filtering */ 14435 "sFilterInput": "", 14436 14437 /* Page length */ 14438 "sLengthSelect": "", 14439 14440 /* Scrolling */ 14441 "sScrollWrapper": "dataTables_scroll", 14442 "sScrollHead": "dataTables_scrollHead", 14443 "sScrollHeadInner": "dataTables_scrollHeadInner", 14444 "sScrollBody": "dataTables_scrollBody", 14445 "sScrollFoot": "dataTables_scrollFoot", 14446 "sScrollFootInner": "dataTables_scrollFootInner", 14447 14448 /* Misc */ 14449 "sHeaderTH": "", 14450 "sFooterTH": "", 14451 14452 // Deprecated 14453 "sSortJUIAsc": "", 14454 "sSortJUIDesc": "", 14455 "sSortJUI": "", 14456 "sSortJUIAscAllowed": "", 14457 "sSortJUIDescAllowed": "", 14458 "sSortJUIWrapper": "", 14459 "sSortIcon": "", 14460 "sJUIHeader": "", 14461 "sJUIFooter": "" 14462 } ); 14463 14464 14465 var extPagination = DataTable.ext.pager; 14466 14467 function _numbers ( page, pages ) { 14468 var 14469 numbers = [], 14470 buttons = extPagination.numbers_length, 14471 half = Math.floor( buttons / 2 ), 14472 i = 1; 14473 14474 if ( pages <= buttons ) { 14475 numbers = _range( 0, pages ); 14476 } 14477 else if ( page <= half ) { 14478 numbers = _range( 0, buttons-2 ); 14479 numbers.push( 'ellipsis' ); 14480 numbers.push( pages-1 ); 14481 } 14482 else if ( page >= pages - 1 - half ) { 14483 numbers = _range( pages-(buttons-2), pages ); 14484 numbers.splice( 0, 0, 'ellipsis' );
14484 // no unshift in ie6 14485 numbers.splice( 0, 0, 0 ); 14486 } 14487 else { 14488 numbers = _range( page-half+2, page+half-1 ); 14489 numbers.push( 'ellipsis' ); 14490 numbers.push( pages-1 ); 14491 numbers.splice( 0, 0, 'ellipsis' ); 14492 numbers.splice( 0, 0, 0 ); 14493 } 14494 14495 numbers.DT_el = 'span'; 14496 return numbers; 14497 } 14498 14499 14500 $.extend( extPagination, { 14501 simple: function ( page, pages ) { 14502 return [ 'previous', 'next' ]; 14503 }, 14504 14505 full: function ( page, pages ) { 14506 return [ 'first', 'previous', 'next', 'last' ]; 14507 }, 14508 14509 numbers: function ( page, pages ) { 14510 return [ _numbers(page, pages) ]; 14511 }, 14512 14513 simple_numbers: function ( page, pages ) { 14514 return [ 'previous', _numbers(page, pages), 'next' ]; 14515 }, 14516 14517 full_numbers: function ( page, pages ) { 14518 return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ]; 14519 }, 14520 14521 first_last_numbers: function (page, pages) { 14522 return ['first', _numbers(page, pages), 'last']; 14523 }, 14524 14525 // For testing and plug-ins to use 14526 _numbers: _numbers, 14527 14528 // Number of number buttons (including ellipsis) to show. _Must be odd!_ 14529 numbers_length: 7 14530 } ); 14531 14532 14533 $.extend( true, DataTable.ext.renderer, { 14534 pageButton: { 14535 _: function ( settings, host, idx, buttons, page, pages ) { 14536 var classes = settings.oClasses; 14537 var lang = settings.oLanguage.oPaginate; 14538 var aria = settings.oLanguage.oAria.paginate || {}; 14539 var btnDisplay, btnClass, counter=0; 14540 14541 var attach = function( container, buttons ) { 14542 var i, ien, node, button; 14543 var clickHandler = function ( e ) { 14544 _fnPageChange( settings, e.data.action, true ); 14545 }; 14546 14547 for ( i=0, ien=buttons.length ; i<ien ; i++ ) { 14548 button = buttons[i]; 14549 14550 if ( $.isArray( button ) ) { 14551 var inner = $( '<'+(button.DT_el || 'div')+'/>' ) 14552 .appendTo( container ); 14553 attach( inner, button ); 14554 } 14555 else { 14556 btnDisplay = null; 14557 btnClass = ''; 14558 14559 switch ( button ) { 14560 case 'ellipsis': 14561 container.append('<span class="ellipsis">…</span>'); 14562 break; 14563 14564 case 'first': 14565 btnDisplay = lang.sFirst; 14566 btnClass = button + (page > 0 ? 14567 '' : ' '+classes.sPageButtonDisabled); 14568 break; 14569 14570 case 'previous': 14571 btnDisplay = lang.sPrevious; 14572 btnClass = button + (page > 0 ? 14573 '' : ' '+classes.sPageButtonDisabled); 14574 break; 14575 14576 case 'next': 14577 btnDisplay = lang.sNext; 14578 btnClass = button + (page < pages-1 ? 14579 '' : ' '+classes.sPageButtonDisabled); 14580 break; 14581 14582 case 'last': 14583 btnDisplay = lang.sLast; 14584 btnClass = button + (page < pages-1 ? 14585 '' : ' '+classes.sPageButtonDisabled); 14586 break; 14587 14588 default: 14589 btnDisplay = button + 1; 14590 btnClass = page === button ? 14591 classes.sPageButtonActive : ''; 14592 break; 14593 } 14594 14595 if ( btnDisplay !== null ) { 14596 node = $('<a>', { 14597 'class': classes.sPageButton+' '+btnClass, 14598 'aria-controls': settings.sTableId, 14599 'aria-label': aria[ button ], 14600 'data-dt-idx': counter, 14601 'tabindex': settings.iTabIndex, 14602 'id': idx === 0 && typeof button === 'string' ? 14603 settings.sTableId +'_'+ button : 14604 null 14605 } ) 14606 .html( btnDisplay ) 14607 .appendTo( container ); 14608 14609 _fnBindAction( 14610 node, {action: button}, clickHandler 14611 ); 14612 14613 counter++; 14614 } 14615 } 14616 } 14617 }; 14618 14619 // IE9 throws an 'unknown error' if document.activeElement is used 14620 // inside an iframe or frame. Try / catch the error. Not good for 14621 // accessibility, but neither are frames. 14622 var activeEl; 14623 14624 try { 14625 // Because this approach is destroying and recreating the paging 14626 // elements, focus is lost on the select button which is bad for 14627 // accessibility. So we want to restore focus once the draw has 14628 // completed 14629 activeEl = $(host).find(document.activeElement).data('dt-idx'); 14630 } 14631 catch (e) {} 14632 14633 attach( $(host).empty(), buttons ); 14634 14635 if ( activeEl !== undefined ) { 14636 $(host).find( '[data-dt-idx='+activeEl+']' ).focus(); 14637 } 14638 } 14639 } 14640 } ); 14641 14642 14643 14644 // Built in type detection. See model.ext.aTypes for information about 14645 // what is required from this methods. 14646 $.extend( DataTable.ext.type.detect, [
vendor: 18,465 bytes, lines 14647-15246
14647 // Plain numbers - first since V8 detects some plain numbers as dates 14648 // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...). 14649 function ( d, settings ) 14650 { 14651 var decimal = settings.oLanguage.sDecimal; 14652 return _isNumber( d, decimal ) ? 'num'+decimal : null; 14653 }, 14654 14655 // Dates (only those recognised by the browser's Date.parse) 14656 function ( d, settings ) 14657 { 14658 // V8 tries _very_ hard to make a string passed into `Date.parse()` 14659 // valid, so we need to use a regex to restrict date formats. Use a 14660 // plug-in for anything other than ISO8601 style strings 14661 if ( d && !(d instanceof Date) && ! _re_date.test(d) ) { 14662 return null; 14663 } 14664 var parsed = Date.parse(d); 14665 return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null; 14666 }, 14667 14668 // Formatted numbers 14669 function ( d, settings ) 14670 { 14671 var decimal = settings.oLanguage.sDecimal; 14672 return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null; 14673 }, 14674 14675 // HTML numeric 14676 function ( d, settings ) 14677 { 14678 var decimal = settings.oLanguage.sDecimal; 14679 return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null; 14680 }, 14681 14682 // HTML numeric, formatted 14683 function ( d, settings ) 14684 { 14685 var decimal = settings.oLanguage.sDecimal; 14686 return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null; 14687 }, 14688 14689 // HTML (this is strict checking - there must be html) 14690 function ( d, settings ) 14691 { 14692 return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ? 14693 'html' : null; 14694 } 14695 ] ); 14696 14697 14698 14699 // Filter formatting functions. See model.ext.ofnSearch for information about 14700 // what is required from these methods. 14701 // 14702 // Note that additional search methods are added for the html numbers and 14703 // html formatted numbers by `_addNumericSort()` when we know what the decimal 14704 // place is 14705 14706 14707 $.extend( DataTable.ext.type.search, { 14708 html: function ( data ) { 14709 return _empty(data) ? 14710 data : 14711 typeof data === 'string' ? 14712 data 14713 .replace( _re_new_lines, " " ) 14714 .replace( _re_html, "" ) : 14715 ''; 14716 }, 14717 14718 string: function ( data ) { 14719 return _empty(data) ? 14720 data : 14721 typeof data === 'string' ? 14722 data.replace( _re_new_lines, " " ) : 14723 data; 14724 } 14725 } ); 14726 14727 14728 14729 var __numericReplace = function ( d, decimalPlace, re1, re2 ) { 14730 if ( d !== 0 && (!d || d === '-') ) { 14731 return -Infinity; 14732 } 14733 14734 // If a decimal place other than `.` is used, it needs to be given to the 14735 // function so we can detect it and replace with a `.` which is the only 14736 // decimal place Javascript recognises - it is not locale aware. 14737 if ( decimalPlace ) { 14738 d = _numToDecimal( d, decimalPlace ); 14739 } 14740 14741 if ( d.replace ) { 14742 if ( re1 ) { 14743 d = d.replace( re1, '' ); 14744 } 14745 14746 if ( re2 ) { 14747 d = d.replace( re2, '' ); 14748 } 14749 } 14750 14751 return d * 1; 14752 }; 14753 14754 14755 // Add the numeric 'deformatting' functions for sorting and search. This is done 14756 // in a function to provide an easy ability for the language options to add 14757 // additional methods if a non-period decimal place is used. 14758 function _addNumericSort ( decimalPlace ) { 14759 $.each( 14760 { 14761 // Plain numbers 14762 "num": function ( d ) { 14763 return __numericReplace( d, decimalPlace ); 14764 }, 14765 14766 // Formatted numbers 14767 "num-fmt": function ( d ) { 14768 return __numericReplace( d, decimalPlace, _re_formatted_numeric ); 14769 }, 14770 14771 // HTML numeric 14772 "html-num": function ( d ) { 14773 return __numericReplace( d, decimalPlace, _re_html ); 14774 }, 14775 14776 // HTML numeric, formatted 14777 "html-num-fmt": function ( d ) { 14778 return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric ); 14779 } 14780 }, 14781 function ( key, fn ) { 14782 // Add the ordering method 14783 _ext.type.order[ key+decimalPlace+'-pre' ] = fn; 14784 14785 // For HTML types add a search formatter that will strip the HTML 14786 if ( key.match(/^html\-/) ) { 14787 _ext.type.search[ key+decimalPlace ] = _ext.type.search.html; 14788 } 14789 } 14790 ); 14791 } 14792 14793 14794 // Default sort methods 14795 $.extend( _ext.type.order, { 14796 // Dates 14797 "date-pre": function ( d ) { 14798 var ts = Date.parse( d ); 14799 return isNaN(ts) ? -Infinity : ts; 14800 }, 14801 14802 // html 14803 "html-pre": function ( a ) { 14804 return _empty(a) ? 14805 '' : 14806 a.replace ? 14807 a.replace( /<.*?>/g, "" ).toLowerCase() : 14808 a+''; 14809 }, 14810 14811 // string 14812 "string-pre": function ( a ) { 14813 // This is a little complex, but faster than always calling toString, 14814 // http://jsperf.com/tostring-v-check 14815 return _empty(a) ? 14816 '' : 14817 typeof a === 'string' ? 14818 a.toLowerCase() : 14819 ! a.toString ? 14820 '' : 14821 a.toString(); 14822 }, 14823 14824 // string-asc and -desc are retained only for compatibility with the old 14825 // sort methods 14826 "string-asc": function ( x, y ) { 14827 return ((x < y) ? -1 : ((x > y) ? 1 : 0)); 14828 }, 14829 14830 "string-desc": function ( x, y ) { 14831 return ((x < y) ? 1 : ((x > y) ? -1 : 0)); 14832 } 14833 } ); 14834 14835 14836 // Numeric sorting types - order doesn't matter here 14837 _addNumericSort( '' ); 14838 14839 14840 $.extend( true, DataTable.ext.renderer, { 14841 header: { 14842 _: function ( settings, cell, column, classes ) { 14843 // No additional mark-up required 14844 // Attach a sort listener to update on sort - note that using the 14845 // `DT` namespace will allow the event to be removed automatically 14846 // on destroy, while the `dt` namespaced event is the one we are 14847 // listening for 14848 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) { 14849 if ( settings !== ctx ) { // need to check this this is the host 14850 return; // table, not a nested one 14851 } 14852 14853 var colIdx = column.idx; 14854 14855 cell.removeClass( 14856 column.sSortingClass +' '+ 14857 classes.sSortAsc +' '+ 14858 classes.sSortDesc 14859 ); 14860 cell.find(".sort-icon").removeClass( 14861 column.sSortingClass +' '+ 14862 classes.sSortAsc +' '+ 14863 classes.sSortDesc 14864 ); 14865 cell.find(".sort-icon").addClass( columns[ colIdx ] == 'asc' ? 14866 classes.sSortAsc : columns[ colIdx ] == 'desc' ? 14867 classes.sSortDesc : 14868 column.sSortingClass 14869 ); 14870 } ); 14871 }, 14872 14873 jqueryui: function ( settings, cell, column, classes ) { 14874 $('<div/>') 14875 .addClass( classes.sSortJUIWrapper ) 14876 .append( cell.contents() ) 14877 .append( $('<span/>') 14878 .addClass( classes.sSortIcon+' '+column.sSortingClassJUI ) 14879 ) 14880 .appendTo( cell ); 14881 14882 // Attach a sort listener to update on sort 14883 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) { 14884 if ( settings !== ctx ) { 14885 return; 14886 } 14887 14888 var colIdx = column.idx; 14889 cell.removeClass( classes.sSortAsc +" "+classes.sSortDesc ); 14890 cell.find(".sort-icon").removeClass( classes.sSortAsc +" "+classes.sSortDesc ); 14891 cell.find(".sort-icon").addClass( columns[ colIdx ] == 'asc' ? 14892 classes.sSortAsc : columns[ colIdx ] == 'desc' ? 14893 classes.sSortDesc : 14894 column.sSortingClass 14895 ); 14896 14897 cell 14898 .find( 'span.'+classes.sSortIcon ) 14899 .removeClass( 14900 classes.sSortJUIAsc +" "+ 14901 classes.sSortJUIDesc +" "+ 14902 classes.sSortJUI +" "+ 14903 classes.sSortJUIAscAllowed +" "+ 14904 classes.sSortJUIDescAllowed 14905 ) 14906 .addClass( columns[ colIdx ] == 'asc' ? 14907 classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ? 14908 classes.sSortJUIDesc : 14909 column.sSortingClassJUI 14910 ); 14911 } ); 14912 } 14913 } 14914 } ); 14915 14916 /* 14917 * Public helper functions. These aren't used internally by DataTables, or 14918 * called by any of the options passed into DataTables, but they can be used 14919 * externally by developers working with DataTables. They are helper functions 14920 * to make working with DataTables a little bit easier. 14921 */ 14922 14923 var __htmlEscapeEntities = function ( d ) { 14924 return typeof d === 'string' ? 14925 d.replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"') : 14926 d; 14927 }; 14928 14929 /** 14930 * Helpers for `columns.render`. 14931 * 14932 * The options defined here can be used with the `columns.render` initialisation 14933 * option to provide a display renderer. The following functions are defined: 14934 * 14935 * * `number` - Will format numeric data (defined by `columns.data`) for 14936 * display, retaining the original unformatted data for sorting and filtering. 14937 * It takes 5 parameters: 14938 * * `string` - Thousands grouping separator 14939 * * `string` - Decimal point indicator 14940 * * `integer` - Number of decimal points to show 14941 * * `string` (optional) - Prefix. 14942 * * `string` (optional) - Postfix (/suffix). 14943 * * `text` - Escape HTML to help prevent XSS attacks. It has no optional 14944 * parameters. 14945 * 14946 * @example 14947 * // Column definition using the number renderer 14948 * { 14949 * data: "salary", 14950 * render: $.fn.dataTable.render.number( '\'', '.', 0, '$' ) 14951 * } 14952 * 14953 * @namespace 14954 */ 14955 DataTable.render = { 14956 number: function ( thousands, decimal, precision, prefix, postfix ) { 14957 return { 14958 display: function ( d ) { 14959 if ( typeof d !== 'number' && typeof d !== 'string' ) { 14960 return d; 14961 } 14962 14963 var negative = d < 0 ? '-' : ''; 14964 var flo = parseFloat( d ); 14965 14966 // If NaN then there isn't much formatting that we can do - just 14967 // return immediately, escaping any HTML (this was supposed to 14968 // be a number after all) 14969 if ( isNaN( flo ) ) { 14970 return __htmlEscapeEntities( d ); 14971 } 14972 14973 flo = flo.toFixed( precision ); 14974 d = Math.abs( flo ); 14975 14976 var intPart = parseInt( d, 10 ); 14977 var floatPart = precision ? 14978 decimal+(d - intPart).toFixed( precision ).substring( 2 ): 14979 ''; 14980 14981 return negative + (prefix||'') + 14982 intPart.toString().replace( 14983 /\B(?=(\d{3})+(?!\d))/g, thousands 14984 ) + 14985 floatPart + 14986 (postfix||''); 14987 } 14988 }; 14989 }, 14990 14991 text: function () { 14992 return { 14993 display: __htmlEscapeEntities 14994 }; 14995 } 14996 }; 14997 14998 14999 /* 15000 * This is really a good bit rubbish this method of exposing the internal methods 15001 * publicly... - To be fixed in 2.0 using methods on the prototype 15002 */ 15003 15004 15005 /** 15006 * Create a wrapper function for exporting an internal functions to an external API. 15007 * @param {string} fn API function name 15008 * @returns {function} wrapped function 15009 * @memberof DataTable#internal 15010 */ 15011 function _fnExternApiFunc (fn) 15012 { 15013 return function() { 15014 var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat( 15015 Array.prototype.slice.call(arguments) 15016 ); 15017 return DataTable.ext.internal[fn].apply( this, args ); 15018 }; 15019 } 15020 15021 15022 /** 15023 * Reference to internal functions for use by plug-in developers. Note that 15024 * these methods are references to internal functions and are considered to be 15025 * private. If you use these methods, be aware that they are liable to change 15026 * between versions. 15027 * @namespace 15028 */ 15029 $.extend( DataTable.ext.internal, { 15030 _fnExternApiFunc: _fnExternApiFunc, 15031 _fnBuildAjax: _fnBuildAjax, 15032 _fnAjaxUpdate: _fnAjaxUpdate, 15033 _fnAjaxParameters: _fnAjaxParameters, 15034 _fnAjaxUpdateDraw: _fnAjaxUpdateDraw, 15035 _fnAjaxDataSrc: _fnAjaxDataSrc, 15036 _fnAddColumn: _fnAddColumn, 15037 _fnColumnOptions: _fnColumnOptions, 15038 _fnAdjustColumnSizing: _fnAdjustColumnSizing, 15039 _fnVisibleToColumnIndex: _fnVisibleToColumnIndex, 15040 _fnColumnIndexToVisible: _fnColumnIndexToVisible, 15041 _fnVisbleColumns: _fnVisbleColumns, 15042 _fnGetColumns: _fnGetColumns, 15043 _fnColumnTypes: _fnColumnTypes, 15044 _fnApplyColumnDefs: _fnApplyColumnDefs, 15045 _fnHungarianMap: _fnHungarianMap, 15046 _fnCamelToHungarian: _fnCamelToHungarian, 15047 _fnLanguageCompat: _fnLanguageCompat, 15048 _fnBrowserDetect: _fnBrowserDetect, 15049 _fnAddData: _fnAddData, 15050 _fnAddTr: _fnAddTr, 15051 _fnNodeToDataIndex: _fnNodeToDataIndex, 15052 _fnNodeToColumnIndex: _fnNodeToColumnIndex, 15053 _fnGetCellData: _fnGetCellData, 15054 _fnSetCellData: _fnSetCellData, 15055 _fnSplitObjNotation: _fnSplitObjNotation, 15056 _fnGetObjectDataFn: _fnGetObjectDataFn, 15057 _fnSetObjectDataFn: _fnSetObjectDataFn, 15058 _fnGetDataMaster: _fnGetDataMaster, 15059 _fnClearTable: _fnClearTable, 15060 _fnDeleteIndex: _fnDeleteIndex, 15061 _fnInvalidate: _fnInvalidate, 15062 _fnGetRowElements: _fnGetRowElements, 15063 _fnCreateTr: _fnCreateTr, 15064 _fnBuildHead: _fnBuildHead, 15065 _fnDrawHead: _fnDrawHead, 15066 _fnDraw: _fnDraw, 15067 _fnReDraw: _fnReDraw, 15068 _fnAddOptionsHtml: _fnAddOptionsHtml, 15069 _fnDetectHeader: _fnDetectHeader, 15070 _fnGetUniqueThs: _fnGetUniqueThs, 15071 _fnFeatureHtmlFilter: _fnFeatureHtmlFilter, 15072 _fnFilterComplete: _fnFilterComplete, 15073 _fnFilterCustom: _fnFilterCustom, 15074 _fnFilterColumn: _fnFilterColumn, 15075 _fnFilter: _fnFilter, 15076 _fnFilterCreateSearch: _fnFilterCreateSearch, 15077 _fnEscapeRegex: _fnEscapeRegex, 15078 _fnFilterData: _fnFilterData, 15079 _fnFeatureHtmlInfo: _fnFeatureHtmlInfo, 15080 _fnUpdateInfo: _fnUpdateInfo, 15081 _fnInfoMacros: _fnInfoMacros, 15082 _fnInitialise: _fnInitialise, 15083 _fnInitComplete: _fnInitComplete, 15084 _fnLengthChange: _fnLengthChange, 15085 _fnFeatureHtmlLength: _fnFeatureHtmlLength, 15086 _fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate, 15087 _fnPageChange: _fnPageChange, 15088 _fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing, 15089 _fnProcessingDisplay: _fnProcessingDisplay, 15090 _fnFeatureHtmlTable: _fnFeatureHtmlTable, 15091 _fnScrollDraw: _fnScrollDraw, 15092 _fnApplyToChildren: _fnApplyToChildren, 15093 _fnCalculateColumnWidths: _fnCalculateColumnWidths, 15094 _fnThrottle: _fnThrottle, 15095 _fnConvertToWidth: _fnConvertToWidth, 15096 _fnGetWidestNode: _fnGetWidestNode, 15097 _fnGetMaxLenString: _fnGetMaxLenString, 15098 _fnStringToCss: _fnStringToCss, 15099 _fnSortFlatten: _fnSortFlatten, 15100 _fnSort: _fnSort, 15101 _fnSortAria: _fnSortAria, 15102 _fnSortListener: _fnSortListener, 15103 _fnSortAttachListener: _fnSortAttachListener, 15104 _fnSortingClasses: _fnSortingClasses, 15105 _fnSortData: _fnSortData, 15106 _fnSaveState: _fnSaveState, 15107 _fnLoadState: _fnLoadState, 15108 _fnSettingsFromNode: _fnSettingsFromNode, 15109 _fnLog: _fnLog, 15110 _fnMap: _fnMap, 15111 _fnBindAction: _fnBindAction, 15112 _fnCallbackReg: _fnCallbackReg, 15113 _fnCallbackFire: _fnCallbackFire, 15114 _fnLengthOverflow: _fnLengthOverflow, 15115 _fnRenderer: _fnRenderer, 15116 _fnDataSource: _fnDataSource, 15117 _fnRowAttributes: _fnRowAttributes, 15118 _fnExtend: _fnExtend, 15119 _fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant 15120 // in 1.10, so this dead-end function is 15121 // added to prevent errors 15122 } ); 15123 15124 15125 // jQuery access 15126 $.fn.dataTable = DataTable; 15127 15128 // Provide access to the host jQuery object (circular reference) 15129 DataTable.$ = $; 15130 15131 // Legacy aliases 15132 $.fn.dataTableSettings = DataTable.settings; 15133 $.fn.dataTableExt = DataTable.ext; 15134 15135 // With a capital `D` we return a DataTables API instance rather than a 15136 // jQuery object 15137 $.fn.DataTable = function ( opts ) { 15138 return $(this).dataTable( opts ).api(); 15139 }; 15140 15141 // All properties that are available to $.fn.dataTable should also be 15142 // available on $.fn.DataTable 15143 $.each( DataTable, function ( prop, val ) { 15144 $.fn.DataTable[ prop ] = val; 15145 } ); 15146 15147 15148 // Information about events fired by DataTables - for documentation. 15149 /** 15150 * Draw event, fired whenever the table is redrawn on the page, at the same 15151 * point as fnDrawCallback. This may be useful for binding events or 15152 * performing calculations when the table is altered at all. 15153 * @name DataTable#draw.dt 15154 * @event 15155 * @param {event} e jQuery event object 15156 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15157 */ 15158 15159 /** 15160 * Search event, fired when the searching applied to the table (using the 15161 * built-in global search, or column filters) is altered. 15162 * @name DataTable#search.dt 15163 * @event 15164 * @param {event} e jQuery event object 15165 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15166 */ 15167 15168 /** 15169 * Page change event, fired when the paging of the table is altered. 15170 * @name DataTable#page.dt 15171 * @event 15172 * @param {event} e jQuery event object 15173 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15174 */ 15175 15176 /** 15177 * Order event, fired when the ordering applied to the table is altered. 15178 * @name DataTable#order.dt 15179 * @event 15180 * @param {event} e jQuery event object 15181 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15182 */ 15183 15184 /** 15185 * DataTables initialisation complete event, fired when the table is fully 15186 * drawn, including Ajax data loaded, if Ajax data is required. 15187 * @name DataTable#init.dt 15188 * @event 15189 * @param {event} e jQuery event object 15190 * @param {object} oSettings DataTables settings object 15191 * @param {object} json The JSON object request from the server - only 15192 * present if client-side Ajax sourced data is used</li></ol> 15193 */ 15194 15195 /** 15196 * State save event, fired when the table has changed state a new state save 15197 * is required. This event allows modification of the state saving object 15198 * prior to actually doing the save, including addition or other state 15199 * properties (for plug-ins) or modification of a DataTables core property. 15200 * @name DataTable#stateSaveParams.dt 15201 * @event 15202 * @param {event} e jQuery event object 15203 * @param {object} oSettings DataTables settings object 15204 * @param {object} json The state information to be saved 15205 */ 15206 15207 /** 15208 * State load event, fired when the table is loading state from the stored 15209 * data, but prior to the settings object being modified by the saved state 15210 * - allowing modification of the saved state is required or loading of 15211 * state for a plug-in. 15212 * @name DataTable#stateLoadParams.dt 15213 * @event 15214 * @param {event} e jQuery event object 15215 * @param {object} oSettings DataTables settings object 15216 * @param {object} json The saved state information 15217 */ 15218 15219 /** 15220 * State loaded event, fired when state has been loaded from stored data and 15221 * the settings object has been modified by the loaded data. 15222 * @name DataTable#stateLoaded.dt 15223 * @event 15224 * @param {event} e jQuery event object 15225 * @param {object} oSettings DataTables settings object 15226 * @param {object} json The saved state information 15227 */ 15228 15229 /** 15230 * Processing event, fired when DataTables is doing some kind of processing 15231 * (be it, order, searcg or anything else). It can be used to indicate to 15232 * the end user that there is something happening, or that something has 15233 * finished. 15234 * @name DataTable#processing.dt 15235 * @event 15236 * @param {event} e jQuery event object 15237 * @param {object} oSettings DataTables settings object 15238 * @param {boolean} bShow Flag for if DataTables is doing processing or not 15239 */ 15240 15241 /** 15242 * Ajax (XHR) event, fired whenever an Ajax request is completed from a 15243 * request to made to the server for new data. This event is called before 15244 * DataTables processed the returned data, so it can also be used to pre- 15245 * process the data returned from the server, if needed. 15246 *
15247 * Note that this trigger is called in `fnServerData`, if you override 15248 * `fnServerData` and which to use this event, you need to trigger it in you 15249 * success function. 15250 * @name DataTable#xhr.dt 15251 * @event 15252 * @param {event} e jQuery event object 15253 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15254 * @param {object} json JSON returned from the server 15255 * 15256 * @example 15257 * // Use a custom property returned from the server in another DOM element 15258 * $('#table').dataTable().on('xhr.dt', function (e, settings, json) { 15259 * $('#status').html( json.status ); 15260 * } ); 15261 * 15262 * @example 15263 * // Pre-process the data returned from the server 15264 * $('#table').dataTable().on('xhr.dt', function (e, settings, json) { 15265 * for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) { 15266 * json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two; 15267 * } 15268 * // Note no return - manipulate the data directly in the JSON object. 15269 * } ); 15270 */ 15271 15272 /** 15273 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy 15274 * or passing the bDestroy:true parameter in the initialisation object. This 15275 * can be used to remove bound events, added DOM nodes, etc. 15276 * @name DataTable#destroy.dt 15277 * @event 15278 * @param {event} e jQuery event object 15279 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15280 */ 15281 15282 /** 15283 * Page length change event, fired when number of records to show on each 15284 * page (the length) is changed. 15285 * @name DataTable#length.dt 15286 * @event 15287 * @param {event} e jQuery event object 15288 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15289 * @param {integer} len New length 15290 */ 15291 15292 /** 15293 * Column sizing has changed. 15294 * @name DataTable#column-sizing.dt 15295 * @event 15296 * @param {event} e jQuery event object 15297 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15298 */ 15299 15300 /** 15301 * Column visibility has changed. 15302 * @name DataTable#column-visibility.dt 15303 * @event 15304 * @param {event} e jQuery event object 15305 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15306 * @param {int} column Column index 15307 * @param {bool} vis `false` if column now hidden, or `true` if visible 15308 */ 15309 15310 return $.fn.dataTable; 15311})); 15312 15313
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.