1/*! DataTables 1.10.13 2 * ©2008-2016 SpryMedia Ltd - datatables.net/license 3 */ 4 5/** 6 * @summary DataTables 7 * @description Paginate, search and order HTML tables 8 * @version 1.10.13 9 * @file jquery.dataTables.js 10 * @author SpryMedia Ltd 11 * @contact www.datatables.net 12 * @copyright Copyright 2008-2016 SpryMedia Ltd. 13 * 14 * This source file is free software, available under the following license: 15 * MIT license - http://datatables.net/license 16 * 17 * This source file is distributed in the hope that it will be useful, but 18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 19 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. 20 * 21 * For details please refer to: http://www.datatables.net 22 */ 23 24/*jslint evil: true, undef: true, browser: true */ 25/*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/ 26 27(function( factory ) { 28 "use strict"; 29 30 if ( typeof define === 'function' && define.amd ) { 31 // AMD 32 define( ['jquery'], function ( $ ) { 33 return factory( $, window, document ); 34 } ); 35 } 36 else if ( typeof exports === 'object' ) { 37 // CommonJS 38 module.exports = function (root, $) { 39 if ( ! root ) { 40 // CommonJS environments without a window global must pass a 41 // root. This will give an error otherwise 42 root = window; 43 } 44 45 if ( ! $ ) { 46 $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window 47 require('jquery') : 48 require('jquery')( root ); 49 } 50 51 return factory( $, root, root.document ); 52 }; 53 } 54 else { 55 // Browser 56 factory( jQuery, window, document ); 57 } 58} 59(function( $, window, document, undefined ) { 60 "use strict"; 61 62 /** 63 * DataTables is a plug-in for the jQuery Javascript library. It is a highly 64 * flexible tool, based upon the foundations of progressive enhancement, 65 * which will add advanced interaction controls to any HTML table. For a 66 * full list of features please refer to 67 * [DataTables.net](href="http://datatables.net). 68 * 69 * Note that the `DataTable` object is not a global variable but is aliased 70 * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may 71 * be accessed. 72 * 73 * @class 74 * @param {object} [init={}] Configuration object for DataTables. Options 75 * are defined by {@link DataTable.defaults} 76 * @requires jQuery 1.7+ 77 * 78 * @example 79 * // Basic initialisation 80 * $(document).ready( function { 81 * $('#example').dataTable(); 82 * } ); 83 * 84 * @example 85 * // Initialisation with configuration options - in this case, disable 86 * // pagination and sorting. 87 * $(document).ready( function { 88 * $('#example').dataTable( { 89 * "paginate": false, 90 * "sort": false 91 * } ); 92 * } ); 93 */ 94 var DataTable = function ( options ) 95 {
vendor: 6,636 bytes, lines 95-254
95 96 /** 97 * Perform a jQuery selector action on the table's TR elements (from the tbody) and 98 * return the resulting jQuery object. 99 * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on 100 * @param {object} [oOpts] Optional parameters for modifying the rows to be included 101 * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter 102 * criterion ("applied") or all TR elements (i.e. no filter). 103 * @param {string} [oOpts.order=current] Order of the TR elements in the processed array. 104 * Can be either 'current', whereby the current sorting of the table is used, or 105 * 'original' whereby the original order the data was read into the table is used. 106 * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page 107 * ("current") or not ("all"). If 'current' is given, then order is assumed to be 108 * 'current' and filter is 'applied', regardless of what they might be given as. 109 * @returns {object} jQuery object, filtered by the given selector. 110 * @dtopt API 111 * @deprecated Since v1.10 112 * 113 * @example 114 * $(document).ready(function() { 115 * var oTable = $('#example').dataTable(); 116 * 117 * // Highlight every second row 118 * oTable.$('tr:odd').css('backgroundColor', 'blue'); 119 * } ); 120 * 121 * @example 122 * $(document).ready(function() { 123 * var oTable = $('#example').dataTable(); 124 * 125 * // Filter to rows with 'Webkit' in them, add a background colour and then 126 * // remove the filter, thus highlighting the 'Webkit' rows only. 127 * oTable.fnFilter('Webkit'); 128 * oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue'); 129 * oTable.fnFilter(''); 130 * } ); 131 */ 132 this.$ = function ( sSelector, oOpts ) 133 { 134 return this.api(true).$( sSelector, oOpts ); 135 }; 136 137 138 /** 139 * Almost identical to $ in operation, but in this case returns the data for the matched 140 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes 141 * rather than any descendants, so the data can be obtained for the row/cell. If matching 142 * rows are found, the data returned is the original data array/object that was used to 143 * create the row (or a generated array if from a DOM source). 144 * 145 * This method is often useful in-combination with $ where both functions are given the 146 * same parameters and the array indexes will match identically. 147 * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on 148 * @param {object} [oOpts] Optional parameters for modifying the rows to be included 149 * @param {string} [oOpts.filter=none] Select elements that meet the current filter 150 * criterion ("applied") or all elements (i.e. no filter). 151 * @param {string} [oOpts.order=current] Order of the data in the processed array. 152 * Can be either 'current', whereby the current sorting of the table is used, or 153 * 'original' whereby the original order the data was read into the table is used. 154 * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page 155 * ("current") or not ("all"). If 'current' is given, then order is assumed to be 156 * 'current' and filter is 'applied', regardless of what they might be given as. 157 * @returns {array} Data for the matched elements. If any elements, as a result of the 158 * selector, were not TR, TD or TH elements in the DataTable, they will have a null 159 * entry in the array. 160 * @dtopt API 161 * @deprecated Since v1.10 162 * 163 * @example 164 * $(document).ready(function() { 165 * var oTable = $('#example').dataTable(); 166 * 167 * // Get the data from the first row in the table 168 * var data = oTable._('tr:first'); 169 * 170 * // Do something useful with the data 171 * alert( "First cell is: "+data[0] ); 172 * } ); 173 * 174 * @example 175 * $(document).ready(function() { 176 * var oTable = $('#example').dataTable(); 177 * 178 * // Filter to 'Webkit' and get all data for 179 * oTable.fnFilter('Webkit'); 180 * var data = oTable._('tr', {"search": "applied"}); 181 * 182 * // Do something with the data 183 * alert( data.length+" rows matched the search" ); 184 * } ); 185 */ 186 this._ = function ( sSelector, oOpts ) 187 { 188 return this.api(true).rows( sSelector, oOpts ).data(); 189 }; 190 191 192 /** 193 * Create a DataTables Api instance, with the currently selected tables for 194 * the Api's context. 195 * @param {boolean} [traditional=false] Set the API instance's context to be 196 * only the table referred to by the `DataTable.ext.iApiIndex` option, as was 197 * used in the API presented by DataTables 1.9- (i.e. the traditional mode), 198 * or if all tables captured in the jQuery object should be used. 199 * @return {DataTables.Api} 200 */ 201 this.api = function ( traditional ) 202 { 203 return traditional ? 204 new _Api( 205 _fnSettingsFromNode( this[ _ext.iApiIndex ] ) 206 ) : 207 new _Api( this ); 208 }; 209 210 211 /** 212 * Add a single new row or multiple rows of data to the table. Please note 213 * that this is suitable for client-side processing only - if you are using 214 * server-side processing (i.e. "bServerSide": true), then to add data, you 215 * must add it to the data source, i.e. the server-side, through an Ajax call. 216 * @param {array|object} data The data to be added to the table. This can be: 217 * <ul> 218 * <li>1D array of data - add a single row with the data provided</li> 219 * <li>2D array of arrays - add multiple rows in a single call</li> 220 * <li>object - data object when using <i>mData</i></li> 221 * <li>array of objects - multiple data objects when using <i>mData</i></li> 222 * </ul> 223 * @param {bool} [redraw=true] redraw the table or not 224 * @returns {array} An array of integers, representing the list of indexes in 225 * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to 226 * the table. 227 * @dtopt API 228 * @deprecated Since v1.10 229 * 230 * @example 231 * // Global var for counter 232 * var giCount = 2; 233 * 234 * $(document).ready(function() { 235 * $('#example').dataTable(); 236 * } ); 237 * 238 * function fnClickAddRow() { 239 * $('#example').dataTable().fnAddData( [ 240 * giCount+".1", 241 * giCount+".2", 242 * giCount+".3", 243 * giCount+".4" ] 244 * ); 245 * 246 * giCount++; 247 * } 248 */ 249 this.fnAddData = function( data, redraw ) 250 { 251 var api = this.api( true ); 252 253 /* Check if we want to add multiple rows or not */ 254 var rows =
254$.isArray(data) && ( $
vendor: 18,409 bytes, lines 254-850
254.isArray(data[0]) || $.isPlainObject(data[0]) ) ? 255 api.rows.add( data ) : 256 api.row.add( data ); 257 258 if ( redraw === undefined || redraw ) { 259 api.draw(); 260 } 261 262 return rows.flatten().toArray(); 263 }; 264 265 266 /** 267 * This function will make DataTables recalculate the column sizes, based on the data 268 * contained in the table and the sizes applied to the columns (in the DOM, CSS or 269 * through the sWidth parameter). This can be useful when the width of the table's 270 * parent element changes (for example a window resize). 271 * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to 272 * @dtopt API 273 * @deprecated Since v1.10 274 * 275 * @example 276 * $(document).ready(function() { 277 * var oTable = $('#example').dataTable( { 278 * "sScrollY": "200px", 279 * "bPaginate": false 280 * } ); 281 * 282 * $(window).on('resize', function () { 283 * oTable.fnAdjustColumnSizing(); 284 * } ); 285 * } ); 286 */ 287 this.fnAdjustColumnSizing = function ( bRedraw ) 288 { 289 var api = this.api( true ).columns.adjust(); 290 var settings = api.settings()[0]; 291 var scroll = settings.oScroll; 292 293 if ( bRedraw === undefined || bRedraw ) { 294 api.draw( false ); 295 } 296 else if ( scroll.sX !== "" || scroll.sY !== "" ) { 297 /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */ 298 _fnScrollDraw( settings ); 299 } 300 }; 301 302 303 /** 304 * Quickly and simply clear a table 305 * @param {bool} [bRedraw=true] redraw the table or not 306 * @dtopt API 307 * @deprecated Since v1.10 308 * 309 * @example 310 * $(document).ready(function() { 311 * var oTable = $('#example').dataTable(); 312 * 313 * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...) 314 * oTable.fnClearTable(); 315 * } ); 316 */ 317 this.fnClearTable = function( bRedraw ) 318 { 319 var api = this.api( true ).clear(); 320 321 if ( bRedraw === undefined || bRedraw ) { 322 api.draw(); 323 } 324 }; 325 326 327 /** 328 * The exact opposite of 'opening' a row, this function will close any rows which 329 * are currently 'open'. 330 * @param {node} nTr the table row to 'close' 331 * @returns {int} 0 on success, or 1 if failed (can't find the row) 332 * @dtopt API 333 * @deprecated Since v1.10 334 * 335 * @example 336 * $(document).ready(function() { 337 * var oTable; 338 * 339 * // 'open' an information row when a row is clicked on 340 * $('#example tbody tr').click( function () { 341 * if ( oTable.fnIsOpen(this) ) { 342 * oTable.fnClose( this ); 343 * } else { 344 * oTable.fnOpen( this, "Temporary row opened", "info_row" ); 345 * } 346 * } ); 347 * 348 * oTable = $('#example').dataTable(); 349 * } ); 350 */ 351 this.fnClose = function( nTr ) 352 { 353 this.api( true ).row( nTr ).child.hide(); 354 }; 355 356 357 /** 358 * Remove a row for the table 359 * @param {mixed} target The index of the row from aoData to be deleted, or 360 * the TR element you want to delete 361 * @param {function|null} [callBack] Callback function 362 * @param {bool} [redraw=true] Redraw the table or not 363 * @returns {array} The row that was deleted 364 * @dtopt API 365 * @deprecated Since v1.10 366 * 367 * @example 368 * $(document).ready(function() { 369 * var oTable = $('#example').dataTable(); 370 * 371 * // Immediately remove the first row 372 * oTable.fnDeleteRow( 0 ); 373 * } ); 374 */ 375 this.fnDeleteRow = function( target, callback, redraw ) 376 { 377 var api = this.api( true ); 378 var rows = api.rows( target ); 379 var settings = rows.settings()[0]; 380 var data = settings.aoData[ rows[0][0] ]; 381 382 rows.remove(); 383 384 if ( callback ) { 385 callback.call( this, settings, data ); 386 } 387 388 if ( redraw === undefined || redraw ) { 389 api.draw(); 390 } 391 392 return data; 393 }; 394 395 396 /** 397 * Restore the table to it's original state in the DOM by removing all of DataTables 398 * enhancements, alterations to the DOM structure of the table and event listeners. 399 * @param {boolean} [remove=false] Completely remove the table from the DOM 400 * @dtopt API 401 * @deprecated Since v1.10 402 * 403 * @example 404 * $(document).ready(function() { 405 * // This example is fairly pointless in reality, but shows how fnDestroy can be used 406 * var oTable = $('#example').dataTable(); 407 * oTable.fnDestroy(); 408 * } ); 409 */ 410 this.fnDestroy = function ( remove ) 411 { 412 this.api( true ).destroy( remove ); 413 }; 414 415 416 /** 417 * Redraw the table 418 * @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw. 419 * @dtopt API 420 * @deprecated Since v1.10 421 * 422 * @example 423 * $(document).ready(function() { 424 * var oTable = $('#example').dataTable(); 425 * 426 * // Re-draw the table - you wouldn't want to do it here, but it's an example :-) 427 * oTable.fnDraw(); 428 * } ); 429 */ 430 this.fnDraw = function( complete ) 431 { 432 // Note that this isn't an exact match to the old call to _fnDraw - it takes 433 // into account the new data, but can hold position. 434 this.api( true ).draw( complete ); 435 }; 436 437 438 /** 439 * Filter the input based on data 440 * @param {string} sInput String to filter the table on 441 * @param {int|null} [iColumn] Column to limit filtering to 442 * @param {bool} [bRegex=false] Treat as regular expression or not 443 * @param {bool} [bSmart=true] Perform smart filtering or not 444 * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es) 445 * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false) 446 * @dtopt API 447 * @deprecated Since v1.10 448 * 449 * @example 450 * $(document).ready(function() { 451 * var oTable = $('#example').dataTable(); 452 * 453 * // Sometime later - filter... 454 * oTable.fnFilter( 'test string' ); 455 * } ); 456 */ 457 this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive ) 458 { 459 var api = this.api( true ); 460 461 if ( iColumn === null || iColumn === undefined ) { 462 api.search( sInput, bRegex, bSmart, bCaseInsensitive ); 463 } 464 else { 465 api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive ); 466 } 467 468 api.draw(); 469 }; 470 471 472 /** 473 * Get the data for the whole table, an individual row or an individual cell based on the 474 * provided parameters. 475 * @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as 476 * a TR node then the data source for the whole row will be returned. If given as a 477 * TD/TH cell node then iCol will be automatically calculated and the data for the 478 * cell returned. If given as an integer, then this is treated as the aoData internal 479 * data index for the row (see fnGetPosition) and the data for that row used. 480 * @param {int} [col] Optional column index that you want the data of. 481 * @returns {array|object|string} If mRow is undefined, then the data for all rows is 482 * returned. If mRow is defined, just data for that row, and is iCol is 483 * defined, only data for the designated cell is returned. 484 * @dtopt API 485 * @deprecated Since v1.10 486 * 487 * @example 488 * // Row data 489 * $(document).ready(function() { 490 * oTable = $('#example').dataTable(); 491 * 492 * oTable.$('tr').click( function () { 493 * var data = oTable.fnGetData( this ); 494 * // ... do something with the array / object of data for the row 495 * } ); 496 * } ); 497 * 498 * @example 499 * // Individual cell data 500 * $(document).ready(function() { 501 * oTable = $('#example').dataTable(); 502 * 503 * oTable.$('td').click( function () { 504 * var sData = oTable.fnGetData( this ); 505 * alert( 'The cell clicked on had the value of '+sData ); 506 * } ); 507 * } ); 508 */ 509 this.fnGetData = function( src, col ) 510 { 511 var api = this.api( true ); 512 513 if ( src !== undefined ) { 514 var type = src.nodeName ? src.nodeName.toLowerCase() : ''; 515 516 return col !== undefined || type == 'td' || type == 'th' ? 517 api.cell( src, col ).data() : 518 api.row( src ).data() || null; 519 } 520 521 return api.data().toArray(); 522 }; 523 524 525 /** 526 * Get an array of the TR nodes that are used in the table's body. Note that you will 527 * typically want to use the '$' API method in preference to this as it is more 528 * flexible. 529 * @param {int} [iRow] Optional row index for the TR element you want 530 * @returns {array|node} If iRow is undefined, returns an array of all TR elements 531 * in the table's body, or iRow is defined, just the TR element requested. 532 * @dtopt API 533 * @deprecated Since v1.10 534 * 535 * @example 536 * $(document).ready(function() { 537 * var oTable = $('#example').dataTable(); 538 * 539 * // Get the nodes from the table 540 * var nNodes = oTable.fnGetNodes( ); 541 * } ); 542 */ 543 this.fnGetNodes = function( iRow ) 544 { 545 var api = this.api( true ); 546 547 return iRow !== undefined ? 548 api.row( iRow ).node() : 549 api.rows().nodes().flatten().toArray(); 550 }; 551 552 553 /** 554 * Get the array indexes of a particular cell from it's DOM element 555 * and column index including hidden columns 556 * @param {node} node this can either be a TR, TD or TH in the table's body 557 * @returns {int} If nNode is given as a TR, then a single index is returned, or 558 * if given as a cell, an array of [row index, column index (visible), 559 * column index (all)] is given. 560 * @dtopt API 561 * @deprecated Since v1.10 562 * 563 * @example 564 * $(document).ready(function() { 565 * $('#example tbody td').click( function () { 566 * // Get the position of the current data from the node 567 * var aPos = oTable.fnGetPosition( this ); 568 * 569 * // Get the data array for this row 570 * var aData = oTable.fnGetData( aPos[0] ); 571 * 572 * // Update the data array and return the value 573 * aData[ aPos[1] ] = 'clicked'; 574 * this.innerHTML = 'clicked'; 575 * } ); 576 * 577 * // Init DataTables 578 * oTable = $('#example').dataTable(); 579 * } ); 580 */ 581 this.fnGetPosition = function( node ) 582 { 583 var api = this.api( true ); 584 var nodeName = node.nodeName.toUpperCase(); 585 586 if ( nodeName == 'TR' ) { 587 return api.row( node ).index(); 588 } 589 else if ( nodeName == 'TD' || nodeName == 'TH' ) { 590 var cell = api.cell( node ).index(); 591 592 return [ 593 cell.row, 594 cell.columnVisible, 595 cell.column 596 ]; 597 } 598 return null; 599 }; 600 601 602 /** 603 * Check to see if a row is 'open' or not. 604 * @param {node} nTr the table row to check 605 * @returns {boolean} true if the row is currently open, false otherwise 606 * @dtopt API 607 * @deprecated Since v1.10 608 * 609 * @example 610 * $(document).ready(function() { 611 * var oTable; 612 * 613 * // 'open' an information row when a row is clicked on 614 * $('#example tbody tr').click( function () { 615 * if ( oTable.fnIsOpen(this) ) { 616 * oTable.fnClose( this ); 617 * } else { 618 * oTable.fnOpen( this, "Temporary row opened", "info_row" ); 619 * } 620 * } ); 621 * 622 * oTable = $('#example').dataTable(); 623 * } ); 624 */ 625 this.fnIsOpen = function( nTr ) 626 { 627 return this.api( true ).row( nTr ).child.isShown(); 628 }; 629 630 631 /** 632 * This function will place a new row directly after a row which is currently 633 * on display on the page, with the HTML contents that is passed into the 634 * function. This can be used, for example, to ask for confirmation that a 635 * particular record should be deleted. 636 * @param {node} nTr The table row to 'open' 637 * @param {string|node|jQuery} mHtml The HTML to put into the row 638 * @param {string} sClass Class to give the new TD cell 639 * @returns {node} The row opened. Note that if the table row passed in as the 640 * first parameter, is not found in the table, this method will silently 641 * return. 642 * @dtopt API 643 * @deprecated Since v1.10 644 * 645 * @example 646 * $(document).ready(function() { 647 * var oTable; 648 * 649 * // 'open' an information row when a row is clicked on 650 * $('#example tbody tr').click( function () { 651 * if ( oTable.fnIsOpen(this) ) { 652 * oTable.fnClose( this ); 653 * } else { 654 * oTable.fnOpen( this, "Temporary row opened", "info_row" ); 655 * } 656 * } ); 657 * 658 * oTable = $('#example').dataTable(); 659 * } ); 660 */ 661 this.fnOpen = function( nTr, mHtml, sClass ) 662 { 663 return this.api( true ) 664 .row( nTr ) 665 .child( mHtml, sClass ) 666 .show() 667 .child()[0]; 668 }; 669 670 671 /** 672 * Change the pagination - provides the internal logic for pagination in a simple API 673 * function. With this function you can have a DataTables table go to the next, 674 * previous, first or last pages. 675 * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last" 676 * or page number to jump to (integer), note that page 0 is the first page. 677 * @param {bool} [bRedraw=true] Redraw the table or not 678 * @dtopt API 679 * @deprecated Since v1.10 680 * 681 * @example 682 * $(document).ready(function() { 683 * var oTable = $('#example').dataTable(); 684 * oTable.fnPageChange( 'next' ); 685 * } ); 686 */ 687 this.fnPageChange = function ( mAction, bRedraw ) 688 { 689 var api = this.api( true ).page( mAction ); 690 691 if ( bRedraw === undefined || bRedraw ) { 692 api.draw(false); 693 } 694 }; 695 696 697 /** 698 * Show a particular column 699 * @param {int} iCol The column whose display should be changed 700 * @param {bool} bShow Show (true) or hide (false) the column 701 * @param {bool} [bRedraw=true] Redraw the table or not 702 * @dtopt API 703 * @deprecated Since v1.10 704 * 705 * @example 706 * $(document).ready(function() { 707 * var oTable = $('#example').dataTable(); 708 * 709 * // Hide the second column after initialisation 710 * oTable.fnSetColumnVis( 1, false ); 711 * } ); 712 */ 713 this.fnSetColumnVis = function ( iCol, bShow, bRedraw ) 714 { 715 var api = this.api( true ).column( iCol ).visible( bShow ); 716 717 if ( bRedraw === undefined || bRedraw ) { 718 api.columns.adjust().draw(); 719 } 720 }; 721 722 723 /** 724 * Get the settings for a particular table for external manipulation 725 * @returns {object} DataTables settings object. See 726 * {@link DataTable.models.oSettings} 727 * @dtopt API 728 * @deprecated Since v1.10 729 * 730 * @example 731 * $(document).ready(function() { 732 * var oTable = $('#example').dataTable(); 733 * var oSettings = oTable.fnSettings(); 734 * 735 * // Show an example parameter from the settings 736 * alert( oSettings._iDisplayStart ); 737 * } ); 738 */ 739 this.fnSettings = function() 740 { 741 return _fnSettingsFromNode( this[_ext.iApiIndex] ); 742 }; 743 744 745 /** 746 * Sort the table by a particular column 747 * @param {int} iCol the data index to sort on. Note that this will not match the 748 * 'display index' if you have hidden data entries 749 * @dtopt API 750 * @deprecated Since v1.10 751 * 752 * @example 753 * $(document).ready(function() { 754 * var oTable = $('#example').dataTable(); 755 * 756 * // Sort immediately with columns 0 and 1 757 * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] ); 758 * } ); 759 */ 760 this.fnSort = function( aaSort ) 761 { 762 this.api( true ).order( aaSort ).draw(); 763 }; 764 765 766 /** 767 * Attach a sort listener to an element for a given column 768 * @param {node} nNode the element to attach the sort listener to 769 * @param {int} iColumn the column that a click on this node will sort on 770 * @param {function} [fnCallback] callback function when sort is run 771 * @dtopt API 772 * @deprecated Since v1.10 773 * 774 * @example 775 * $(document).ready(function() { 776 * var oTable = $('#example').dataTable(); 777 * 778 * // Sort on column 1, when 'sorter' is clicked on 779 * oTable.fnSortListener( document.getElementById('sorter'), 1 ); 780 * } ); 781 */ 782 this.fnSortListener = function( nNode, iColumn, fnCallback ) 783 { 784 this.api( true ).order.listener( nNode, iColumn, fnCallback ); 785 }; 786 787 788 /** 789 * Update a table cell or row - this method will accept either a single value to 790 * update the cell with, an array of values with one element for each column or 791 * an object in the same format as the original data source. The function is 792 * self-referencing in order to make the multi column updates easier. 793 * @param {object|array|string} mData Data to update the cell/row with 794 * @param {node|int} mRow TR element you want to update or the aoData index 795 * @param {int} [iColumn] The column to update, give as null or undefined to 796 * update a whole row. 797 * @param {bool} [bRedraw=true] Redraw the table or not 798 * @param {bool} [bAction=true] Perform pre-draw actions or not 799 * @returns {int} 0 on success, 1 on error 800 * @dtopt API 801 * @deprecated Since v1.10 802 * 803 * @example 804 * $(document).ready(function() { 805 * var oTable = $('#example').dataTable(); 806 * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell 807 * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row 808 * } ); 809 */ 810 this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction ) 811 { 812 var api = this.api( true ); 813 814 if ( iColumn === undefined || iColumn === null ) { 815 api.row( mRow ).data( mData ); 816 } 817 else { 818 api.cell( mRow, iColumn ).data( mData ); 819 } 820 821 if ( bAction === undefined || bAction ) { 822 api.columns.adjust(); 823 } 824 825 if ( bRedraw === undefined || bRedraw ) { 826 api.draw(); 827 } 828 return 0; 829 }; 830 831 832 /** 833 * Provide a common method for plug-ins to check the version of DataTables being used, in order 834 * to ensure compatibility. 835 * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the 836 * formats "X" and "X.Y" are also acceptable. 837 * @returns {boolean} true if this version of DataTables is greater or equal to the required 838 * version, or false if this version of DataTales is not suitable 839 * @method 840 * @dtopt API 841 * @deprecated Since v1.10 842 * 843 * @example 844 * $(document).ready(function() { 845 * var oTable = $('#example').dataTable(); 846 * alert( oTable.fnVersionCheck( '1.9.0' ) ); 847 * } ); 848 */ 849 this.fnVersionCheck = _ext.fnVersionCheck; 850
vendor: 57,432 bytes, lines 851-2849
851 852 var _that = this; 853 var emptyInit = options === undefined; 854 var len = this.length; 855 856 if ( emptyInit ) { 857 options = {}; 858 } 859 860 this.oApi = this.internal = _ext.internal; 861 862 // Extend with old style plug-in API methods 863 for ( var fn in DataTable.ext.internal ) { 864 if ( fn ) { 865 this[fn] = _fnExternApiFunc(fn); 866 } 867 } 868 869 this.each(function() { 870 // For each initialisation we want to give it a clean initialisation 871 // object that can be bashed around 872 var o = {}; 873 var oInit = len > 1 ? // optimisation for single table case 874 _fnExtend( o, options, true ) : 875 options; 876 877 /*global oInit,_that,emptyInit*/ 878 var i=0, iLen, j, jLen, k, kLen; 879 var sId = this.getAttribute( 'id' ); 880 var bInitHandedOff = false; 881 var defaults = DataTable.defaults; 882 var $this = $(this); 883 884 885 /* Sanity check */ 886 if ( this.nodeName.toLowerCase() != 'table' ) 887 { 888 _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 ); 889 return; 890 } 891 892 /* Backwards compatibility for the defaults */ 893 _fnCompatOpts( defaults ); 894 _fnCompatCols( defaults.column ); 895 896 /* Convert the camel-case defaults to Hungarian */ 897 _fnCamelToHungarian( defaults, defaults, true ); 898 _fnCamelToHungarian( defaults.column, defaults.column, true ); 899 900 /* Setting up the initialisation object */ 901 _fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) ); 902 903 904 905 /* Check to see if we are re-initialising a table */ 906 var allSettings = DataTable.settings; 907 for ( i=0, iLen=allSettings.length ; i<iLen ; i++ ) 908 { 909 var s = allSettings[i]; 910 911 /* Base check on table node */ 912 if ( s.nTable == this || s.nTHead.parentNode == this || (s.nTFoot && s.nTFoot.parentNode == this) ) 913 { 914 var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve; 915 var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy; 916 917 if ( emptyInit || bRetrieve ) 918 { 919 return s.oInstance; 920 } 921 else if ( bDestroy ) 922 { 923 s.oInstance.fnDestroy(); 924 break; 925 } 926 else 927 { 928 _fnLog( s, 0, 'Cannot reinitialise DataTable', 3 ); 929 return; 930 } 931 } 932 933 /* If the element we are initialising has the same ID as a table which was previously 934 * initialised, but the table nodes don't match (from before) then we destroy the old 935 * instance by simply deleting it. This is under the assumption that the table has been 936 * destroyed by other methods. Anyone using non-id selectors will need to do this manually 937 */ 938 if ( s.sTableId == this.id ) 939 { 940 allSettings.splice( i, 1 ); 941 break; 942 } 943 } 944 945 /* Ensure the table has an ID - required for accessibility */ 946 if ( sId === null || sId === "" ) 947 { 948 sId = "DataTables_Table_"+(DataTable.ext._unique++); 949 this.id = sId; 950 } 951 952 /* Create the settings object for this table and set some of the default parameters */ 953 var oSettings = $.extend( true, {}, DataTable.models.oSettings, { 954 "sDestroyWidth": $this[0].style.width, 955 "sInstance": sId, 956 "sTableId": sId 957 } ); 958 oSettings.nTable = this; 959 oSettings.oApi = _that.internal; 960 oSettings.oInit = oInit; 961 962 allSettings.push( oSettings ); 963 964 // Need to add the instance after the instance after the settings object has been added 965 // to the settings array, so we can self reference the table instance if more than one 966 oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable(); 967 968 // Backwards compatibility, before we apply all the defaults 969 _fnCompatOpts( oInit ); 970 971 if ( oInit.oLanguage ) 972 { 973 _fnLanguageCompat( oInit.oLanguage ); 974 } 975 976 // If the length menu is given, but the init display length is not, use the length menu 977 if ( oInit.aLengthMenu && ! oInit.iDisplayLength ) 978 { 979 oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ? 980 oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0]; 981 } 982 983 // Apply the defaults and init options to make a single init object will all 984 // options defined from defaults and instance options. 985 oInit = _fnExtend( $.extend( true, {}, defaults ), oInit ); 986 987 988 // Map the initialisation options onto the settings object 989 _fnMap( oSettings.oFeatures, oInit, [ 990 "bPaginate", 991 "bLengthChange", 992 "bFilter", 993 "bSort", 994 "bSortMulti", 995 "bInfo", 996 "bProcessing", 997 "bAutoWidth", 998 "bSortClasses", 999 "bServerSide", 1000 "bDeferRender" 1001 ] ); 1002 _fnMap( oSettings, oInit, [ 1003 "asStripeClasses", 1004 "ajax", 1005 "fnServerData", 1006 "fnFormatNumber", 1007 "sServerMethod", 1008 "aaSorting", 1009 "aaSortingFixed", 1010 "aLengthMenu", 1011 "sPaginationType", 1012 "sAjaxSource", 1013 "sAjaxDataProp", 1014 "iStateDuration", 1015 "sDom", 1016 "bSortCellsTop", 1017 "iTabIndex", 1018 "fnStateLoadCallback", 1019 "fnStateSaveCallback", 1020 "renderer", 1021 "searchDelay", 1022 "rowId", 1023 [ "iCookieDuration", "iStateDuration" ], // backwards compat 1024 [ "oSearch", "oPreviousSearch" ], 1025 [ "aoSearchCols", "aoPreSearchCols" ], 1026 [ "iDisplayLength", "_iDisplayLength" ], 1027 [ "bJQueryUI", "bJUI" ] 1028 ] ); 1029 _fnMap( oSettings.oScroll, oInit, [ 1030 [ "sScrollX", "sX" ], 1031 [ "sScrollXInner", "sXInner" ], 1032 [ "sScrollY", "sY" ], 1033 [ "bScrollCollapse", "bCollapse" ] 1034 ] ); 1035 _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" ); 1036 1037 /* Callback functions which are array driven */ 1038 _fnCallbackReg( oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user' ); 1039 _fnCallbackReg( oSettings, 'aoServerParams', oInit.fnServerParams, 'user' ); 1040 _fnCallbackReg( oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user' ); 1041 _fnCallbackReg( oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user' ); 1042 _fnCallbackReg( oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user' ); 1043 _fnCallbackReg( oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user' ); 1044 _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user' ); 1045 _fnCallbackReg( oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user' ); 1046 _fnCallbackReg( oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user' ); 1047 _fnCallbackReg( oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user' ); 1048 _fnCallbackReg( oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user' ); 1049 1050 oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId ); 1051 1052 /* Browser support detection */ 1053 _fnBrowserDetect( oSettings ); 1054 1055 var oClasses = oSettings.oClasses; 1056 1057 // @todo Remove in 1.11 1058 if ( oInit.bJQueryUI ) 1059 { 1060 /* Use the JUI classes object for display. You could clone the oStdClasses object if 1061 * you want to have multiple tables with multiple independent classes 1062 */ 1063 $.extend( oClasses, DataTable.ext.oJUIClasses, oInit.oClasses ); 1064 1065 if ( oInit.sDom === defaults.sDom && defaults.sDom === "lfrtip" ) 1066 { 1067 /* Set the DOM to use a layout suitable for jQuery UI's theming */ 1068 oSettings.sDom = '<"H"lfr>t<"F"ip>'; 1069 } 1070 1071 if ( ! oSettings.renderer ) { 1072 oSettings.renderer = 'jqueryui'; 1073 } 1074 else if ( $.isPlainObject( oSettings.renderer ) && ! oSettings.renderer.header ) { 1075 oSettings.renderer.header = 'jqueryui'; 1076 } 1077 } 1078 else 1079 { 1080 $.extend( oClasses, DataTable.ext.classes, oInit.oClasses ); 1081 } 1082 $this.addClass( oClasses.sTable ); 1083 1084 1085 if ( oSettings.iInitDisplayStart === undefined ) 1086 { 1087 /* Display start point, taking into account the save saving */ 1088 oSettings.iInitDisplayStart = oInit.iDisplayStart; 1089 oSettings._iDisplayStart = oInit.iDisplayStart; 1090 } 1091 1092 if ( oInit.iDeferLoading !== null ) 1093 { 1094 oSettings.bDeferLoading = true; 1095 var tmp = $.isArray( oInit.iDeferLoading ); 1096 oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading; 1097 oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading; 1098 } 1099 1100 /* Language definitions */ 1101 var oLanguage = oSettings.oLanguage; 1102 $.extend( true, oLanguage, oInit.oLanguage ); 1103 1104 if ( oLanguage.sUrl ) 1105 { 1106 /* Get the language definitions from a file - because this Ajax call makes the language 1107 * get async to the remainder of this function we use bInitHandedOff to indicate that 1108 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor 1109 */ 1110 $.ajax( { 1111 dataType: 'json', 1112 url: oLanguage.sUrl, 1113 success: function ( json ) { 1114 _fnLanguageCompat( json ); 1115 _fnCamelToHungarian( defaults.oLanguage, json ); 1116 $.extend( true, oLanguage, json ); 1117 _fnInitialise( oSettings ); 1118 }, 1119 error: function () { 1120 // Error occurred loading language file, continue on as best we can 1121 _fnInitialise( oSettings ); 1122 } 1123 } ); 1124 bInitHandedOff = true; 1125 } 1126 1127 /* 1128 * Stripes 1129 */ 1130 if ( oInit.asStripeClasses === null ) 1131 { 1132 oSettings.asStripeClasses =[ 1133 oClasses.sStripeOdd, 1134 oClasses.sStripeEven 1135 ]; 1136 } 1137 1138 /* Remove row stripe classes if they are already on the table row */ 1139 var stripeClasses = oSettings.asStripeClasses; 1140 var rowOne = $this.children('tbody').find('tr').eq(0); 1141 if ( $.inArray( true, $.map( stripeClasses, function(el, i) { 1142 return rowOne.hasClass(el); 1143 } ) ) !== -1 ) { 1144 $('tbody tr', this).removeClass( stripeClasses.join(' ') ); 1145 oSettings.asDestroyStripes = stripeClasses.slice(); 1146 } 1147 1148 /* 1149 * Columns 1150 * See if we should load columns automatically or use defined ones 1151 */ 1152 var anThs = []; 1153 var aoColumnsInit; 1154 var nThead = this.getElementsByTagName('thead'); 1155 if ( nThead.length !== 0 ) 1156 { 1157 _fnDetectHeader( oSettings.aoHeader, nThead[0] ); 1158 anThs = _fnGetUniqueThs( oSettings ); 1159 } 1160 1161 /* If not given a column array, generate one with nulls */ 1162 if ( oInit.aoColumns === null ) 1163 { 1164 aoColumnsInit = []; 1165 for ( i=0, iLen=anThs.length ; i<iLen ; i++ ) 1166 { 1167 aoColumnsInit.push( null ); 1168 } 1169 } 1170 else 1171 { 1172 aoColumnsInit = oInit.aoColumns; 1173 } 1174 1175 /* Add the columns */ 1176 for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ ) 1177 { 1178 _fnAddColumn( oSettings, anThs ? anThs[i] : null ); 1179 } 1180 1181 /* Apply the column definitions */ 1182 _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) { 1183 _fnColumnOptions( oSettings, iCol, oDef ); 1184 } ); 1185 1186 /* HTML5 attribute detection - build an mData object automatically if the 1187 * attributes are found 1188 */ 1189 if ( rowOne.length ) { 1190 var a = function ( cell, name ) { 1191 return cell.getAttribute( 'data-'+name ) !== null ? name : null; 1192 }; 1193 1194 $( rowOne[0] ).children('th, td').each( function (i, cell) { 1195 var col = oSettings.aoColumns[i]; 1196 1197 if ( col.mData === i ) { 1198 var sort = a( cell, 'sort' ) || a( cell, 'order' ); 1199 var filter = a( cell, 'filter' ) || a( cell, 'search' ); 1200 1201 if ( sort !== null || filter !== null ) { 1202 col.mData = { 1203 _: i+'.display', 1204 sort: sort !== null ? i+'.@data-'+sort : undefined, 1205 type: sort !== null ? i+'.@data-'+sort : undefined, 1206 filter: filter !== null ? i+'.@data-'+filter : undefined 1207 }; 1208 1209 _fnColumnOptions( oSettings, i ); 1210 } 1211 } 1212 } ); 1213 } 1214 1215 var features = oSettings.oFeatures; 1216 var loadedInit = function () { 1217 /* 1218 * Sorting 1219 * @todo For modularisation (1.11) this needs to do into a sort start up handler 1220 */ 1221 1222 // If aaSorting is not defined, then we use the first indicator in asSorting 1223 // in case that has been altered, so the default sort reflects that option 1224 if ( oInit.aaSorting === undefined ) { 1225 var sorting = oSettings.aaSorting; 1226 for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) { 1227 sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0]; 1228 } 1229 } 1230 1231 /* Do a first pass on the sorting classes (allows any size changes to be taken into 1232 * account, and also will apply sorting disabled classes if disabled 1233 */ 1234 _fnSortingClasses( oSettings ); 1235 1236 if ( features.bSort ) { 1237 _fnCallbackReg( oSettings, 'aoDrawCallback', function () { 1238 if ( oSettings.bSorted ) { 1239 var aSort = _fnSortFlatten( oSettings ); 1240 var sortedColumns = {}; 1241 1242 $.each( aSort, function (i, val) { 1243 sortedColumns[ val.src ] = val.dir; 1244 } ); 1245 1246 _fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] ); 1247 _fnSortAria( oSettings ); 1248 } 1249 } ); 1250 } 1251 1252 _fnCallbackReg( oSettings, 'aoDrawCallback', function () { 1253 if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) { 1254 _fnSortingClasses( oSettings ); 1255 } 1256 }, 'sc' ); 1257 1258 1259 /* 1260 * Final init 1261 * Cache the header, body and footer as required, creating them if needed 1262 */ 1263 1264 // Work around for Webkit bug 83867 - store the caption-side before removing from doc 1265 var captions = $this.children('caption').each( function () { 1266 this._captionSide = $(this).css('caption-side'); 1267 } ); 1268 1269 var thead = $this.children('thead'); 1270 if ( thead.length === 0 ) { 1271 thead = $('<thead/>').appendTo($this); 1272 } 1273 oSettings.nTHead = thead[0]; 1274 1275 var tbody = $this.children('tbody'); 1276 if ( tbody.length === 0 ) { 1277 tbody = $('<tbody/>').appendTo($this); 1278 } 1279 oSettings.nTBody = tbody[0]; 1280 1281 var tfoot = $this.children('tfoot'); 1282 if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) { 1283 // If we are a scrolling table, and no footer has been given, then we need to create 1284 // a tfoot element for the caption element to be appended to 1285 tfoot = $('<tfoot/>').appendTo($this); 1286 } 1287 1288 if ( tfoot.length === 0 || tfoot.children().length === 0 ) { 1289 $this.addClass( oClasses.sNoFooter ); 1290 } 1291 else if ( tfoot.length > 0 ) { 1292 oSettings.nTFoot = tfoot[0]; 1293 _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot ); 1294 } 1295 1296 /* Check if there is data passing into the constructor */ 1297 if ( oInit.aaData ) { 1298 for ( i=0 ; i<oInit.aaData.length ; i++ ) { 1299 _fnAddData( oSettings, oInit.aaData[ i ] ); 1300 } 1301 } 1302 else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) { 1303 /* Grab the data from the page - only do this when deferred loading or no Ajax 1304 * source since there is no point in reading the DOM data if we are then going 1305 * to replace it with Ajax data 1306 */ 1307 _fnAddTr( oSettings, $(oSettings.nTBody).children('tr') ); 1308 } 1309 1310 /* Copy the data index array */ 1311 oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); 1312 1313 /* Initialisation complete - table can be drawn */ 1314 oSettings.bInitialised = true; 1315 1316 /* Check if we need to initialise the table (it might not have been handed off to the 1317 * language processor) 1318 */ 1319 if ( bInitHandedOff === false ) { 1320 _fnInitialise( oSettings ); 1321 } 1322 }; 1323 1324 /* Must be done after everything which can be overridden by the state saving! */ 1325 if ( oInit.bStateSave ) 1326 { 1327 features.bStateSave = true; 1328 _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' ); 1329 _fnLoadState( oSettings, oInit, loadedInit ); 1330 } 1331 else { 1332 loadedInit(); 1333 } 1334 1335 } ); 1336 _that = null; 1337 return this; 1338 }; 1339 1340 1341 /* 1342 * It is useful to have variables which are scoped locally so only the 1343 * DataTables functions can access them and they don't leak into global space. 1344 * At the same time these functions are often useful over multiple files in the 1345 * core and API, so we list, or at least document, all variables which are used 1346 * by DataTables as private variables here. This also ensures that there is no 1347 * clashing of variable names and that they can easily referenced for reuse. 1348 */ 1349 1350 1351 // Defined else where 1352 // _selector_run 1353 // _selector_opts 1354 // _selector_first 1355 // _selector_row_indexes 1356 1357 var _ext; // DataTable.ext 1358 var _Api; // DataTable.Api 1359 var _api_register; // DataTable.Api.register 1360 var _api_registerPlural; // DataTable.Api.registerPlural 1361 1362 var _re_dic = {}; 1363 var _re_new_lines = /[\r\n]/g; 1364 var _re_html = /<.*?>/g; 1365 1366 // This is not strict ISO8601 - Date.parse() is quite lax, although 1367 // implementations differ between browsers. 1368 var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/; 1369 1370 // Escape regular expression special characters 1371 var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' ); 1372 1373 // http://en.wikipedia.org/wiki/Foreign_exchange_market 1374 // - \u20BD - Russian ruble. 1375 // - \u20a9 - South Korean Won 1376 // - \u20BA - Turkish Lira 1377 // - \u20B9 - Indian Rupee 1378 // - R - Brazil (R$) and South Africa 1379 // - fr - Swiss Franc 1380 // - kr - Swedish krona, Norwegian krone and Danish krone 1381 // - \u2009 is thin space and \u202F is narrow no-break space, both used in many 1382 // standards as thousands separators. 1383 var _re_formatted_numeric = /[',$£â¬Â¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi; 1384 1385 1386 var _empty = function ( d ) { 1387 return !d || d === true || d === '-' ? true : false; 1388 }; 1389 1390 1391 var _intVal = function ( s ) { 1392 var integer = parseInt( s, 10 ); 1393 return !isNaN(integer) && isFinite(s) ? integer : null; 1394 }; 1395 1396 // Convert from a formatted number with characters other than `.` as the 1397 // decimal place, to a Javascript number 1398 var _numToDecimal = function ( num, decimalPoint ) { 1399 // Cache created regular expressions for speed as this function is called often 1400 if ( ! _re_dic[ decimalPoint ] ) { 1401 _re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' ); 1402 } 1403 return typeof num === 'string' && decimalPoint !== '.' ? 1404 num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) : 1405 num; 1406 }; 1407 1408 1409 var _isNumber = function ( d, decimalPoint, formatted ) { 1410 var strType = typeof d === 'string'; 1411 1412 // If empty return immediately so there must be a number if it is a 1413 // formatted string (this stops the string "k", or "kr", etc being detected 1414 // as a formatted number for currency 1415 if ( _empty( d ) ) { 1416 return true; 1417 } 1418 1419 if ( decimalPoint && strType ) { 1420 d = _numToDecimal( d, decimalPoint ); 1421 } 1422 1423 if ( formatted && strType ) { 1424 d = d.replace( _re_formatted_numeric, '' ); 1425 } 1426 1427 return !isNaN( parseFloat(d) ) && isFinite( d ); 1428 }; 1429 1430 1431 // A string without HTML in it can be considered to be HTML still 1432 var _isHtml = function ( d ) { 1433 return _empty( d ) || typeof d === 'string'; 1434 }; 1435 1436 1437 var _htmlNumeric = function ( d, decimalPoint, formatted ) { 1438 if ( _empty( d ) ) { 1439 return true; 1440 } 1441 1442 var html = _isHtml( d ); 1443 return ! html ? 1444 null : 1445 _isNumber( _stripHtml( d ), decimalPoint, formatted ) ? 1446 true : 1447 null; 1448 }; 1449 1450 1451 var _pluck = function ( a, prop, prop2 ) { 1452 var out = []; 1453 var i=0, ien=a.length; 1454 1455 // Could have the test in the loop for slightly smaller code, but speed 1456 // is essential here 1457 if ( prop2 !== undefined ) { 1458 for ( ; i<ien ; i++ ) { 1459 if ( a[i] && a[i][ prop ] ) { 1460 out.push( a[i][ prop ][ prop2 ] ); 1461 } 1462 } 1463 } 1464 else { 1465 for ( ; i<ien ; i++ ) { 1466 if ( a[i] ) { 1467 out.push( a[i][ prop ] ); 1468 } 1469 } 1470 } 1471 1472 return out; 1473 }; 1474 1475 1476 // Basically the same as _pluck, but rather than looping over `a` we use `order` 1477 // as the indexes to pick from `a` 1478 var _pluck_order = function ( a, order, prop, prop2 ) 1479 { 1480 var out = []; 1481 var i=0, ien=order.length; 1482 1483 // Could have the test in the loop for slightly smaller code, but speed 1484 // is essential here 1485 if ( prop2 !== undefined ) { 1486 for ( ; i<ien ; i++ ) { 1487 if ( a[ order[i] ][ prop ] ) { 1488 out.push( a[ order[i] ][ prop ][ prop2 ] ); 1489 } 1490 } 1491 } 1492 else { 1493 for ( ; i<ien ; i++ ) { 1494 out.push( a[ order[i] ][ prop ] ); 1495 } 1496 } 1497 1498 return out; 1499 }; 1500 1501 1502 var _range = function ( len, start ) 1503 { 1504 var out = []; 1505 var end; 1506 1507 if ( start === undefined ) { 1508 start = 0; 1509 end = len; 1510 } 1511 else { 1512 end = start; 1513 start = len; 1514 } 1515 1516 for ( var i=start ; i<end ; i++ ) { 1517 out.push( i ); 1518 } 1519 1520 return out; 1521 }; 1522 1523 1524 var _removeEmpty = function ( a ) 1525 { 1526 var out = []; 1527 1528 for ( var i=0, ien=a.length ; i<ien ; i++ ) { 1529 if ( a[i] ) { // careful - will remove all falsy values! 1530 out.push( a[i] ); 1531 } 1532 } 1533 1534 return out; 1535 }; 1536 1537 1538 var _stripHtml = function ( d ) { 1539 return d.replace( _re_html, '' ); 1540 }; 1541 1542 1543 /** 1544 * Find the unique elements in a source array. 1545 * 1546 * @param {array} src Source array 1547 * @return {array} Array of unique items 1548 * @ignore 1549 */ 1550 var _unique = function ( src ) 1551 { 1552 // A faster unique method is to use object keys to identify used values, 1553 // but this doesn't work with arrays or objects, which we must also 1554 // consider. See jsperf.com/compare-array-unique-versions/4 for more 1555 // information. 1556 var 1557 out = [], 1558 val, 1559 i, ien=src.length, 1560 j, k=0; 1561 1562 again: for ( i=0 ; i<ien ; i++ ) { 1563 val = src[i]; 1564 1565 for ( j=0 ; j<k ; j++ ) { 1566 if ( out[j] === val ) { 1567 continue again; 1568 } 1569 } 1570 1571 out.push( val ); 1572 k++; 1573 } 1574 1575 return out; 1576 }; 1577 1578 1579 /** 1580 * DataTables utility methods 1581 * 1582 * This namespace provides helper methods that DataTables uses internally to 1583 * create a DataTable, but which are not exclusively used only for DataTables. 1584 * These methods can be used by extension authors to save the duplication of 1585 * code. 1586 * 1587 * @namespace 1588 */ 1589 DataTable.util = { 1590 /** 1591 * Throttle the calls to a function. Arguments and context are maintained 1592 * for the throttled function. 1593 * 1594 * @param {function} fn Function to be called 1595 * @param {integer} freq Call frequency in mS 1596 * @return {function} Wrapped function 1597 */ 1598 throttle: function ( fn, freq ) { 1599 var 1600 frequency = freq !== undefined ? freq : 200, 1601 last, 1602 timer; 1603 1604 return function () { 1605 var 1606 that = this, 1607 now = +new Date(), 1608 args = arguments; 1609 1610 if ( last && now < last + frequency ) { 1611 clearTimeout( timer ); 1612 1613 timer = setTimeout( function () { 1614 last = undefined; 1615 fn.apply( that, args ); 1616 }, frequency ); 1617 } 1618 else { 1619 last = now; 1620 fn.apply( that, args ); 1621 } 1622 }; 1623 }, 1624 1625 1626 /** 1627 * Escape a string such that it can be used in a regular expression 1628 * 1629 * @param {string} val string to escape 1630 * @returns {string} escaped string 1631 */ 1632 escapeRegex: function ( val ) { 1633 return val.replace( _re_escape_regex, '\\$1' ); 1634 } 1635 }; 1636 1637 1638 1639 /** 1640 * Create a mapping object that allows camel case parameters to be looked up 1641 * for their Hungarian counterparts. The mapping is stored in a private 1642 * parameter called `_hungarianMap` which can be accessed on the source object. 1643 * @param {object} o 1644 * @memberof DataTable#oApi 1645 */ 1646 function _fnHungarianMap ( o ) 1647 { 1648 var 1649 hungarian = 'a aa ai ao as b fn i m o s ', 1650 match, 1651 newKey, 1652 map = {}; 1653 1654 $.each( o, function (key, val) { 1655 match = key.match(/^([^A-Z]+?)([A-Z])/); 1656 1657 if ( match && hungarian.indexOf(match[1]+' ') !== -1 ) 1658 { 1659 newKey = key.replace( match[0], match[2].toLowerCase() ); 1660 map[ newKey ] = key; 1661 1662 if ( match[1] === 'o' ) 1663 { 1664 _fnHungarianMap( o[key] ); 1665 } 1666 } 1667 } ); 1668 1669 o._hungarianMap = map; 1670 } 1671 1672 1673 /** 1674 * Convert from camel case parameters to Hungarian, based on a Hungarian map 1675 * created by _fnHungarianMap. 1676 * @param {object} src The model object which holds all parameters that can be 1677 * mapped. 1678 * @param {object} user The object to convert from camel case to Hungarian. 1679 * @param {boolean} force When set to `true`, properties which already have a 1680 * Hungarian value in the `user` object will be overwritten. Otherwise they 1681 * won't be. 1682 * @memberof DataTable#oApi 1683 */ 1684 function _fnCamelToHungarian ( src, user, force ) 1685 { 1686 if ( ! src._hungarianMap ) { 1687 _fnHungarianMap( src ); 1688 } 1689 1690 var hungarianKey; 1691 1692 $.each( user, function (key, val) { 1693 hungarianKey = src._hungarianMap[ key ]; 1694 1695 if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) ) 1696 { 1697 // For objects, we need to buzz down into the object to copy parameters 1698 if ( hungarianKey.charAt(0) === 'o' ) 1699 { 1700 // Copy the camelCase options over to the hungarian 1701 if ( ! user[ hungarianKey ] ) { 1702 user[ hungarianKey ] = {}; 1703 } 1704 $.extend( true, user[hungarianKey], user[key] ); 1705 1706 _fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force ); 1707 } 1708 else { 1709 user[hungarianKey] = user[ key ]; 1710 } 1711 } 1712 } ); 1713 } 1714 1715 1716 /** 1717 * Language compatibility - when certain options are given, and others aren't, we 1718 * need to duplicate the values over, in order to provide backwards compatibility 1719 * with older language files. 1720 * @param {object} oSettings dataTables settings object 1721 * @memberof DataTable#oApi 1722 */ 1723 function _fnLanguageCompat( lang ) 1724 { 1725 var defaults = DataTable.defaults.oLanguage; 1726 var zeroRecords = lang.sZeroRecords; 1727 1728 /* Backwards compatibility - if there is no sEmptyTable given, then use the same as 1729 * sZeroRecords - assuming that is given. 1730 */ 1731 if ( ! lang.sEmptyTable && zeroRecords && 1732 defaults.sEmptyTable === "No data available in table" ) 1733 { 1734 _fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' ); 1735 } 1736 1737 /* Likewise with loading records */ 1738 if ( ! lang.sLoadingRecords && zeroRecords && 1739 defaults.sLoadingRecords === "Loading..." ) 1740 { 1741 _fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' ); 1742 } 1743 1744 // Old parameter name of the thousands separator mapped onto the new 1745 if ( lang.sInfoThousands ) { 1746 lang.sThousands = lang.sInfoThousands; 1747 } 1748 1749 var decimal = lang.sDecimal; 1750 if ( decimal ) { 1751 _addNumericSort( decimal ); 1752 } 1753 } 1754 1755 1756 /** 1757 * Map one parameter onto another 1758 * @param {object} o Object to map 1759 * @param {*} knew The new parameter name 1760 * @param {*} old The old parameter name 1761 */ 1762 var _fnCompatMap = function ( o, knew, old ) { 1763 if ( o[ knew ] !== undefined ) { 1764 o[ old ] = o[ knew ]; 1765 } 1766 }; 1767 1768 1769 /** 1770 * Provide backwards compatibility for the main DT options. Note that the new 1771 * options are mapped onto the old parameters, so this is an external interface 1772 * change only. 1773 * @param {object} init Object to map 1774 */ 1775 function _fnCompatOpts ( init ) 1776 { 1777 _fnCompatMap( init, 'ordering', 'bSort' ); 1778 _fnCompatMap( init, 'orderMulti', 'bSortMulti' ); 1779 _fnCompatMap( init, 'orderClasses', 'bSortClasses' ); 1780 _fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' ); 1781 _fnCompatMap( init, 'order', 'aaSorting' ); 1782 _fnCompatMap( init, 'orderFixed', 'aaSortingFixed' ); 1783 _fnCompatMap( init, 'paging', 'bPaginate' ); 1784 _fnCompatMap( init, 'pagingType', 'sPaginationType' ); 1785 _fnCompatMap( init, 'pageLength', 'iDisplayLength' ); 1786 _fnCompatMap( init, 'searching', 'bFilter' ); 1787 1788 // Boolean initialisation of x-scrolling 1789 if ( typeof init.sScrollX === 'boolean' ) { 1790 init.sScrollX = init.sScrollX ? '100%' : ''; 1791 } 1792 if ( typeof init.scrollX === 'boolean' ) { 1793 init.scrollX = init.scrollX ? '100%' : ''; 1794 } 1795 1796 // Column search objects are in an array, so it needs to be converted 1797 // element by element 1798 var searchCols = init.aoSearchCols; 1799 1800 if ( searchCols ) { 1801 for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) { 1802 if ( searchCols[i] ) { 1803 _fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] ); 1804 } 1805 } 1806 } 1807 } 1808 1809 1810 /** 1811 * Provide backwards compatibility for column options. Note that the new options 1812 * are mapped onto the old parameters, so this is an external interface change 1813 * only. 1814 * @param {object} init Object to map 1815 */ 1816 function _fnCompatCols ( init ) 1817 { 1818 _fnCompatMap( init, 'orderable', 'bSortable' ); 1819 _fnCompatMap( init, 'orderData', 'aDataSort' ); 1820 _fnCompatMap( init, 'orderSequence', 'asSorting' ); 1821 _fnCompatMap( init, 'orderDataType', 'sortDataType' ); 1822 1823 // orderData can be given as an integer 1824 var dataSort = init.aDataSort; 1825 if ( dataSort && ! $.isArray( dataSort ) ) { 1826 init.aDataSort = [ dataSort ]; 1827 } 1828 } 1829 1830 1831 /** 1832 * Browser feature detection for capabilities, quirks 1833 * @param {object} settings dataTables settings object 1834 * @memberof DataTable#oApi 1835 */ 1836 function _fnBrowserDetect( settings ) 1837 { 1838 // We don't need to do this every time DataTables is constructed, the values 1839 // calculated are specific to the browser and OS configuration which we 1840 // don't expect to change between initialisations 1841 if ( ! DataTable.__browser ) { 1842 var browser = {}; 1843 DataTable.__browser = browser; 1844 1845 // Scrolling feature / quirks detection 1846 var n = $('<div/>') 1847 .css( { 1848 position: 'fixed', 1849 top: 0, 1850 left: $(window).scrollLeft()*-1, // allow for scrolling 1851 height: 1, 1852 width: 1, 1853 overflow: 'hidden' 1854 } ) 1855 .append( 1856 $('<div/>') 1857 .css( { 1858 position: 'absolute', 1859 top: 1, 1860 left: 1, 1861 width: 100, 1862 overflow: 'scroll' 1863 } ) 1864 .append( 1865 $('<div/>') 1866 .css( { 1867 width: '100%', 1868 height: 10 1869 } ) 1870 ) 1871 ) 1872 .appendTo( 'body' ); 1873 1874 var outer = n.children(); 1875 var inner = outer.children(); 1876 1877 // Numbers below, in order, are: 1878 // inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth 1879 // 1880 // IE6 XP: 100 100 100 83 1881 // IE7 Vista: 100 100 100 83 1882 // IE 8+ Windows: 83 83 100 83 1883 // Evergreen Windows: 83 83 100 83 1884 // Evergreen Mac with scrollbars: 85 85 100 85 1885 // Evergreen Mac without scrollbars: 100 100 100 100 1886 1887 // Get scrollbar width 1888 browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth; 1889 1890 // IE6/7 will oversize a width 100% element inside a scrolling element, to 1891 // include the width of the scrollbar, while other browsers ensure the inner 1892 // element is contained without forcing scrolling 1893 browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100; 1894 1895 // In rtl text layout, some browsers (most, but not all) will place the 1896 // scrollbar on the left, rather than the right. 1897 browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1; 1898 1899 // IE8- don't provide height and width for getBoundingClientRect 1900 browser.bBounding = n[0].getBoundingClientRect().width ? true : false; 1901 1902 n.remove(); 1903 } 1904 1905 $.extend( settings.oBrowser, DataTable.__browser ); 1906 settings.oScroll.iBarWidth = DataTable.__browser.barWidth; 1907 } 1908 1909 1910 /** 1911 * Array.prototype reduce[Right] method, used for browsers which don't support 1912 * JS 1.6. Done this way to reduce code size, since we iterate either way 1913 * @param {object} settings dataTables settings object 1914 * @memberof DataTable#oApi 1915 */ 1916 function _fnReduce ( that, fn, init, start, end, inc ) 1917 { 1918 var 1919 i = start, 1920 value, 1921 isSet = false; 1922 1923 if ( init !== undefined ) { 1924 value = init; 1925 isSet = true; 1926 } 1927 1928 while ( i !== end ) { 1929 if ( ! that.hasOwnProperty(i) ) { 1930 continue; 1931 } 1932 1933 value = isSet ? 1934 fn( value, that[i], i, that ) : 1935 that[i]; 1936 1937 isSet = true; 1938 i += inc; 1939 } 1940 1941 return value; 1942 } 1943 1944 /** 1945 * Add a column to the list used for the table with default values 1946 * @param {object} oSettings dataTables settings object 1947 * @param {node} nTh The th element for this column 1948 * @memberof DataTable#oApi 1949 */ 1950 function _fnAddColumn( oSettings, nTh ) 1951 { 1952 // Add column to aoColumns array 1953 var oDefaults = DataTable.defaults.column; 1954 var iCol = oSettings.aoColumns.length; 1955 var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, { 1956 "nTh": nTh ? nTh : document.createElement('th'), 1957 "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '', 1958 "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol], 1959 "mData": oDefaults.mData ? oDefaults.mData : iCol, 1960 idx: iCol 1961 } ); 1962 oSettings.aoColumns.push( oCol ); 1963 1964 // Add search object for column specific search. Note that the `searchCols[ iCol ]` 1965 // passed into extend can be undefined. This allows the user to give a default 1966 // with only some of the parameters defined, and also not give a default 1967 var searchCols = oSettings.aoPreSearchCols; 1968 searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] ); 1969 1970 // Use the default column options function to initialise classes etc 1971 _fnColumnOptions( oSettings, iCol, $(nTh).data() ); 1972 } 1973 1974 1975 /** 1976 * Apply options for a column 1977 * @param {object} oSettings dataTables settings object 1978 * @param {int} iCol column index to consider 1979 * @param {object} oOptions object with sType, bVisible and bSearchable etc 1980 * @memberof DataTable#oApi 1981 */ 1982 function _fnColumnOptions( oSettings, iCol, oOptions ) 1983 { 1984 var oCol = oSettings.aoColumns[ iCol ]; 1985 var oClasses = oSettings.oClasses; 1986 var th = $(oCol.nTh); 1987 1988 // Try to get width information from the DOM. We can't get it from CSS 1989 // as we'd need to parse the CSS stylesheet. `width` option can override 1990 if ( ! oCol.sWidthOrig ) { 1991 // Width attribute 1992 oCol.sWidthOrig = th.attr('width') || null; 1993 1994 // Style attribute 1995 var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/); 1996 if ( t ) { 1997 oCol.sWidthOrig = t[1]; 1998 } 1999 } 2000 2001 /* User specified column options */ 2002 if ( oOptions !== undefined && oOptions !== null ) 2003 { 2004 // Backwards compatibility 2005 _fnCompatCols( oOptions ); 2006 2007 // Map camel case parameters to their Hungarian counterparts 2008 _fnCamelToHungarian( DataTable.defaults.column, oOptions ); 2009 2010 /* Backwards compatibility for mDataProp */ 2011 if ( oOptions.mDataProp !== undefined && !oOptions.mData ) 2012 { 2013 oOptions.mData = oOptions.mDataProp; 2014 } 2015 2016 if ( oOptions.sType ) 2017 { 2018 oCol._sManualType = oOptions.sType; 2019 } 2020 2021 // `class` is a reserved word in Javascript, so we need to provide 2022 // the ability to use a valid name for the camel case input 2023 if ( oOptions.className && ! oOptions.sClass ) 2024 { 2025 oOptions.sClass = oOptions.className; 2026 } 2027 2028 $.extend( oCol, oOptions ); 2029 _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" ); 2030 2031 /* iDataSort to be applied (backwards compatibility), but aDataSort will take 2032 * priority if defined 2033 */ 2034 if ( oOptions.iDataSort !== undefined ) 2035 { 2036 oCol.aDataSort = [ oOptions.iDataSort ]; 2037 } 2038 _fnMap( oCol, oOptions, "aDataSort" ); 2039 } 2040 2041 /* Cache the data get and set functions for speed */ 2042 var mDataSrc = oCol.mData; 2043 var mData = _fnGetObjectDataFn( mDataSrc ); 2044 var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null; 2045 2046 var attrTest = function( src ) { 2047 return typeof src === 'string' && src.indexOf('@') !== -1; 2048 }; 2049 oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && ( 2050 attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter) 2051 ); 2052 oCol._setter = null; 2053 2054 oCol.fnGetData = function (rowData, type, meta) { 2055 var innerData = mData( rowData, type, undefined, meta ); 2056 2057 return mRender && type ? 2058 mRender( innerData, type, rowData, meta ) : 2059 innerData; 2060 }; 2061 oCol.fnSetData = function ( rowData, val, meta ) { 2062 return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta ); 2063 }; 2064 2065 // Indicate if DataTables should read DOM data as an object or array 2066 // Used in _fnGetRowElements 2067 if ( typeof mDataSrc !== 'number' ) { 2068 oSettings._rowReadObject = true; 2069 } 2070 2071 /* Feature sorting overrides column specific when off */ 2072 if ( !oSettings.oFeatures.bSort ) 2073 { 2074 oCol.bSortable = false; 2075 th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called 2076 } 2077 2078 /* Check that the class assignment is correct for sorting */ 2079 var bAsc = $.inArray('asc', oCol.asSorting) !== -1; 2080 var bDesc = $.inArray('desc', oCol.asSorting) !== -1; 2081 if ( !oCol.bSortable || (!bAsc && !bDesc) ) 2082 { 2083 oCol.sSortingClass = oClasses.sSortableNone; 2084 oCol.sSortingClassJUI = ""; 2085 } 2086 else if ( bAsc && !bDesc ) 2087 { 2088 oCol.sSortingClass = oClasses.sSortableAsc; 2089 oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed; 2090 } 2091 else if ( !bAsc && bDesc ) 2092 { 2093 oCol.sSortingClass = oClasses.sSortableDesc; 2094 oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed; 2095 } 2096 else 2097 { 2098 oCol.sSortingClass = oClasses.sSortable; 2099 oCol.sSortingClassJUI = oClasses.sSortJUI; 2100 } 2101 } 2102 2103 2104 /** 2105 * Adjust the table column widths for new data. Note: you would probably want to 2106 * do a redraw after calling this function! 2107 * @param {object} settings dataTables settings object 2108 * @memberof DataTable#oApi 2109 */ 2110 function _fnAdjustColumnSizing ( settings ) 2111 { 2112 /* Not interested in doing column width calculation if auto-width is disabled */ 2113 if ( settings.oFeatures.bAutoWidth !== false ) 2114 { 2115 var columns = settings.aoColumns; 2116 2117 _fnCalculateColumnWidths( settings ); 2118 for ( var i=0 , iLen=columns.length ; i<iLen ; i++ ) 2119 { 2120 columns[i].nTh.style.width = columns[i].sWidth; 2121 } 2122 } 2123 2124 var scroll = settings.oScroll; 2125 if ( scroll.sY !== '' || scroll.sX !== '') 2126 { 2127 _fnScrollDraw( settings ); 2128 } 2129 2130 _fnCallbackFire( settings, null, 'column-sizing', [settings] ); 2131 } 2132 2133 2134 /** 2135 * Covert the index of a visible column to the index in the data array (take account 2136 * of hidden columns) 2137 * @param {object} oSettings dataTables settings object 2138 * @param {int} iMatch Visible column index to lookup 2139 * @returns {int} i the data index 2140 * @memberof DataTable#oApi 2141 */ 2142 function _fnVisibleToColumnIndex( oSettings, iMatch ) 2143 { 2144 var aiVis = _fnGetColumns( oSettings, 'bVisible' ); 2145 2146 return typeof aiVis[iMatch] === 'number' ? 2147 aiVis[iMatch] : 2148 null; 2149 } 2150 2151 2152 /** 2153 * Covert the index of an index in the data array and convert it to the visible 2154 * column index (take account of hidden columns) 2155 * @param {int} iMatch Column index to lookup 2156 * @param {object} oSettings dataTables settings object 2157 * @returns {int} i the data index 2158 * @memberof DataTable#oApi 2159 */ 2160 function _fnColumnIndexToVisible( oSettings, iMatch ) 2161 { 2162 var aiVis = _fnGetColumns( oSettings, 'bVisible' ); 2163 var iPos = $.inArray( iMatch, aiVis ); 2164 2165 return iPos !== -1 ? iPos : null; 2166 } 2167 2168 2169 /** 2170 * Get the number of visible columns 2171 * @param {object} oSettings dataTables settings object 2172 * @returns {int} i the number of visible columns 2173 * @memberof DataTable#oApi 2174 */ 2175 function _fnVisbleColumns( oSettings ) 2176 { 2177 var vis = 0; 2178 2179 // No reduce in IE8, use a loop for now 2180 $.each( oSettings.aoColumns, function ( i, col ) { 2181 if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) { 2182 vis++; 2183 } 2184 } ); 2185 2186 return vis; 2187 } 2188 2189 2190 /** 2191 * Get an array of column indexes that match a given property 2192 * @param {object} oSettings dataTables settings object 2193 * @param {string} sParam Parameter in aoColumns to look for - typically 2194 * bVisible or bSearchable 2195 * @returns {array} Array of indexes with matched properties 2196 * @memberof DataTable#oApi 2197 */ 2198 function _fnGetColumns( oSettings, sParam ) 2199 { 2200 var a = []; 2201 2202 $.map( oSettings.aoColumns, function(val, i) { 2203 if ( val[sParam] ) { 2204 a.push( i ); 2205 } 2206 } ); 2207 2208 return a; 2209 } 2210 2211 2212 /** 2213 * Calculate the 'type' of a column 2214 * @param {object} settings dataTables settings object 2215 * @memberof DataTable#oApi 2216 */ 2217 function _fnColumnTypes ( settings ) 2218 { 2219 var columns = settings.aoColumns; 2220 var data = settings.aoData; 2221 var types = DataTable.ext.type.detect; 2222 var i, ien, j, jen, k, ken; 2223 var col, cell, detectedType, cache; 2224 2225 // For each column, spin over the 2226 for ( i=0, ien=columns.length ; i<ien ; i++ ) { 2227 col = columns[i]; 2228 cache = []; 2229 2230 if ( ! col.sType && col._sManualType ) { 2231 col.sType = col._sManualType; 2232 } 2233 else if ( ! col.sType ) { 2234 for ( j=0, jen=types.length ; j<jen ; j++ ) { 2235 for ( k=0, ken=data.length ; k<ken ; k++ ) { 2236 // Use a cache array so we only need to get the type data 2237 // from the formatter once (when using multiple detectors) 2238 if ( cache[k] === undefined ) { 2239 cache[k] = _fnGetCellData( settings, k, i, 'type' ); 2240 } 2241 2242 detectedType = types[j]( cache[k], settings ); 2243 2244 // If null, then this type can't apply to this column, so 2245 // rather than testing all cells, break out. There is an 2246 // exception for the last type which is `html`. We need to 2247 // scan all rows since it is possible to mix string and HTML 2248 // types 2249 if ( ! detectedType && j !== types.length-1 ) { 2250 break; 2251 } 2252 2253 // Only a single match is needed for html type since it is 2254 // bottom of the pile and very similar to string 2255 if ( detectedType === 'html' ) { 2256 break; 2257 } 2258 } 2259 2260 // Type is valid for all data points in the column - use this 2261 // type 2262 if ( detectedType ) { 2263 col.sType = detectedType; 2264 break; 2265 } 2266 } 2267 2268 // Fall back - if no type was detected, always use string 2269 if ( ! col.sType ) { 2270 col.sType = 'string'; 2271 } 2272 } 2273 } 2274 } 2275 2276 2277 /** 2278 * Take the column definitions and static columns arrays and calculate how 2279 * they relate to column indexes. The callback function will then apply the 2280 * definition found for a column to a suitable configuration object. 2281 * @param {object} oSettings dataTables settings object 2282 * @param {array} aoColDefs The aoColumnDefs array that is to be applied 2283 * @param {array} aoCols The aoColumns array that defines columns individually 2284 * @param {function} fn Callback function - takes two parameters, the calculated 2285 * column index and the definition for that column. 2286 * @memberof DataTable#oApi 2287 */ 2288 function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn ) 2289 { 2290 var i, iLen, j, jLen, k, kLen, def; 2291 var columns = oSettings.aoColumns; 2292 2293 // Column definitions with aTargets 2294 if ( aoColDefs ) 2295 { 2296 /* Loop over the definitions array - loop in reverse so first instance has priority */ 2297 for ( i=aoColDefs.length-1 ; i>=0 ; i-- ) 2298 { 2299 def = aoColDefs[i]; 2300 2301 /* Each definition can target multiple columns, as it is an array */ 2302 var aTargets = def.targets !== undefined ? 2303 def.targets : 2304 def.aTargets; 2305 2306 if ( ! $.isArray( aTargets ) ) 2307 { 2308 aTargets = [ aTargets ]; 2309 } 2310 2311 for ( j=0, jLen=aTargets.length ; j<jLen ; j++ ) 2312 { 2313 if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 ) 2314 { 2315 /* Add columns that we don't yet know about */ 2316 while( columns.length <= aTargets[j] ) 2317 { 2318 _fnAddColumn( oSettings ); 2319 } 2320 2321 /* Integer, basic index */ 2322 fn( aTargets[j], def ); 2323 } 2324 else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 ) 2325 { 2326 /* Negative integer, right to left column counting */ 2327 fn( columns.length+aTargets[j], def ); 2328 } 2329 else if ( typeof aTargets[j] === 'string' ) 2330 { 2331 /* Class name matching on TH element */ 2332 for ( k=0, kLen=columns.length ; k<kLen ; k++ ) 2333 { 2334 if ( aTargets[j] == "_all" || 2335 $(columns[k].nTh).hasClass( aTargets[j] ) ) 2336 { 2337 fn( k, def ); 2338 } 2339 } 2340 } 2341 } 2342 } 2343 } 2344 2345 // Statically defined columns array 2346 if ( aoCols ) 2347 { 2348 for ( i=0, iLen=aoCols.length ; i<iLen ; i++ ) 2349 { 2350 fn( i, aoCols[i] ); 2351 } 2352 } 2353 } 2354 2355 /** 2356 * Add a data array to the table, creating DOM node etc. This is the parallel to 2357 * _fnGatherData, but for adding rows from a Javascript source, rather than a 2358 * DOM source. 2359 * @param {object} oSettings dataTables settings object 2360 * @param {array} aData data array to be added 2361 * @param {node} [nTr] TR element to add to the table - optional. If not given, 2362 * DataTables will create a row automatically 2363 * @param {array} [anTds] Array of TD|TH elements for the row - must be given 2364 * if nTr is. 2365 * @returns {int} >=0 if successful (index of new aoData entry), -1 if failed 2366 * @memberof DataTable#oApi 2367 */ 2368 function _fnAddData ( oSettings, aDataIn, nTr, anTds ) 2369 { 2370 /* Create the object for storing information about this new row */ 2371 var iRow = oSettings.aoData.length; 2372 var oData = $.extend( true, {}, DataTable.models.oRow, { 2373 src: nTr ? 'dom' : 'data', 2374 idx: iRow 2375 } ); 2376 2377 oData._aData = aDataIn; 2378 oSettings.aoData.push( oData ); 2379 2380 /* Create the cells */ 2381 var nTd, sThisType; 2382 var columns = oSettings.aoColumns; 2383 2384 // Invalidate the column types as the new data needs to be revalidated 2385 for ( var i=0, iLen=columns.length ; i<iLen ; i++ ) 2386 { 2387 columns[i].sType = null; 2388 } 2389 2390 /* Add to the display array */ 2391 oSettings.aiDisplayMaster.push( iRow ); 2392 2393 var id = oSettings.rowIdFn( aDataIn ); 2394 if ( id !== undefined ) { 2395 oSettings.aIds[ id ] = oData; 2396 } 2397 2398 /* Create the DOM information, or register it if already present */ 2399 if ( nTr || ! oSettings.oFeatures.bDeferRender ) 2400 { 2401 _fnCreateTr( oSettings, iRow, nTr, anTds ); 2402 } 2403 2404 return iRow; 2405 } 2406 2407 2408 /** 2409 * Add one or more TR elements to the table. Generally we'd expect to 2410 * use this for reading data from a DOM sourced table, but it could be 2411 * used for an TR element. Note that if a TR is given, it is used (i.e. 2412 * it is not cloned). 2413 * @param {object} settings dataTables settings object 2414 * @param {array|node|jQuery} trs The TR element(s) to add to the table 2415 * @returns {array} Array of indexes for the added rows 2416 * @memberof DataTable#oApi 2417 */ 2418 function _fnAddTr( settings, trs ) 2419 { 2420 var row; 2421 2422 // Allow an individual node to be passed in 2423 if ( ! (trs instanceof $) ) { 2424 trs = $(trs); 2425 } 2426 2427 return trs.map( function (i, el) { 2428 row = _fnGetRowElements( settings, el ); 2429 return _fnAddData( settings, row.data, el, row.cells ); 2430 } ); 2431 } 2432 2433 2434 /** 2435 * Take a TR element and convert it to an index in aoData 2436 * @param {object} oSettings dataTables settings object 2437 * @param {node} n the TR element to find 2438 * @returns {int} index if the node is found, null if not 2439 * @memberof DataTable#oApi 2440 */ 2441 function _fnNodeToDataIndex( oSettings, n ) 2442 { 2443 return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null; 2444 } 2445 2446 2447 /** 2448 * Take a TD element and convert it into a column data index (not the visible index) 2449 * @param {object} oSettings dataTables settings object 2450 * @param {int} iRow The row number the TD/TH can be found in 2451 * @param {node} n The TD/TH element to find 2452 * @returns {int} index if the node is found, -1 if not 2453 * @memberof DataTable#oApi 2454 */ 2455 function _fnNodeToColumnIndex( oSettings, iRow, n ) 2456 { 2457 return $.inArray( n, oSettings.aoData[ iRow ].anCells ); 2458 } 2459 2460 2461 /** 2462 * Get the data for a given cell from the internal cache, taking into account data mapping 2463 * @param {object} settings dataTables settings object 2464 * @param {int} rowIdx aoData row id 2465 * @param {int} colIdx Column index 2466 * @param {string} type data get type ('display', 'type' 'filter' 'sort') 2467 * @returns {*} Cell data 2468 * @memberof DataTable#oApi 2469 */ 2470 function _fnGetCellData( settings, rowIdx, colIdx, type ) 2471 { 2472 var draw = settings.iDraw; 2473 var col = settings.aoColumns[colIdx]; 2474 var rowData = settings.aoData[rowIdx]._aData; 2475 var defaultContent = col.sDefaultContent; 2476 var cellData = col.fnGetData( rowData, type, { 2477 settings: settings, 2478 row: rowIdx, 2479 col: colIdx 2480 } ); 2481 2482 if ( cellData === undefined ) { 2483 if ( settings.iDrawError != draw && defaultContent === null ) { 2484 _fnLog( settings, 0, "Requested unknown parameter "+ 2485 (typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+ 2486 " for row "+rowIdx+", column "+colIdx, 4 ); 2487 settings.iDrawError = draw; 2488 } 2489 return defaultContent; 2490 } 2491 2492 // When the data source is null and a specific data type is requested (i.e. 2493 // not the original data), we can use default column data 2494 if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) { 2495 cellData = defaultContent; 2496 } 2497 else if ( typeof cellData === 'function' ) { 2498 // If the data source is a function, then we run it and use the return, 2499 // executing in the scope of the data object (for instances) 2500 return cellData.call( rowData ); 2501 } 2502 2503 if ( cellData === null && type == 'display' ) { 2504 return ''; 2505 } 2506 return cellData; 2507 } 2508 2509 2510 /** 2511 * Set the value for a specific cell, into the internal data cache 2512 * @param {object} settings dataTables settings object 2513 * @param {int} rowIdx aoData row id 2514 * @param {int} colIdx Column index 2515 * @param {*} val Value to set 2516 * @memberof DataTable#oApi 2517 */ 2518 function _fnSetCellData( settings, rowIdx, colIdx, val ) 2519 { 2520 var col = settings.aoColumns[colIdx]; 2521 var rowData = settings.aoData[rowIdx]._aData; 2522 2523 col.fnSetData( rowData, val, { 2524 settings: settings, 2525 row: rowIdx, 2526 col: colIdx 2527 } ); 2528 } 2529 2530 2531 // Private variable that is used to match action syntax in the data property object 2532 var __reArray = /\[.*?\]$/; 2533 var __reFn = /\(\)$/; 2534 2535 /** 2536 * Split string on periods, taking into account escaped periods 2537 * @param {string} str String to split 2538 * @return {array} Split string 2539 */ 2540 function _fnSplitObjNotation( str ) 2541 { 2542 return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) { 2543 return s.replace(/\\\./g, '.'); 2544 } ); 2545 } 2546 2547 2548 /** 2549 * Return a function that can be used to get data from a source object, taking 2550 * into account the ability to use nested objects as a source 2551 * @param {string|int|function} mSource The data source for the object 2552 * @returns {function} Data get function 2553 * @memberof DataTable#oApi 2554 */ 2555 function _fnGetObjectDataFn( mSource ) 2556 { 2557 if ( $.isPlainObject( mSource ) ) 2558 { 2559 /* Build an object of get functions, and wrap them in a single call */ 2560 var o = {}; 2561 $.each( mSource, function (key, val) { 2562 if ( val ) { 2563 o[key] = _fnGetObjectDataFn( val ); 2564 } 2565 } ); 2566 2567 return function (data, type, row, meta) { 2568 var t = o[type] || o._; 2569 return t !== undefined ? 2570 t(data, type, row, meta) : 2571 data; 2572 }; 2573 } 2574 else if ( mSource === null ) 2575 { 2576 /* Give an empty string for rendering / sorting etc */ 2577 return function (data) { // type, row and meta also passed, but not used 2578 return data; 2579 }; 2580 } 2581 else if ( typeof mSource === 'function' ) 2582 { 2583 return function (data, type, row, meta) { 2584 return mSource( data, type, row, meta ); 2585 }; 2586 } 2587 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || 2588 mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) ) 2589 { 2590 /* If there is a . in the source string then the data source is in a 2591 * nested object so we loop over the data for each level to get the next 2592 * level down. On each loop we test for undefined, and if found immediately 2593 * return. This allows entire objects to be missing and sDefaultContent to 2594 * be used if defined, rather than throwing an error 2595 */ 2596 var fetchData = function (data, type, src) { 2597 var arrayNotation, funcNotation, out, innerSrc; 2598 2599 if ( src !== "" ) 2600 { 2601 var a = _fnSplitObjNotation( src ); 2602 2603 for ( var i=0, iLen=a.length ; i<iLen ; i++ ) 2604 { 2605 // Check if we are dealing with special notation 2606 arrayNotation = a[i].match(__reArray); 2607 funcNotation = a[i].match(__reFn); 2608 2609 if ( arrayNotation ) 2610 { 2611 // Array notation 2612 a[i] = a[i].replace(__reArray, ''); 2613 2614 // Condition allows simply [] to be passed in 2615 if ( a[i] !== "" ) { 2616 data = data[ a[i] ]; 2617 } 2618 out = []; 2619 2620 // Get the remainder of the nested object to get 2621 a.splice( 0, i+1 ); 2622 innerSrc = a.join('.'); 2623 2624 // Traverse each entry in the array getting the properties requested 2625 if ( $.isArray( data ) ) { 2626 for ( var j=0, jLen=data.length ; j<jLen ; j++ ) { 2627 out.push( fetchData( data[j], type, innerSrc ) ); 2628 } 2629 } 2630 2631 // If a string is given in between the array notation indicators, that 2632 // is used to join the strings together, otherwise an array is returned 2633 var join = arrayNotation[0].substring(1, arrayNotation[0].length-1); 2634 data = (join==="") ? out : out.join(join); 2635 2636 // The inner call to fetchData has already traversed through the remainder 2637 // of the source requested, so we exit from the loop 2638 break; 2639 } 2640 else if ( funcNotation ) 2641 { 2642 // Function call 2643 a[i] = a[i].replace(__reFn, ''); 2644 data = data[ a[i] ](); 2645 continue; 2646 } 2647 2648 if ( data === null || data[ a[i] ] === undefined ) 2649 { 2650 return undefined; 2651 } 2652 data = data[ a[i] ]; 2653 } 2654 } 2655 2656 return data; 2657 }; 2658 2659 return function (data, type) { // row and meta also passed, but not used 2660 return fetchData( data, type, mSource ); 2661 }; 2662 } 2663 else 2664 { 2665 /* Array or flat object mapping */ 2666 return function (data, type) { // row and meta also passed, but not used 2667 return data[mSource]; 2668 }; 2669 } 2670 } 2671 2672 2673 /** 2674 * Return a function that can be used to set data from a source object, taking 2675 * into account the ability to use nested objects as a source 2676 * @param {string|int|function} mSource The data source for the object 2677 * @returns {function} Data set function 2678 * @memberof DataTable#oApi 2679 */ 2680 function _fnSetObjectDataFn( mSource ) 2681 { 2682 if ( $.isPlainObject( mSource ) ) 2683 { 2684 /* Unlike get, only the underscore (global) option is used for for 2685 * setting data since we don't know the type here. This is why an object 2686 * option is not documented for `mData` (which is read/write), but it is 2687 * for `mRender` which is read only. 2688 */ 2689 return _fnSetObjectDataFn( mSource._ ); 2690 } 2691 else if ( mSource === null ) 2692 { 2693 /* Nothing to do when the data source is null */ 2694 return function () {}; 2695 } 2696 else if ( typeof mSource === 'function' ) 2697 { 2698 return function (data, val, meta) { 2699 mSource( data, 'set', val, meta ); 2700 }; 2701 } 2702 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || 2703 mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) ) 2704 { 2705 /* Like the get, we need to get data from a nested object */ 2706 var setData = function (data, val, src) { 2707 var a = _fnSplitObjNotation( src ), b; 2708 var aLast = a[a.length-1]; 2709 var arrayNotation, funcNotation, o, innerSrc; 2710 2711 for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ ) 2712 { 2713 // Check if we are dealing with an array notation request 2714 arrayNotation = a[i].match(__reArray); 2715 funcNotation = a[i].match(__reFn); 2716 2717 if ( arrayNotation ) 2718 { 2719 a[i] = a[i].replace(__reArray, ''); 2720 data[ a[i] ] = []; 2721 2722 // Get the remainder of the nested object to set so we can recurse 2723 b = a.slice(); 2724 b.splice( 0, i+1 ); 2725 innerSrc = b.join('.'); 2726 2727 // Traverse each entry in the array setting the properties requested 2728 if ( $.isArray( val ) ) 2729 { 2730 for ( var j=0, jLen=val.length ; j<jLen ; j++ ) 2731 { 2732 o = {}; 2733 setData( o, val[j], innerSrc ); 2734 data[ a[i] ].push( o ); 2735 } 2736 } 2737 else 2738 { 2739 // We've been asked to save data to an array, but it 2740 // isn't array data to be saved. Best that can be done 2741 // is to just save the value. 2742 data[ a[i] ] = val; 2743 } 2744 2745 // The inner call to setData has already traversed through the remainder 2746 // of the source and has set the data, thus we can exit here 2747 return; 2748 } 2749 else if ( funcNotation ) 2750 { 2751 // Function call 2752 a[i] = a[i].replace(__reFn, ''); 2753 data = data[ a[i] ]( val ); 2754 } 2755 2756 // If the nested object doesn't currently exist - since we are 2757 // trying to set the value - create it 2758 if ( data[ a[i] ] === null || data[ a[i] ] === undefined ) 2759 { 2760 data[ a[i] ] = {}; 2761 } 2762 data = data[ a[i] ]; 2763 } 2764 2765 // Last item in the input - i.e, the actual set 2766 if ( aLast.match(__reFn ) ) 2767 { 2768 // Function call 2769 data = data[ aLast.replace(__reFn, '') ]( val ); 2770 } 2771 else 2772 { 2773 // If array notation is used, we just want to strip it and use the property name 2774 // and assign the value. If it isn't used, then we get the result we want anyway 2775 data[ aLast.replace(__reArray, '') ] = val; 2776 } 2777 }; 2778 2779 return function (data, val) { // meta is also passed in, but not used 2780 return setData( data, val, mSource ); 2781 }; 2782 } 2783 else 2784 { 2785 /* Array or flat object mapping */ 2786 return function (data, val) { // meta is also passed in, but not used 2787 data[mSource] = val; 2788 }; 2789 } 2790 } 2791 2792 2793 /** 2794 * Return an array with the full table data 2795 * @param {object} oSettings dataTables settings object 2796 * @returns array {array} aData Master data array 2797 * @memberof DataTable#oApi 2798 */ 2799 function _fnGetDataMaster ( settings ) 2800 { 2801 return _pluck( settings.aoData, '_aData' ); 2802 } 2803 2804 2805 /** 2806 * Nuke the table 2807 * @param {object} oSettings dataTables settings object 2808 * @memberof DataTable#oApi 2809 */ 2810 function _fnClearTable( settings ) 2811 { 2812 settings.aoData.length = 0; 2813 settings.aiDisplayMaster.length = 0; 2814 settings.aiDisplay.length = 0; 2815 settings.aIds = {}; 2816 } 2817 2818 2819 /** 2820 * Take an array of integers (index array) and remove a target integer (value - not 2821 * the key!) 2822 * @param {array} a Index array to target 2823 * @param {int} iTarget value to find 2824 * @memberof DataTable#oApi 2825 */ 2826 function _fnDeleteIndex( a, iTarget, splice ) 2827 { 2828 var iTargetIndex = -1; 2829 2830 for ( var i=0, iLen=a.length ; i<iLen ; i++ ) 2831 { 2832 if ( a[i] == iTarget ) 2833 { 2834 iTargetIndex = i; 2835 } 2836 else if ( a[i] > iTarget ) 2837 { 2838 a[i]--; 2839 } 2840 } 2841 2842 if ( iTargetIndex != -1 && splice === undefined ) 2843 { 2844 a.splice( iTargetIndex, 1 ); 2845 } 2846 } 2847 2848 2849 /**
2850 * Mark cached data as invalid such that a re-read of the data will occur when 2851 * the cached data is next requested. Also update from the data source object. 2852 * 2853 * @param {object} settings DataTables settings object 2854 * @param {int} rowIdx Row index to invalidate 2855 * @param {string} [src] Source to invalidate from: undefined, 'auto', 'dom' 2856 * or 'data' 2857 * @param {int} [colIdx] Column index to invalidate. If undefined the whole 2858 * row will be invalidated 2859 * @memberof DataTable#oApi 2860 * 2861 * @todo For the modularisation of v1.11 this will need to become a callback, so 2862 * the sort and filter methods can subscribe to it. That will required 2863 * initialisation options for sorting, which is why it is not already baked in 2864 */ 2865 function _fnInvalidate( settings, rowIdx, src, colIdx ) 2866 { 2867 var row = settings.aoData[ rowIdx ]; 2868 var i, ien; 2869 var cellWrite = function ( cell, col ) { 2870 // This is very frustrating, but in IE if you just write directly 2871 // to innerHTML, and elements that are overwritten are GC'ed, 2872 // even if there is a reference to them elsewhere 2873 while ( cell.childNodes.length ) { 2874 cell.removeChild( cell.firstChild ); 2875 } 2876 2877 cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' ); 2878 }; 2879 2880 // Are we reading last data from DOM or the data object? 2881 if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) { 2882 // Read the data from the DOM 2883 row._aData = _fnGetRowElements( 2884 settings, row, colIdx, colIdx === undefined ? undefined : row._aData 2885 ) 2886 .data; 2887 } 2888 else { 2889 // Reading from data object, update the DOM 2890 var cells = row.anCells; 2891 2892 if ( cells ) { 2893 if ( colIdx !== undefined ) { 2894 cellWrite( cells[colIdx], colIdx ); 2895 } 2896 else { 2897 for ( i=0, ien=cells.length ; i<ien ; i++ ) { 2898 cellWrite( cells[i], i ); 2899 } 2900 } 2901 } 2902 } 2903 2904 // For both row and cell invalidation, the cached data for sorting and 2905 // filtering is nulled out 2906 row._aSortData = null; 2907 row._aFilterData = null; 2908 2909 // Invalidate the type for a specific column (if given) or all columns since 2910 // the data might have changed 2911 var cols = settings.aoColumns; 2912 if ( colIdx !== undefined ) { 2913 cols[ colIdx ].sType = null; 2914 } 2915 else { 2916 for ( i=0, ien=cols.length ; i<ien ; i++ ) { 2917 cols[i].sType = null; 2918 } 2919 2920 // Update DataTables special `DT_*` attributes for the row 2921 _fnRowAttributes( settings, row ); 2922 } 2923 } 2924 2925 2926 /** 2927 * Build a data source object from an HTML row, reading the contents of the 2928 * cells that are in the row. 2929 * 2930 * @param {object} settings DataTables settings object 2931 * @param {node|object} TR element from which to read data or existing row 2932 * object from which to re-read the data from the cells 2933 * @param {int} [colIdx] Optional column index 2934 * @param {array|object} [d] Data source object. If `colIdx` is given then this 2935 * parameter should also be given and will be used to write the data into. 2936 * Only the column in question will be written 2937 * @returns {object} Object with two parameters: `data` the data read, in 2938 * document order, and `cells` and array of nodes (they can be useful to the 2939 * caller, so rather than needing a second traversal to get them, just return 2940 * them from here). 2941 * @memberof DataTable#oApi 2942 */ 2943 function _fnGetRowElements( settings, row, colIdx, d ) 2944 { 2945 var 2946 tds = [], 2947 td = row.firstChild, 2948 name, col, o, i=0, contents, 2949 columns = settings.aoColumns, 2950 objectRead = settings._rowReadObject; 2951 2952 // Allow the data object to be passed in, or construct 2953 d = d !== undefined ? 2954 d : 2955 objectRead ? 2956 {} : 2957 []; 2958 2959 var attr = function ( str, td ) { 2960 if ( typeof str === 'string' ) { 2961 var idx = str.indexOf('@'); 2962 2963 if ( idx !== -1 ) { 2964 var attr = str.substring( idx+1 ); 2965 var setter = _fnSetObjectDataFn( str ); 2966 setter( d, td.getAttribute( attr ) ); 2967 } 2968 } 2969 }; 2970 2971 // Read data from a cell and store into the data object 2972 var cellProcess = function ( cell ) { 2973 if ( colIdx === undefined || colIdx === i ) { 2974 col = columns[i]; 2975 contents = $.trim(cell.innerHTML); 2976 2977 if ( col && col._bAttrSrc ) { 2978 var setter = _fnSetObjectDataFn( col.mData._ ); 2979 setter( d, contents ); 2980 2981 attr( col.mData.sort, cell ); 2982 attr( col.mData.type, cell ); 2983 attr( col.mData.filter, cell ); 2984 } 2985 else { 2986 // Depending on the `data` option for the columns the data can 2987 // be read to either an object or an array.
vendor: 11,978 bytes, lines 2988-3445
2988 if ( objectRead ) { 2989 if ( ! col._setter ) { 2990 // Cache the setter function 2991 col._setter = _fnSetObjectDataFn( col.mData ); 2992 } 2993 col._setter( d, contents ); 2994 } 2995 else { 2996 d[i] = contents; 2997 } 2998 } 2999 } 3000 3001 i++; 3002 }; 3003 3004 if ( td ) { 3005 // `tr` element was passed in 3006 while ( td ) { 3007 name = td.nodeName.toUpperCase(); 3008 3009 if ( name == "TD" || name == "TH" ) { 3010 cellProcess( td ); 3011 tds.push( td ); 3012 } 3013 3014 td = td.nextSibling; 3015 } 3016 } 3017 else { 3018 // Existing row object passed in 3019 tds = row.anCells; 3020 3021 for ( var j=0, jen=tds.length ; j<jen ; j++ ) { 3022 cellProcess( tds[j] ); 3023 } 3024 } 3025 3026 // Read the ID from the DOM if present 3027 var rowNode = row.firstChild ? row : row.nTr; 3028 3029 if ( rowNode ) { 3030 var id = rowNode.getAttribute( 'id' ); 3031 3032 if ( id ) { 3033 _fnSetObjectDataFn( settings.rowId )( d, id ); 3034 } 3035 } 3036 3037 return { 3038 data: d, 3039 cells: tds 3040 }; 3041 } 3042 /** 3043 * Create a new TR element (and it's TD children) for a row 3044 * @param {object} oSettings dataTables settings object 3045 * @param {int} iRow Row to consider 3046 * @param {node} [nTrIn] TR element to add to the table - optional. If not given, 3047 * DataTables will create a row automatically 3048 * @param {array} [anTds] Array of TD|TH elements for the row - must be given 3049 * if nTr is. 3050 * @memberof DataTable#oApi 3051 */ 3052 function _fnCreateTr ( oSettings, iRow, nTrIn, anTds ) 3053 { 3054 var 3055 row = oSettings.aoData[iRow], 3056 rowData = row._aData, 3057 cells = [], 3058 nTr, nTd, oCol, 3059 i, iLen; 3060 3061 if ( row.nTr === null ) 3062 { 3063 nTr = nTrIn || document.createElement('tr'); 3064 3065 row.nTr = nTr; 3066 row.anCells = cells; 3067 3068 /* Use a private property on the node to allow reserve mapping from the node 3069 * to the aoData array for fast look up 3070 */ 3071 nTr._DT_RowIndex = iRow; 3072 3073 /* Special parameters can be given by the data source to be used on the row */ 3074 _fnRowAttributes( oSettings, row ); 3075 3076 /* Process each column */ 3077 for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) 3078 { 3079 oCol = oSettings.aoColumns[i]; 3080 3081 nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType ); 3082 nTd._DT_CellIndex = { 3083 row: iRow, 3084 column: i 3085 }; 3086 3087 cells.push( nTd ); 3088 3089 // Need to create the HTML if new, or if a rendering function is defined 3090 if ( (!nTrIn || oCol.mRender || oCol.mData !== i) && 3091 (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display') 3092 ) { 3093 nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' ); 3094 } 3095 3096 /* Add user defined class */ 3097 if ( oCol.sClass ) 3098 { 3099 nTd.className += ' '+oCol.sClass; 3100 } 3101 3102 // Visibility - add or remove as required 3103 if ( oCol.bVisible && ! nTrIn ) 3104 { 3105 nTr.appendChild( nTd ); 3106 } 3107 else if ( ! oCol.bVisible && nTrIn ) 3108 { 3109 nTd.parentNode.removeChild( nTd ); 3110 } 3111 3112 if ( oCol.fnCreatedCell ) 3113 { 3114 oCol.fnCreatedCell.call( oSettings.oInstance, 3115 nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i 3116 ); 3117 } 3118 } 3119 3120 _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] ); 3121 } 3122 3123 // Remove once webkit bug 131819 and Chromium bug 365619 have been resolved 3124 // and deployed 3125 row.nTr.setAttribute( 'role', 'row' ); 3126 } 3127 3128 3129 /** 3130 * Add attributes to a row based on the special `DT_*` parameters in a data 3131 * source object. 3132 * @param {object} settings DataTables settings object 3133 * @param {object} DataTables row object for the row to be modified 3134 * @memberof DataTable#oApi 3135 */ 3136 function _fnRowAttributes( settings, row ) 3137 { 3138 var tr = row.nTr; 3139 var data = row._aData; 3140 3141 if ( tr ) { 3142 var id = settings.rowIdFn( data ); 3143 3144 if ( id ) { 3145 tr.id = id; 3146 } 3147 3148 if ( data.DT_RowClass ) { 3149 // Remove any classes added by DT_RowClass before 3150 var a = data.DT_RowClass.split(' '); 3151 row.__rowc = row.__rowc ? 3152 _unique( row.__rowc.concat( a ) ) : 3153 a; 3154 3155 $(tr) 3156 .removeClass( row.__rowc.join(' ') ) 3157 .addClass( data.DT_RowClass ); 3158 } 3159 3160 if ( data.DT_RowAttr ) { 3161 $(tr).attr( data.DT_RowAttr ); 3162 } 3163 3164 if ( data.DT_RowData ) { 3165 $(tr).data( data.DT_RowData ); 3166 } 3167 } 3168 } 3169 3170 3171 /** 3172 * Create the HTML header for the table 3173 * @param {object} oSettings dataTables settings object 3174 * @memberof DataTable#oApi 3175 */ 3176 function _fnBuildHead( oSettings ) 3177 { 3178 var i, ien, cell, row, column; 3179 var thead = oSettings.nTHead; 3180 var tfoot = oSettings.nTFoot; 3181 var createHeader = $('th, td', thead).length === 0; 3182 var classes = oSettings.oClasses; 3183 var columns = oSettings.aoColumns; 3184 3185 if ( createHeader ) { 3186 row = $('<tr/>').appendTo( thead ); 3187 } 3188 3189 for ( i=0, ien=columns.length ; i<ien ; i++ ) { 3190 column = columns[i]; 3191 cell = $( column.nTh ).addClass( column.sClass ); 3192 3193 if ( createHeader ) { 3194 cell.appendTo( row ); 3195 } 3196 3197 // 1.11 move into sorting 3198 if ( oSettings.oFeatures.bSort ) { 3199 cell.addClass( column.sSortingClass ); 3200 3201 if ( column.bSortable !== false ) { 3202 cell 3203 .attr( 'tabindex', oSettings.iTabIndex ) 3204 .attr( 'aria-controls', oSettings.sTableId ); 3205 3206 _fnSortAttachListener( oSettings, column.nTh, i ); 3207 } 3208 } 3209 3210 if ( column.sTitle != cell[0].innerHTML ) { 3211 cell.html( column.sTitle ); 3212 } 3213 3214 _fnRenderer( oSettings, 'header' )( 3215 oSettings, cell, column, classes 3216 ); 3217 } 3218 3219 if ( createHeader ) { 3220 _fnDetectHeader( oSettings.aoHeader, thead ); 3221 } 3222 3223 /* ARIA role for the rows */ 3224 $(thead).find('>tr').attr('role', 'row'); 3225 3226 /* Deal with the footer - add classes if required */ 3227 $(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH ); 3228 $(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH ); 3229 3230 // Cache the footer cells. Note that we only take the cells from the first 3231 // row in the footer. If there is more than one row the user wants to 3232 // interact with, they need to use the table().foot() method. Note also this 3233 // allows cells to be used for multiple columns using colspan 3234 if ( tfoot !== null ) { 3235 var cells = oSettings.aoFooter[0]; 3236 3237 for ( i=0, ien=cells.length ; i<ien ; i++ ) { 3238 column = columns[i]; 3239 column.nTf = cells[i].cell; 3240 3241 if ( column.sClass ) { 3242 $(column.nTf).addClass( column.sClass ); 3243 } 3244 } 3245 } 3246 } 3247 3248 3249 /** 3250 * Draw the header (or footer) element based on the column visibility states. The 3251 * methodology here is to use the layout array from _fnDetectHeader, modified for 3252 * the instantaneous column visibility, to construct the new layout. The grid is 3253 * traversed over cell at a time in a rows x columns grid fashion, although each 3254 * cell insert can cover multiple elements in the grid - which is tracks using the 3255 * aApplied array. Cell inserts in the grid will only occur where there isn't 3256 * already a cell in that position. 3257 * @param {object} oSettings dataTables settings object 3258 * @param array {objects} aoSource Layout array from _fnDetectHeader 3259 * @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc, 3260 * @memberof DataTable#oApi 3261 */ 3262 function _fnDrawHead( oSettings, aoSource, bIncludeHidden ) 3263 { 3264 var i, iLen, j, jLen, k, kLen, n, nLocalTr; 3265 var aoLocal = []; 3266 var aApplied = []; 3267 var iColumns = oSettings.aoColumns.length; 3268 var iRowspan, iColspan; 3269 3270 if ( ! aoSource ) 3271 { 3272 return; 3273 } 3274 3275 if ( bIncludeHidden === undefined ) 3276 { 3277 bIncludeHidden = false; 3278 } 3279 3280 /* Make a copy of the master layout array, but without the visible columns in it */ 3281 for ( i=0, iLen=aoSource.length ; i<iLen ; i++ ) 3282 { 3283 aoLocal[i] = aoSource[i].slice(); 3284 aoLocal[i].nTr = aoSource[i].nTr; 3285 3286 /* Remove any columns which are currently hidden */ 3287 for ( j=iColumns-1 ; j>=0 ; j-- ) 3288 { 3289 if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden ) 3290 { 3291 aoLocal[i].splice( j, 1 ); 3292 } 3293 } 3294 3295 /* Prep the applied array - it needs an element for each row */ 3296 aApplied.push( [] ); 3297 } 3298 3299 for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ ) 3300 { 3301 nLocalTr = aoLocal[i].nTr; 3302 3303 /* All cells are going to be replaced, so empty out the row */ 3304 if ( nLocalTr ) 3305 { 3306 while( (n = nLocalTr.firstChild) ) 3307 { 3308 nLocalTr.removeChild( n ); 3309 } 3310 } 3311 3312 for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ ) 3313 { 3314 iRowspan = 1; 3315 iColspan = 1; 3316 3317 /* Check to see if there is already a cell (row/colspan) covering our target 3318 * insert point. If there is, then there is nothing to do. 3319 */ 3320 if ( aApplied[i][j] === undefined ) 3321 { 3322 nLocalTr.appendChild( aoLocal[i][j].cell ); 3323 aApplied[i][j] = 1; 3324 3325 /* Expand the cell to cover as many rows as needed */ 3326 while ( aoLocal[i+iRowspan] !== undefined && 3327 aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell ) 3328 { 3329 aApplied[i+iRowspan][j] = 1; 3330 iRowspan++; 3331 } 3332 3333 /* Expand the cell to cover as many columns as needed */ 3334 while ( aoLocal[i][j+iColspan] !== undefined && 3335 aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell ) 3336 { 3337 /* Must update the applied array over the rows for the columns */ 3338 for ( k=0 ; k<iRowspan ; k++ ) 3339 { 3340 aApplied[i+k][j+iColspan] = 1; 3341 } 3342 iColspan++; 3343 } 3344 3345 /* Do the actual expansion in the DOM */ 3346 $(aoLocal[i][j].cell) 3347 .attr('rowspan', iRowspan) 3348 .attr('colspan', iColspan); 3349 } 3350 } 3351 } 3352 } 3353 3354 3355 /** 3356 * Insert the required TR nodes into the table for display 3357 * @param {object} oSettings dataTables settings object 3358 * @memberof DataTable#oApi 3359 */ 3360 function _fnDraw( oSettings ) 3361 { 3362 /* Provide a pre-callback function which can be used to cancel the draw is false is returned */ 3363 var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] ); 3364 if ( $.inArray( false, aPreDraw ) !== -1 ) 3365 { 3366 _fnProcessingDisplay( oSettings, false ); 3367 return; 3368 } 3369 3370 var i, iLen, n; 3371 var anRows = []; 3372 var iRowCount = 0; 3373 var asStripeClasses = oSettings.asStripeClasses; 3374 var iStripes = asStripeClasses.length; 3375 var iOpenRows = oSettings.aoOpenRows.length; 3376 var oLang = oSettings.oLanguage; 3377 var iInitDisplayStart = oSettings.iInitDisplayStart; 3378 var bServerSide = _fnDataSource( oSettings ) == 'ssp'; 3379 var aiDisplay = oSettings.aiDisplay; 3380 3381 oSettings.bDrawing = true; 3382 3383 /* Check and see if we have an initial draw position from state saving */ 3384 if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 ) 3385 { 3386 oSettings._iDisplayStart = bServerSide ? 3387 iInitDisplayStart : 3388 iInitDisplayStart >= oSettings.fnRecordsDisplay() ? 3389 0 : 3390 iInitDisplayStart; 3391 3392 oSettings.iInitDisplayStart = -1; 3393 } 3394 3395 var iDisplayStart = oSettings._iDisplayStart; 3396 var iDisplayEnd = oSettings.fnDisplayEnd(); 3397 3398 /* Server-side processing draw intercept */ 3399 if ( oSettings.bDeferLoading ) 3400 { 3401 oSettings.bDeferLoading = false; 3402 oSettings.iDraw++; 3403 _fnProcessingDisplay( oSettings, false ); 3404 } 3405 else if ( !bServerSide ) 3406 { 3407 oSettings.iDraw++; 3408 } 3409 else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) ) 3410 { 3411 return; 3412 } 3413 3414 if ( aiDisplay.length !== 0 ) 3415 { 3416 var iStart = bServerSide ? 0 : iDisplayStart; 3417 var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd; 3418 3419 for ( var j=iStart ; j<iEnd ; j++ ) 3420 { 3421 var iDataIndex = aiDisplay[j]; 3422 var aoData = oSettings.aoData[ iDataIndex ]; 3423 if ( aoData.nTr === null ) 3424 { 3425 _fnCreateTr( oSettings, iDataIndex ); 3426 } 3427 3428 var nRow = aoData.nTr; 3429 3430 /* Remove the old striping classes and then add the new one */ 3431 if ( iStripes !== 0 ) 3432 { 3433 var sStripe = asStripeClasses[ iRowCount % iStripes ]; 3434 if ( aoData._sRowStripe != sStripe ) 3435 { 3436 $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe ); 3437 aoData._sRowStripe = sStripe; 3438 } 3439 } 3440 3441 // Row callback functions - might want to manipulate the row 3442 // iRowCount and j are not currently documented. Are they at all 3443 // useful? 3444 _fnCallbackFire( oSettings, 'aoRowCallback', null, 3445 [nRow, aoData._aData, iRowCount, j
vendor: 9,503 bytes, lines 3445-3799
3445] ); 3446 3447 anRows.push( nRow ); 3448 iRowCount++; 3449 } 3450 } 3451 else 3452 { 3453 /* Table is empty - create a row with an empty message in it */ 3454 var sZero = oLang.sZeroRecords; 3455 if ( oSettings.iDraw == 1 && _fnDataSource( oSettings ) == 'ajax' ) 3456 { 3457 sZero = oLang.sLoadingRecords; 3458 } 3459 else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 ) 3460 { 3461 sZero = oLang.sEmptyTable; 3462 } 3463 3464 anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } ) 3465 .append( $('<td />', { 3466 'valign': 'top', 3467 'colSpan': _fnVisbleColumns( oSettings ), 3468 'class': oSettings.oClasses.sRowEmpty 3469 } ).html( sZero ) )[0]; 3470 } 3471 3472 /* Header and footer callbacks */ 3473 _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0], 3474 _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] ); 3475 3476 _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0], 3477 _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] ); 3478 3479 var body = $(oSettings.nTBody); 3480 3481 body.children().detach(); 3482 body.append( $(anRows) ); 3483 3484 /* Call all required callback functions for the end of a draw */ 3485 _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] ); 3486 3487 /* Draw is complete, sorting and filtering must be as well */ 3488 oSettings.bSorted = false; 3489 oSettings.bFiltered = false; 3490 oSettings.bDrawing = false; 3491 } 3492 3493 3494 /** 3495 * Redraw the table - taking account of the various features which are enabled 3496 * @param {object} oSettings dataTables settings object 3497 * @param {boolean} [holdPosition] Keep the current paging position. By default 3498 * the paging is reset to the first page 3499 * @memberof DataTable#oApi 3500 */ 3501 function _fnReDraw( settings, holdPosition ) 3502 { 3503 var 3504 features = settings.oFeatures, 3505 sort = features.bSort, 3506 filter = features.bFilter; 3507 3508 if ( sort ) { 3509 _fnSort( settings ); 3510 } 3511 3512 if ( filter ) { 3513 _fnFilterComplete( settings, settings.oPreviousSearch ); 3514 } 3515 else { 3516 // No filtering, so we want to just use the display master 3517 settings.aiDisplay = settings.aiDisplayMaster.slice(); 3518 } 3519 3520 if ( holdPosition !== true ) { 3521 settings._iDisplayStart = 0; 3522 } 3523 3524 // Let any modules know about the draw hold position state (used by 3525 // scrolling internally) 3526 settings._drawHold = holdPosition; 3527 3528 _fnDraw( settings ); 3529 3530 settings._drawHold = false; 3531 } 3532 3533 3534 /** 3535 * Add the options to the page HTML for the table 3536 * @param {object} oSettings dataTables settings object 3537 * @memberof DataTable#oApi 3538 */ 3539 function _fnAddOptionsHtml ( oSettings ) 3540 { 3541 var classes = oSettings.oClasses; 3542 var table = $(oSettings.nTable); 3543 var holding = $('<div/>').insertBefore( table ); // Holding element for speed 3544 var features = oSettings.oFeatures; 3545 3546 // All DataTables are wrapped in a div 3547 var insert = $('<div/>', { 3548 id: oSettings.sTableId+'_wrapper', 3549 'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter) 3550 } ); 3551 3552 oSettings.nHolding = holding[0]; 3553 oSettings.nTableWrapper = insert[0]; 3554 oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling; 3555 3556 /* Loop over the user set positioning and place the elements as needed */ 3557 var aDom = oSettings.sDom.split(''); 3558 var featureNode, cOption, nNewNode, cNext, sAttr, j; 3559 for ( var i=0 ; i<aDom.length ; i++ ) 3560 { 3561 featureNode = null; 3562 cOption = aDom[i]; 3563 3564 if ( cOption == '<' ) 3565 { 3566 /* New container div */ 3567 nNewNode = $('<div/>')[0]; 3568 3569 /* Check to see if we should append an id and/or a class name to the container */ 3570 cNext = aDom[i+1]; 3571 if ( cNext == "'" || cNext == '"' ) 3572 { 3573 sAttr = ""; 3574 j = 2; 3575 while ( aDom[i+j] != cNext ) 3576 { 3577 sAttr += aDom[i+j]; 3578 j++; 3579 } 3580 3581 /* Replace jQuery UI constants @todo depreciated */ 3582 if ( sAttr == "H" ) 3583 { 3584 sAttr = classes.sJUIHeader; 3585 } 3586 else if ( sAttr == "F" ) 3587 { 3588 sAttr = classes.sJUIFooter; 3589 } 3590 3591 /* The attribute can be in the format of "#id.class", "#id" or "class" This logic 3592 * breaks the string into parts and applies them as needed 3593 */ 3594 if ( sAttr.indexOf('.') != -1 ) 3595 { 3596 var aSplit = sAttr.split('.'); 3597 nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1); 3598 nNewNode.className = aSplit[1]; 3599 } 3600 else if ( sAttr.charAt(0) == "#" ) 3601 { 3602 nNewNode.id = sAttr.substr(1, sAttr.length-1); 3603 } 3604 else 3605 { 3606 nNewNode.className = sAttr; 3607 } 3608 3609 i += j; /* Move along the position array */ 3610 } 3611 3612 insert.append( nNewNode ); 3613 insert = $(nNewNode); 3614 } 3615 else if ( cOption == '>' ) 3616 { 3617 /* End container div */ 3618 insert = insert.parent(); 3619 } 3620 // @todo Move options into their own plugins? 3621 else if ( cOption == 'l' && features.bPaginate && features.bLengthChange ) 3622 { 3623 /* Length */ 3624 featureNode = _fnFeatureHtmlLength( oSettings ); 3625 } 3626 else if ( cOption == 'f' && features.bFilter ) 3627 { 3628 /* Filter */ 3629 featureNode = _fnFeatureHtmlFilter( oSettings ); 3630 } 3631 else if ( cOption == 'r' && features.bProcessing ) 3632 { 3633 /* pRocessing */ 3634 featureNode = _fnFeatureHtmlProcessing( oSettings ); 3635 } 3636 else if ( cOption == 't' ) 3637 { 3638 /* Table */ 3639 featureNode = _fnFeatureHtmlTable( oSettings ); 3640 } 3641 else if ( cOption == 'i' && features.bInfo ) 3642 { 3643 /* Info */ 3644 featureNode = _fnFeatureHtmlInfo( oSettings ); 3645 } 3646 else if ( cOption == 'p' && features.bPaginate ) 3647 { 3648 /* Pagination */ 3649 featureNode = _fnFeatureHtmlPaginate( oSettings ); 3650 } 3651 else if ( DataTable.ext.feature.length !== 0 ) 3652 { 3653 /* Plug-in features */ 3654 var aoFeatures = DataTable.ext.feature; 3655 for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ ) 3656 { 3657 if ( cOption == aoFeatures[k].cFeature ) 3658 { 3659 featureNode = aoFeatures[k].fnInit( oSettings ); 3660 break; 3661 } 3662 } 3663 } 3664 3665 /* Add to the 2D features array */ 3666 if ( featureNode ) 3667 { 3668 var aanFeatures = oSettings.aanFeatures; 3669 3670 if ( ! aanFeatures[cOption] ) 3671 { 3672 aanFeatures[cOption] = []; 3673 } 3674 3675 aanFeatures[cOption].push( featureNode ); 3676 insert.append( featureNode ); 3677 } 3678 } 3679 3680 /* Built our DOM structure - replace the holding div with what we want */ 3681 holding.replaceWith( insert ); 3682 oSettings.nHolding = null; 3683 } 3684 3685 3686 /** 3687 * Use the DOM source to create up an array of header cells. The idea here is to 3688 * create a layout grid (array) of rows x columns, which contains a reference 3689 * to the cell that that point in the grid (regardless of col/rowspan), such that 3690 * any column / row could be removed and the new grid constructed 3691 * @param array {object} aLayout Array to store the calculated layout in 3692 * @param {node} nThead The header/footer element for the table 3693 * @memberof DataTable#oApi 3694 */ 3695 function _fnDetectHeader ( aLayout, nThead ) 3696 { 3697 var nTrs = $(nThead).children('tr'); 3698 var nTr, nCell; 3699 var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan; 3700 var bUnique; 3701 var fnShiftCol = function ( a, i, j ) { 3702 var k = a[i]; 3703 while ( k[j] ) { 3704 j++; 3705 } 3706 return j; 3707 }; 3708 3709 aLayout.splice( 0, aLayout.length ); 3710 3711 /* We know how many rows there are in the layout - so prep it */ 3712 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ ) 3713 { 3714 aLayout.push( [] ); 3715 } 3716 3717 /* Calculate a layout array */ 3718 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ ) 3719 { 3720 nTr = nTrs[i]; 3721 iColumn = 0; 3722 3723 /* For every cell in the row... */ 3724 nCell = nTr.firstChild; 3725 while ( nCell ) { 3726 if ( nCell.nodeName.toUpperCase() == "TD" || 3727 nCell.nodeName.toUpperCase() == "TH" ) 3728 { 3729 /* Get the col and rowspan attributes from the DOM and sanitise them */ 3730 iColspan = nCell.getAttribute('colspan') * 1; 3731 iRowspan = nCell.getAttribute('rowspan') * 1; 3732 iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan; 3733 iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan; 3734 3735 /* There might be colspan cells already in this row, so shift our target 3736 * accordingly 3737 */ 3738 iColShifted = fnShiftCol( aLayout, i, iColumn ); 3739 3740 /* Cache calculation for unique columns */ 3741 bUnique = iColspan === 1 ? true : false; 3742 3743 /* If there is col / rowspan, copy the information into the layout grid */ 3744 for ( l=0 ; l<iColspan ; l++ ) 3745 { 3746 for ( k=0 ; k<iRowspan ; k++ ) 3747 { 3748 aLayout[i+k][iColShifted+l] = { 3749 "cell": nCell, 3750 "unique": bUnique 3751 }; 3752 aLayout[i+k].nTr = nTr; 3753 } 3754 } 3755 } 3756 nCell = nCell.nextSibling; 3757 } 3758 } 3759 } 3760 3761 3762 /** 3763 * Get an array of unique th elements, one for each column 3764 * @param {object} oSettings dataTables settings object 3765 * @param {node} nHeader automatically detect the layout from this node - optional 3766 * @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional 3767 * @returns array {node} aReturn list of unique th's 3768 * @memberof DataTable#oApi 3769 */ 3770 function _fnGetUniqueThs ( oSettings, nHeader, aLayout ) 3771 { 3772 var aReturn = []; 3773 if ( !aLayout ) 3774 { 3775 aLayout = oSettings.aoHeader; 3776 if ( nHeader ) 3777 { 3778 aLayout = []; 3779 _fnDetectHeader( aLayout, nHeader ); 3780 } 3781 } 3782 3783 for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ ) 3784 { 3785 for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ ) 3786 { 3787 if ( aLayout[i][j].unique && 3788 (!aReturn[j] || !oSettings.bSortCellsTop) ) 3789 { 3790 aReturn[j] = aLayout[i][j].cell; 3791 } 3792 } 3793 } 3794 3795 return aReturn; 3796 } 3797 3798 /** 3799 *
3799Create an Ajax call based on the table's settings, taking into account that 3800 * parameters can have multiple forms, and backwards compatibility. 3801 * 3802 * @param {object} oSettings dataTables settings object 3803 * @param {array} data Data to send to the server, required by 3804 * DataTables - may be augmented by developer callbacks 3805 * @param {function} fn Callback function to run when data is obtained 3806 */ 3807 function _fnBuildAjax( oSettings, data, fn ) 3808 { 3809 // Compatibility with 1.9-, allow fnServerData and event to manipulate 3810 _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] ); 3811 3812 // Convert to object based for 1.10+ if using the old array scheme which can 3813 // come from server-side processing or serverParams 3814 if ( data && $.isArray(data) ) { 3815 var tmp = {}; 3816 var rbracket = /(.*?)\[\]$/; 3817 3818 $.each( data, function (key, val) { 3819 var match = val.name.match(rbracket); 3820 3821 if ( match ) { 3822 // Support for arrays 3823 var name = match[0]; 3824 3825 if ( ! tmp[ name ] ) { 3826 tmp[ name ] = []; 3827 } 3828 tmp[ name ].push( val.value ); 3829 } 3830 else { 3831 tmp[val.name] = val.value; 3832 } 3833 } ); 3834 data = tmp; 3835 } 3836 3837 var ajaxData; 3838 var ajax = oSettings.ajax; 3839 var instance = oSettings.oInstance; 3840 var callback = function ( json ) { 3841 _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] ); 3842 fn( json ); 3843 }; 3844 3845 if ( $.isPlainObject( ajax ) && ajax.data ) 3846 { 3847 ajaxData = ajax.data; 3848 3849 var newData = $.isFunction( ajaxData ) ? 3850 ajaxData( data, oSettings ) : // fn can manipulate data or return 3851 ajaxData; // an object object or array to merge 3852 3853 // If the function returned something, use that alone 3854 data = $.isFunction( ajaxData ) && newData ? 3855 newData : 3856 $.extend( true, data, newData ); 3857 3858 // Remove the data property as we've resolved it already and don't want 3859 // jQuery to do it again (it is restored at the end of the function) 3860 delete ajax.data; 3861 } 3862 3863 var baseAjax = { 3864 "data": data, 3865 "success": function (json) { 3866 var error = json.error || json.sError; 3867 if ( error ) { 3868 _fnLog( oSettings, 0, error ); 3869 } 3870 3871 oSettings.json = json; 3872 callback( json ); 3873 }, 3874 "dataType": "json", 3875 "cache": false, 3876 "type": oSettings.sServerMethod, 3877 "error": function (xhr, error, thrown) { 3878 var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] ); 3879 3880 if ( $.inArray( true, ret ) === -1 ) { 3881 if ( error == "parsererror" ) { 3882 _fnLog( oSettings, 0, 'Invalid JSON response', 1 ); 3883 } 3884 else if ( xhr.readyState === 4 ) { 3885 _fnLog( oSettings, 0, 'Ajax error', 7 ); 3886 } 3887 } 3888 3889 _fnProcessingDisplay( oSettings, false ); 3890 } 3891 }; 3892 3893 // Store the data submitted for the API 3894 oSettings.oAjaxData = data; 3895 3896 // Allow plug-ins and external processes to modify the data 3897 _fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] ); 3898 3899 if ( oSettings.fnServerData ) 3900 { 3901 // DataTables 1.9- compatibility 3902 oSettings.fnServerData.call( instance, 3903 oSettings.sAjaxSource, 3904 $.map( data, function (val, key) { // Need to convert back to 1.9 trad format 3905 return { name: key, value: val }; 3906 } ), 3907 callback, 3908 oSettings 3909 ); 3910 } 3911 else if ( oSettings.sAjaxSource || typeof ajax === 'string' ) 3912 { 3913 // DataTables 1.9- compatibility 3914 oSettings.jqXHR = $.ajax( $.extend( baseAjax, { 3915 url: ajax || oSettings.sAjaxSource 3916 } ) ); 3917 } 3918 else if ( $.isFunction( ajax ) ) 3919 { 3920 // Is a function - let the caller define what needs to be done 3921 oSettings.jqXHR = ajax.call( instance, data, callback, oSettings ); 3922 } 3923 else 3924 { 3925 // Object to extend the base settings 3926 oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) ); 3927 3928 // Restore for next time around 3929 ajax.data = ajaxData; 3930 } 3931 } 3932 3933 3934 /** 3935 * Update the table using an Ajax call 3936 * @param {object} settings dataTables settings object 3937 * @returns {boolean} Block the table drawing or not 3938 * @memberof DataTable#oApi 3939 */ 3940 function _fnAjaxUpdate( settings ) 3941 { 3942 if ( settings.bAjaxDataGet ) { 3943 settings.iDraw++; 3944 _fnProcessingDisplay( settings, true ); 3945 3946 _fnBuildAjax( 3947 settings, 3948 _fnAjaxParameters( settings ), 3949 function(json) { 3950 _fnAjaxUpdateDraw( settings, json ); 3951 } 3952 ); 3953 3954 return false;
vendor: 43,049 bytes, lines 3955-5429
3955 } 3956 return true; 3957 } 3958 3959 3960 /** 3961 * Build up the parameters in an object needed for a server-side processing 3962 * request. Note that this is basically done twice, is different ways - a modern 3963 * method which is used by default in DataTables 1.10 which uses objects and 3964 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if 3965 * the sAjaxSource option is used in the initialisation, or the legacyAjax 3966 * option is set. 3967 * @param {object} oSettings dataTables settings object 3968 * @returns {bool} block the table drawing or not 3969 * @memberof DataTable#oApi 3970 */ 3971 function _fnAjaxParameters( settings ) 3972 { 3973 var 3974 columns = settings.aoColumns, 3975 columnCount = columns.length, 3976 features = settings.oFeatures, 3977 preSearch = settings.oPreviousSearch, 3978 preColSearch = settings.aoPreSearchCols, 3979 i, data = [], dataProp, column, columnSearch, 3980 sort = _fnSortFlatten( settings ), 3981 displayStart = settings._iDisplayStart, 3982 displayLength = features.bPaginate !== false ? 3983 settings._iDisplayLength : 3984 -1; 3985 3986 var param = function ( name, value ) { 3987 data.push( { 'name': name, 'value': value } ); 3988 }; 3989 3990 // DataTables 1.9- compatible method 3991 param( 'sEcho', settings.iDraw ); 3992 param( 'iColumns', columnCount ); 3993 param( 'sColumns', _pluck( columns, 'sName' ).join(',') ); 3994 param( 'iDisplayStart', displayStart ); 3995 param( 'iDisplayLength', displayLength ); 3996 3997 // DataTables 1.10+ method 3998 var d = { 3999 draw: settings.iDraw, 4000 columns: [], 4001 order: [], 4002 start: displayStart, 4003 length: displayLength, 4004 search: { 4005 value: preSearch.sSearch, 4006 regex: preSearch.bRegex 4007 } 4008 }; 4009 4010 for ( i=0 ; i<columnCount ; i++ ) { 4011 column = columns[i]; 4012 columnSearch = preColSearch[i]; 4013 dataProp = typeof column.mData=="function" ? 'function' : column.mData ; 4014 4015 d.columns.push( { 4016 data: dataProp, 4017 name: column.sName, 4018 searchable: column.bSearchable, 4019 orderable: column.bSortable, 4020 search: { 4021 value: columnSearch.sSearch, 4022 regex: columnSearch.bRegex 4023 } 4024 } ); 4025 4026 param( "mDataProp_"+i, dataProp ); 4027 4028 if ( features.bFilter ) { 4029 param( 'sSearch_'+i, columnSearch.sSearch ); 4030 param( 'bRegex_'+i, columnSearch.bRegex ); 4031 param( 'bSearchable_'+i, column.bSearchable ); 4032 } 4033 4034 if ( features.bSort ) { 4035 param( 'bSortable_'+i, column.bSortable ); 4036 } 4037 } 4038 4039 if ( features.bFilter ) { 4040 param( 'sSearch', preSearch.sSearch ); 4041 param( 'bRegex', preSearch.bRegex ); 4042 } 4043 4044 if ( features.bSort ) { 4045 $.each( sort, function ( i, val ) { 4046 d.order.push( { column: val.col, dir: val.dir } ); 4047 4048 param( 'iSortCol_'+i, val.col ); 4049 param( 'sSortDir_'+i, val.dir ); 4050 } ); 4051 4052 param( 'iSortingCols', sort.length ); 4053 } 4054 4055 // If the legacy.ajax parameter is null, then we automatically decide which 4056 // form to use, based on sAjaxSource 4057 var legacy = DataTable.ext.legacy.ajax; 4058 if ( legacy === null ) { 4059 return settings.sAjaxSource ? data : d; 4060 } 4061 4062 // Otherwise, if legacy has been specified then we use that to decide on the 4063 // form 4064 return legacy ? data : d; 4065 } 4066 4067 4068 /** 4069 * Data the data from the server (nuking the old) and redraw the table 4070 * @param {object} oSettings dataTables settings object 4071 * @param {object} json json data return from the server. 4072 * @param {string} json.sEcho Tracking flag for DataTables to match requests 4073 * @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering 4074 * @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering 4075 * @param {array} json.aaData The data to display on this page 4076 * @param {string} [json.sColumns] Column ordering (sName, comma separated) 4077 * @memberof DataTable#oApi 4078 */ 4079 function _fnAjaxUpdateDraw ( settings, json ) 4080 { 4081 // v1.10 uses camelCase variables, while 1.9 uses Hungarian notation. 4082 // Support both 4083 var compat = function ( old, modern ) { 4084 return json[old] !== undefined ? json[old] : json[modern]; 4085 }; 4086 4087 var data = _fnAjaxDataSrc( settings, json ); 4088 var draw = compat( 'sEcho', 'draw' ); 4089 var recordsTotal = compat( 'iTotalRecords', 'recordsTotal' ); 4090 var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' ); 4091 4092 if ( draw ) { 4093 // Protect against out of sequence returns 4094 if ( draw*1 < settings.iDraw ) { 4095 return; 4096 } 4097 settings.iDraw = draw * 1; 4098 } 4099 4100 _fnClearTable( settings ); 4101 settings._iRecordsTotal = parseInt(recordsTotal, 10); 4102 settings._iRecordsDisplay = parseInt(recordsFiltered, 10); 4103 4104 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 4105 _fnAddData( settings, data[i] ); 4106 } 4107 settings.aiDisplay = settings.aiDisplayMaster.slice(); 4108 4109 settings.bAjaxDataGet = false; 4110 _fnDraw( settings ); 4111 4112 if ( ! settings._bInitComplete ) { 4113 _fnInitComplete( settings, json ); 4114 } 4115 4116 settings.bAjaxDataGet = true; 4117 _fnProcessingDisplay( settings, false ); 4118 } 4119 4120 4121 /** 4122 * Get the data from the JSON data source to use for drawing a table. Using 4123 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the 4124 * source object, or from a processing function. 4125 * @param {object} oSettings dataTables settings object 4126 * @param {object} json Data source object / array from the server 4127 * @return {array} Array of data to use 4128 */ 4129 function _fnAjaxDataSrc ( oSettings, json ) 4130 { 4131 var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ? 4132 oSettings.ajax.dataSrc : 4133 oSettings.sAjaxDataProp; // Compatibility with 1.9-. 4134 4135 // Compatibility with 1.9-. In order to read from aaData, check if the 4136 // default has been changed, if not, check for aaData 4137 if ( dataSrc === 'data' ) { 4138 return json.aaData || json[dataSrc]; 4139 } 4140 4141 return dataSrc !== "" ? 4142 _fnGetObjectDataFn( dataSrc )( json ) : 4143 json; 4144 } 4145 4146 /** 4147 * Generate the node required for filtering text 4148 * @returns {node} Filter control element 4149 * @param {object} oSettings dataTables settings object 4150 * @memberof DataTable#oApi 4151 */ 4152 function _fnFeatureHtmlFilter ( settings ) 4153 { 4154 var classes = settings.oClasses; 4155 var tableId = settings.sTableId; 4156 var language = settings.oLanguage; 4157 var previousSearch = settings.oPreviousSearch; 4158 var features = settings.aanFeatures; 4159 var input = '<input type="search" class="'+classes.sFilterInput+'"/>'; 4160 4161 var str = language.sSearch; 4162 str = str.match(/_INPUT_/) ? 4163 str.replace('_INPUT_', input) : 4164 str+input; 4165 4166 var filter = $('<div/>', { 4167 'id': ! features.f ? tableId+'_filter' : null, 4168 'class': classes.sFilter 4169 } ) 4170 .append( $('<label/>' ).append( str ) ); 4171 4172 var searchFn = function() { 4173 /* Update all other filter input elements for the new display */ 4174 var n = features.f; 4175 var val = !this.value ? "" : this.value; // mental IE8 fix :-( 4176 4177 /* Now do the filter */ 4178 if ( val != previousSearch.sSearch ) { 4179 _fnFilterComplete( settings, { 4180 "sSearch": val, 4181 "bRegex": previousSearch.bRegex, 4182 "bSmart": previousSearch.bSmart , 4183 "bCaseInsensitive": previousSearch.bCaseInsensitive 4184 } ); 4185 4186 // Need to redraw, without resorting 4187 settings._iDisplayStart = 0; 4188 _fnDraw( settings ); 4189 } 4190 }; 4191 4192 var searchDelay = settings.searchDelay !== null ? 4193 settings.searchDelay : 4194 _fnDataSource( settings ) === 'ssp' ? 4195 400 : 4196 0; 4197 4198 var jqFilter = $('input', filter) 4199 .val( previousSearch.sSearch ) 4200 .attr( 'placeholder', language.sSearchPlaceholder ) 4201 .on( 4202 'keyup.DT search.DT input.DT paste.DT cut.DT', 4203 searchDelay ? 4204 _fnThrottle( searchFn, searchDelay ) : 4205 searchFn 4206 ) 4207 .on( 'keypress.DT', function(e) { 4208 /* Prevent form submission */ 4209 if ( e.keyCode == 13 ) { 4210 return false; 4211 } 4212 } ) 4213 .attr('aria-controls', tableId); 4214 4215 // Update the input elements whenever the table is filtered 4216 $(settings.nTable).on( 'search.dt.DT', function ( ev, s ) { 4217 if ( settings === s ) { 4218 // IE9 throws an 'unknown error' if document.activeElement is used 4219 // inside an iframe or frame... 4220 try { 4221 if ( jqFilter[0] !== document.activeElement ) { 4222 jqFilter.val( previousSearch.sSearch ); 4223 } 4224 } 4225 catch ( e ) {} 4226 } 4227 } ); 4228 4229 return filter[0]; 4230 } 4231 4232 4233 /** 4234 * Filter the table using both the global filter and column based filtering 4235 * @param {object} oSettings dataTables settings object 4236 * @param {object} oSearch search information 4237 * @param {int} [iForce] force a research of the master array (1) or not (undefined or 0) 4238 * @memberof DataTable#oApi 4239 */ 4240 function _fnFilterComplete ( oSettings, oInput, iForce ) 4241 { 4242 var oPrevSearch = oSettings.oPreviousSearch; 4243 var aoPrevSearch = oSettings.aoPreSearchCols; 4244 var fnSaveFilter = function ( oFilter ) { 4245 /* Save the filtering values */ 4246 oPrevSearch.sSearch = oFilter.sSearch; 4247 oPrevSearch.bRegex = oFilter.bRegex; 4248 oPrevSearch.bSmart = oFilter.bSmart; 4249 oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive; 4250 }; 4251 var fnRegex = function ( o ) { 4252 // Backwards compatibility with the bEscapeRegex option 4253 return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex; 4254 }; 4255 4256 // Resolve any column types that are unknown due to addition or invalidation 4257 // @todo As per sort - can this be moved into an event handler? 4258 _fnColumnTypes( oSettings ); 4259 4260 /* In server-side processing all filtering is done by the server, so no point hanging around here */ 4261 if ( _fnDataSource( oSettings ) != 'ssp' ) 4262 { 4263 /* Global filter */ 4264 _fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive ); 4265 fnSaveFilter( oInput ); 4266 4267 /* Now do the individual column filter */ 4268 for ( var i=0 ; i<aoPrevSearch.length ; i++ ) 4269 { 4270 _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]), 4271 aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive ); 4272 } 4273 4274 /* Custom filtering */ 4275 _fnFilterCustom( oSettings ); 4276 } 4277 else 4278 { 4279 fnSaveFilter( oInput ); 4280 } 4281 4282 /* Tell the draw function we have been filtering */ 4283 oSettings.bFiltered = true; 4284 _fnCallbackFire( oSettings, null, 'search', [oSettings] ); 4285 } 4286 4287 4288 /** 4289 * Apply custom filtering functions 4290 * @param {object} oSettings dataTables settings object 4291 * @memberof DataTable#oApi 4292 */ 4293 function _fnFilterCustom( settings ) 4294 { 4295 var filters = DataTable.ext.search; 4296 var displayRows = settings.aiDisplay; 4297 var row, rowIdx; 4298 4299 for ( var i=0, ien=filters.length ; i<ien ; i++ ) { 4300 var rows = []; 4301 4302 // Loop over each row and see if it should be included 4303 for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) { 4304 rowIdx = displayRows[ j ]; 4305 row = settings.aoData[ rowIdx ]; 4306 4307 if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) { 4308 rows.push( rowIdx ); 4309 } 4310 } 4311 4312 // So the array reference doesn't break set the results into the 4313 // existing array 4314 displayRows.length = 0; 4315 $.merge( displayRows, rows ); 4316 } 4317 } 4318 4319 4320 /** 4321 * Filter the table on a per-column basis 4322 * @param {object} oSettings dataTables settings object 4323 * @param {string} sInput string to filter on 4324 * @param {int} iColumn column to filter 4325 * @param {bool} bRegex treat search string as a regular expression or not 4326 * @param {bool} bSmart use smart filtering or not 4327 * @param {bool} bCaseInsensitive Do case insenstive matching or not 4328 * @memberof DataTable#oApi 4329 */ 4330 function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive ) 4331 { 4332 if ( searchStr === '' ) { 4333 return; 4334 } 4335 4336 var data; 4337 var out = []; 4338 var display = settings.aiDisplay; 4339 var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive ); 4340 4341 for ( var i=0 ; i<display.length ; i++ ) { 4342 data = settings.aoData[ display[i] ]._aFilterData[ colIdx ]; 4343 4344 if ( rpSearch.test( data ) ) { 4345 out.push( display[i] ); 4346 } 4347 } 4348 4349 settings.aiDisplay = out; 4350 } 4351 4352 4353 /** 4354 * Filter the data table based on user input and draw the table 4355 * @param {object} settings dataTables settings object 4356 * @param {string} input string to filter on 4357 * @param {int} force optional - force a research of the master array (1) or not (undefined or 0) 4358 * @param {bool} regex treat as a regular expression or not 4359 * @param {bool} smart perform smart filtering or not 4360 * @param {bool} caseInsensitive Do case insenstive matching or not 4361 * @memberof DataTable#oApi 4362 */ 4363 function _fnFilter( settings, input, force, regex, smart, caseInsensitive ) 4364 { 4365 var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive ); 4366 var prevSearch = settings.oPreviousSearch.sSearch; 4367 var displayMaster = settings.aiDisplayMaster; 4368 var display, invalidated, i; 4369 var filtered = []; 4370 4371 // Need to take account of custom filtering functions - always filter 4372 if ( DataTable.ext.search.length !== 0 ) { 4373 force = true; 4374 } 4375 4376 // Check if any of the rows were invalidated 4377 invalidated = _fnFilterData( settings ); 4378 4379 // If the input is blank - we just want the full data set 4380 if ( input.length <= 0 ) { 4381 settings.aiDisplay = displayMaster.slice(); 4382 } 4383 else { 4384 // New search - start from the master array 4385 if ( invalidated || 4386 force || 4387 prevSearch.length > input.length || 4388 input.indexOf(prevSearch) !== 0 || 4389 settings.bSorted // On resort, the display master needs to be 4390 // re-filtered since indexes will have changed 4391 ) { 4392 settings.aiDisplay = displayMaster.slice(); 4393 } 4394 4395 // Search the display array 4396 display = settings.aiDisplay; 4397 4398 for ( i=0 ; i<display.length ; i++ ) { 4399 if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) { 4400 filtered.push( display[i] ); 4401 } 4402 } 4403 4404 settings.aiDisplay = filtered; 4405 } 4406 } 4407 4408 4409 /** 4410 * Build a regular expression object suitable for searching a table 4411 * @param {string} sSearch string to search for 4412 * @param {bool} bRegex treat as a regular expression or not 4413 * @param {bool} bSmart perform smart filtering or not 4414 * @param {bool} bCaseInsensitive Do case insensitive matching or not 4415 * @returns {RegExp} constructed object 4416 * @memberof DataTable#oApi 4417 */ 4418 function _fnFilterCreateSearch( search, regex, smart, caseInsensitive ) 4419 { 4420 search = regex ? 4421 search : 4422 _fnEscapeRegex( search ); 4423 4424 if ( smart ) { 4425 /* For smart filtering we want to allow the search to work regardless of 4426 * word order. We also want double quoted text to be preserved, so word 4427 * order is important - a la google. So this is what we want to 4428 * generate: 4429 * 4430 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$ 4431 */ 4432 var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) { 4433 if ( word.charAt(0) === '"' ) { 4434 var m = word.match( /^"(.*)"$/ ); 4435 word = m ? m[1] : word; 4436 } 4437 4438 return word.replace('"', ''); 4439 } ); 4440 4441 search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$'; 4442 } 4443 4444 return new RegExp( search, caseInsensitive ? 'i' : '' ); 4445 } 4446 4447 4448 /** 4449 * Escape a string such that it can be used in a regular expression 4450 * @param {string} sVal string to escape 4451 * @returns {string} escaped string 4452 * @memberof DataTable#oApi 4453 */ 4454 var _fnEscapeRegex = DataTable.util.escapeRegex; 4455 4456 var __filter_div = $('<div>')[0]; 4457 var __filter_div_textContent = __filter_div.textContent !== undefined; 4458 4459 // Update the filtering data for each row if needed (by invalidation or first run) 4460 function _fnFilterData ( settings ) 4461 { 4462 var columns = settings.aoColumns; 4463 var column; 4464 var i, j, ien, jen, filterData, cellData, row; 4465 var fomatters = DataTable.ext.type.search; 4466 var wasInvalidated = false; 4467 4468 for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 4469 row = settings.aoData[i]; 4470 4471 if ( ! row._aFilterData ) { 4472 filterData = []; 4473 4474 for ( j=0, jen=columns.length ; j<jen ; j++ ) { 4475 column = columns[j]; 4476 4477 if ( column.bSearchable ) { 4478 cellData = _fnGetCellData( settings, i, j, 'filter' ); 4479 4480 if ( fomatters[ column.sType ] ) { 4481 cellData = fomatters[ column.sType ]( cellData ); 4482 } 4483 4484 // Search in DataTables 1.10 is string based. In 1.11 this 4485 // should be altered to also allow strict type checking. 4486 if ( cellData === null ) { 4487 cellData = ''; 4488 } 4489 4490 if ( typeof cellData !== 'string' && cellData.toString ) { 4491 cellData = cellData.toString(); 4492 } 4493 } 4494 else { 4495 cellData = ''; 4496 } 4497 4498 // If it looks like there is an HTML entity in the string, 4499 // attempt to decode it so sorting works as expected. Note that 4500 // we could use a single line of jQuery to do this, but the DOM 4501 // method used here is much faster http://jsperf.com/html-decode 4502 if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) { 4503 __filter_div.innerHTML = cellData; 4504 cellData = __filter_div_textContent ? 4505 __filter_div.textContent : 4506 __filter_div.innerText; 4507 } 4508 4509 if ( cellData.replace ) { 4510 cellData = cellData.replace(/[\r\n]/g, ''); 4511 } 4512 4513 filterData.push( cellData ); 4514 } 4515 4516 row._aFilterData = filterData; 4517 row._sFilterRow = filterData.join(' '); 4518 wasInvalidated = true; 4519 } 4520 } 4521 4522 return wasInvalidated; 4523 } 4524 4525 4526 /** 4527 * Convert from the internal Hungarian notation to camelCase for external 4528 * interaction 4529 * @param {object} obj Object to convert 4530 * @returns {object} Inverted object 4531 * @memberof DataTable#oApi 4532 */ 4533 function _fnSearchToCamel ( obj ) 4534 { 4535 return { 4536 search: obj.sSearch, 4537 smart: obj.bSmart, 4538 regex: obj.bRegex, 4539 caseInsensitive: obj.bCaseInsensitive 4540 }; 4541 } 4542 4543 4544 4545 /** 4546 * Convert from camelCase notation to the internal Hungarian. We could use the 4547 * Hungarian convert function here, but this is cleaner 4548 * @param {object} obj Object to convert 4549 * @returns {object} Inverted object 4550 * @memberof DataTable#oApi 4551 */ 4552 function _fnSearchToHung ( obj ) 4553 { 4554 return { 4555 sSearch: obj.search, 4556 bSmart: obj.smart, 4557 bRegex: obj.regex, 4558 bCaseInsensitive: obj.caseInsensitive 4559 }; 4560 } 4561 4562 /** 4563 * Generate the node required for the info display 4564 * @param {object} oSettings dataTables settings object 4565 * @returns {node} Information element 4566 * @memberof DataTable#oApi 4567 */ 4568 function _fnFeatureHtmlInfo ( settings ) 4569 { 4570 var 4571 tid = settings.sTableId, 4572 nodes = settings.aanFeatures.i, 4573 n = $('<div/>', { 4574 'class': settings.oClasses.sInfo, 4575 'id': ! nodes ? tid+'_info' : null 4576 } ); 4577 4578 if ( ! nodes ) { 4579 // Update display on each draw 4580 settings.aoDrawCallback.push( { 4581 "fn": _fnUpdateInfo, 4582 "sName": "information" 4583 } ); 4584 4585 n 4586 .attr( 'role', 'status' ) 4587 .attr( 'aria-live', 'polite' ); 4588 4589 // Table is described by our info div 4590 $(settings.nTable).attr( 'aria-describedby', tid+'_info' ); 4591 } 4592 4593 return n[0]; 4594 } 4595 4596 4597 /** 4598 * Update the information elements in the display 4599 * @param {object} settings dataTables settings object 4600 * @memberof DataTable#oApi 4601 */ 4602 function _fnUpdateInfo ( settings ) 4603 { 4604 /* Show information about the table */ 4605 var nodes = settings.aanFeatures.i; 4606 if ( nodes.length === 0 ) { 4607 return; 4608 } 4609 4610 var 4611 lang = settings.oLanguage, 4612 start = settings._iDisplayStart+1, 4613 end = settings.fnDisplayEnd(), 4614 max = settings.fnRecordsTotal(), 4615 total = settings.fnRecordsDisplay(), 4616 out = total ? 4617 lang.sInfo : 4618 lang.sInfoEmpty; 4619 4620 if ( total !== max ) { 4621 /* Record set after filtering */ 4622 out += ' ' + lang.sInfoFiltered; 4623 } 4624 4625 // Convert the macros 4626 out += lang.sInfoPostFix; 4627 out = _fnInfoMacros( settings, out ); 4628 4629 var callback = lang.fnInfoCallback; 4630 if ( callback !== null ) { 4631 out = callback.call( settings.oInstance, 4632 settings, start, end, max, total, out 4633 ); 4634 } 4635 4636 $(nodes).html( out ); 4637 } 4638 4639 4640 function _fnInfoMacros ( settings, str ) 4641 { 4642 // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only 4643 // internally 4644 var 4645 formatter = settings.fnFormatNumber, 4646 start = settings._iDisplayStart+1, 4647 len = settings._iDisplayLength, 4648 vis = settings.fnRecordsDisplay(), 4649 all = len === -1; 4650 4651 return str. 4652 replace(/_START_/g, formatter.call( settings, start ) ). 4653 replace(/_END_/g, formatter.call( settings, settings.fnDisplayEnd() ) ). 4654 replace(/_MAX_/g, formatter.call( settings, settings.fnRecordsTotal() ) ). 4655 replace(/_TOTAL_/g, formatter.call( settings, vis ) ). 4656 replace(/_PAGE_/g, formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ). 4657 replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) ); 4658 } 4659 4660 4661 4662 /** 4663 * Draw the table for the first time, adding all required features 4664 * @param {object} settings dataTables settings object 4665 * @memberof DataTable#oApi 4666 */ 4667 function _fnInitialise ( settings ) 4668 { 4669 var i, iLen, iAjaxStart=settings.iInitDisplayStart; 4670 var columns = settings.aoColumns, column; 4671 var features = settings.oFeatures; 4672 var deferLoading = settings.bDeferLoading; // value modified by the draw 4673 4674 /* Ensure that the table data is fully initialised */ 4675 if ( ! settings.bInitialised ) { 4676 setTimeout( function(){ _fnInitialise( settings ); }, 200 ); 4677 return; 4678 } 4679 4680 /* Show the display HTML options */ 4681 _fnAddOptionsHtml( settings ); 4682 4683 /* Build and draw the header / footer for the table */ 4684 _fnBuildHead( settings ); 4685 _fnDrawHead( settings, settings.aoHeader ); 4686 _fnDrawHead( settings, settings.aoFooter ); 4687 4688 /* Okay to show that something is going on now */ 4689 _fnProcessingDisplay( settings, true ); 4690 4691 /* Calculate sizes for columns */ 4692 if ( features.bAutoWidth ) { 4693 _fnCalculateColumnWidths( settings ); 4694 } 4695 4696 for ( i=0, iLen=columns.length ; i<iLen ; i++ ) { 4697 column = columns[i]; 4698 4699 if ( column.sWidth ) { 4700 column.nTh.style.width = _fnStringToCss( column.sWidth ); 4701 } 4702 } 4703 4704 _fnCallbackFire( settings, null, 'preInit', [settings] ); 4705 4706 // If there is default sorting required - let's do it. The sort function 4707 // will do the drawing for us. Otherwise we draw the table regardless of the 4708 // Ajax source - this allows the table to look initialised for Ajax sourcing 4709 // data (show 'loading' message possibly) 4710 _fnReDraw( settings ); 4711 4712 // Server-side processing init complete is done by _fnAjaxUpdateDraw 4713 var dataSrc = _fnDataSource( settings ); 4714 if ( dataSrc != 'ssp' || deferLoading ) { 4715 // if there is an ajax source load the data 4716 if ( dataSrc == 'ajax' ) { 4717 _fnBuildAjax( settings, [], function(json) { 4718 var aData = _fnAjaxDataSrc( settings, json ); 4719 4720 // Got the data - add it to the table 4721 for ( i=0 ; i<aData.length ; i++ ) { 4722 _fnAddData( settings, aData[i] ); 4723 } 4724 4725 // Reset the init display for cookie saving. We've already done 4726 // a filter, and therefore cleared it before. So we need to make 4727 // it appear 'fresh' 4728 settings.iInitDisplayStart = iAjaxStart; 4729 4730 _fnReDraw( settings ); 4731 4732 _fnProcessingDisplay( settings, false ); 4733 _fnInitComplete( settings, json ); 4734 }, settings ); 4735 } 4736 else { 4737 _fnProcessingDisplay( settings, false ); 4738 _fnInitComplete( settings ); 4739 } 4740 } 4741 } 4742 4743 4744 /** 4745 * Draw the table for the first time, adding all required features 4746 * @param {object} oSettings dataTables settings object 4747 * @param {object} [json] JSON from the server that completed the table, if using Ajax source 4748 * with client-side processing (optional) 4749 * @memberof DataTable#oApi 4750 */ 4751 function _fnInitComplete ( settings, json ) 4752 { 4753 settings._bInitComplete = true; 4754 4755 // When data was added after the initialisation (data or Ajax) we need to 4756 // calculate the column sizing 4757 if ( json || settings.oInit.aaData ) { 4758 _fnAdjustColumnSizing( settings ); 4759 } 4760 4761 _fnCallbackFire( settings, null, 'plugin-init', [settings, json] ); 4762 _fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] ); 4763 } 4764 4765 4766 function _fnLengthChange ( settings, val ) 4767 { 4768 var len = parseInt( val, 10 ); 4769 settings._iDisplayLength = len; 4770 4771 _fnLengthOverflow( settings ); 4772 4773 // Fire length change event 4774 _fnCallbackFire( settings, null, 'length', [settings, len] ); 4775 } 4776 4777 4778 /** 4779 * Generate the node required for user display length changing 4780 * @param {object} settings dataTables settings object 4781 * @returns {node} Display length feature node 4782 * @memberof DataTable#oApi 4783 */ 4784 function _fnFeatureHtmlLength ( settings ) 4785 { 4786 var 4787 classes = settings.oClasses, 4788 tableId = settings.sTableId, 4789 menu = settings.aLengthMenu, 4790 d2 = $.isArray( menu[0] ), 4791 lengths = d2 ? menu[0] : menu, 4792 language = d2 ? menu[1] : menu; 4793 4794 var select = $('<select/>', { 4795 'name': tableId+'_length', 4796 'aria-controls': tableId, 4797 'class': classes.sLengthSelect 4798 } ); 4799 4800 for ( var i=0, ien=lengths.length ; i<ien ; i++ ) { 4801 select[0][ i ] = new Option( language[i], lengths[i] ); 4802 } 4803 4804 var div = $('<div><label/></div>').addClass( classes.sLength ); 4805 if ( ! settings.aanFeatures.l ) { 4806 div[0].id = tableId+'_length'; 4807 } 4808 4809 div.children().append( 4810 settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML ) 4811 ); 4812 4813 // Can't use `select` variable as user might provide their own and the 4814 // reference is broken by the use of outerHTML 4815 $('select', div) 4816 .val( settings._iDisplayLength ) 4817 .on( 'change.DT', function(e) { 4818 _fnLengthChange( settings, $(this).val() ); 4819 _fnDraw( settings ); 4820 } ); 4821 4822 // Update node value whenever anything changes the table's length 4823 $(settings.nTable).on( 'length.dt.DT', function (e, s, len) { 4824 if ( settings === s ) { 4825 $('select', div).val( len ); 4826 } 4827 } ); 4828 4829 return div[0]; 4830 } 4831 4832 4833 4834 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 4835 * Note that most of the paging logic is done in 4836 * DataTable.ext.pager 4837 */ 4838 4839 /** 4840 * Generate the node required for default pagination 4841 * @param {object} oSettings dataTables settings object 4842 * @returns {node} Pagination feature node 4843 * @memberof DataTable#oApi 4844 */ 4845 function _fnFeatureHtmlPaginate ( settings ) 4846 { 4847 var 4848 type = settings.sPaginationType, 4849 plugin = DataTable.ext.pager[ type ], 4850 modern = typeof plugin === 'function', 4851 redraw = function( settings ) { 4852 _fnDraw( settings ); 4853 }, 4854 node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0], 4855 features = settings.aanFeatures; 4856 4857 if ( ! modern ) { 4858 plugin.fnInit( settings, node, redraw ); 4859 } 4860 4861 /* Add a draw callback for the pagination on first instance, to update the paging display */ 4862 if ( ! features.p ) 4863 { 4864 node.id = settings.sTableId+'_paginate'; 4865 4866 settings.aoDrawCallback.push( { 4867 "fn": function( settings ) { 4868 if ( modern ) { 4869 var 4870 start = settings._iDisplayStart, 4871 len = settings._iDisplayLength, 4872 visRecords = settings.fnRecordsDisplay(), 4873 all = len === -1, 4874 page = all ? 0 : Math.ceil( start / len ), 4875 pages = all ? 1 : Math.ceil( visRecords / len ), 4876 buttons = plugin(page, pages), 4877 i, ien; 4878 4879 for ( i=0, ien=features.p.length ; i<ien ; i++ ) { 4880 _fnRenderer( settings, 'pageButton' )( 4881 settings, features.p[i], i, buttons, page, pages 4882 ); 4883 } 4884 } 4885 else { 4886 plugin.fnUpdate( settings, redraw ); 4887 } 4888 }, 4889 "sName": "pagination" 4890 } ); 4891 } 4892 4893 return node; 4894 } 4895 4896 4897 /** 4898 * Alter the display settings to change the page 4899 * @param {object} settings DataTables settings object 4900 * @param {string|int} action Paging action to take: "first", "previous", 4901 * "next" or "last" or page number to jump to (integer) 4902 * @param [bool] redraw Automatically draw the update or not 4903 * @returns {bool} true page has changed, false - no change 4904 * @memberof DataTable#oApi 4905 */ 4906 function _fnPageChange ( settings, action, redraw ) 4907 { 4908 var 4909 start = settings._iDisplayStart, 4910 len = settings._iDisplayLength, 4911 records = settings.fnRecordsDisplay(); 4912 4913 if ( records === 0 || len === -1 ) 4914 { 4915 start = 0; 4916 } 4917 else if ( typeof action === "number" ) 4918 { 4919 start = action * len; 4920 4921 if ( start > records ) 4922 { 4923 start = 0; 4924 } 4925 } 4926 else if ( action == "first" ) 4927 { 4928 start = 0; 4929 } 4930 else if ( action == "previous" ) 4931 { 4932 start = len >= 0 ? 4933 start - len : 4934 0; 4935 4936 if ( start < 0 ) 4937 { 4938 start = 0; 4939 } 4940 } 4941 else if ( action == "next" ) 4942 { 4943 if ( start + len < records ) 4944 { 4945 start += len; 4946 } 4947 } 4948 else if ( action == "last" ) 4949 { 4950 start = Math.floor( (records-1) / len) * len; 4951 } 4952 else 4953 { 4954 _fnLog( settings, 0, "Unknown paging action: "+action, 5 ); 4955 } 4956 4957 var changed = settings._iDisplayStart !== start; 4958 settings._iDisplayStart = start; 4959 4960 if ( changed ) { 4961 _fnCallbackFire( settings, null, 'page', [settings] ); 4962 4963 if ( redraw ) { 4964 _fnDraw( settings ); 4965 } 4966 } 4967 4968 return changed; 4969 } 4970 4971 4972 4973 /** 4974 * Generate the node required for the processing node 4975 * @param {object} settings dataTables settings object 4976 * @returns {node} Processing element 4977 * @memberof DataTable#oApi 4978 */ 4979 function _fnFeatureHtmlProcessing ( settings ) 4980 { 4981 return $('<div/>', { 4982 'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null, 4983 'class': settings.oClasses.sProcessing 4984 } ) 4985 .html( settings.oLanguage.sProcessing ) 4986 .insertBefore( settings.nTable )[0]; 4987 } 4988 4989 4990 /** 4991 * Display or hide the processing indicator 4992 * @param {object} settings dataTables settings object 4993 * @param {bool} show Show the processing indicator (true) or not (false) 4994 * @memberof DataTable#oApi 4995 */ 4996 function _fnProcessingDisplay ( settings, show ) 4997 { 4998 if ( settings.oFeatures.bProcessing ) { 4999 $(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' ); 5000 } 5001 5002 _fnCallbackFire( settings, null, 'processing', [settings, show] ); 5003 } 5004 5005 /** 5006 * Add any control elements for the table - specifically scrolling 5007 * @param {object} settings dataTables settings object 5008 * @returns {node} Node to add to the DOM 5009 * @memberof DataTable#oApi 5010 */ 5011 function _fnFeatureHtmlTable ( settings ) 5012 { 5013 var table = $(settings.nTable); 5014 5015 // Add the ARIA grid role to the table 5016 table.attr( 'role', 'grid' ); 5017 5018 // Scrolling from here on in 5019 var scroll = settings.oScroll; 5020 5021 if ( scroll.sX === '' && scroll.sY === '' ) { 5022 return settings.nTable; 5023 } 5024 5025 var scrollX = scroll.sX; 5026 var scrollY = scroll.sY; 5027 var classes = settings.oClasses; 5028 var caption = table.children('caption'); 5029 var captionSide = caption.length ? caption[0]._captionSide : null; 5030 var headerClone = $( table[0].cloneNode(false) ); 5031 var footerClone = $( table[0].cloneNode(false) ); 5032 var footer = table.children('tfoot'); 5033 var _div = '<div/>'; 5034 var size = function ( s ) { 5035 return !s ? null : _fnStringToCss( s ); 5036 }; 5037 5038 if ( ! footer.length ) { 5039 footer = null; 5040 } 5041 5042 /* 5043 * The HTML structure that we want to generate in this function is: 5044 * div - scroller 5045 * div - scroll head 5046 * div - scroll head inner 5047 * table - scroll head table 5048 * thead - thead 5049 * div - scroll body 5050 * table - table (master table) 5051 * thead - thead clone for sizing 5052 * tbody - tbody 5053 * div - scroll foot 5054 * div - scroll foot inner 5055 * table - scroll foot table 5056 * tfoot - tfoot 5057 */ 5058 var scroller = $( _div, { 'class': classes.sScrollWrapper } ) 5059 .append( 5060 $(_div, { 'class': classes.sScrollHead } ) 5061 .css( { 5062 overflow: 'hidden', 5063 position: 'relative', 5064 border: 0, 5065 width: scrollX ? size(scrollX) : '100%' 5066 } ) 5067 .append( 5068 $(_div, { 'class': classes.sScrollHeadInner } ) 5069 .css( { 5070 'box-sizing': 'content-box', 5071 width: scroll.sXInner || '100%' 5072 } ) 5073 .append( 5074 headerClone 5075 .removeAttr('id') 5076 .css( 'margin-left', 0 ) 5077 .append( captionSide === 'top' ? caption : null ) 5078 .append( 5079 table.children('thead') 5080 ) 5081 ) 5082 ) 5083 ) 5084 .append( 5085 $(_div, { 'class': classes.sScrollBody } ) 5086 .css( { 5087 position: 'relative', 5088 overflow: 'auto', 5089 width: size( scrollX ) 5090 } ) 5091 .append( table ) 5092 ); 5093 5094 if ( footer ) { 5095 scroller.append( 5096 $(_div, { 'class': classes.sScrollFoot } ) 5097 .css( { 5098 overflow: 'hidden', 5099 border: 0, 5100 width: scrollX ? size(scrollX) : '100%' 5101 } ) 5102 .append( 5103 $(_div, { 'class': classes.sScrollFootInner } ) 5104 .append( 5105 footerClone 5106 .removeAttr('id') 5107 .css( 'margin-left', 0 ) 5108 .append( captionSide === 'bottom' ? caption : null ) 5109 .append( 5110 table.children('tfoot') 5111 ) 5112 ) 5113 ) 5114 ); 5115 } 5116 5117 var children = scroller.children(); 5118 var scrollHead = children[0]; 5119 var scrollBody = children[1]; 5120 var scrollFoot = footer ? children[2] : null; 5121 5122 // When the body is scrolled, then we also want to scroll the headers 5123 if ( scrollX ) { 5124 $(scrollBody).on( 'scroll.DT', function (e) { 5125 var scrollLeft = this.scrollLeft; 5126 5127 scrollHead.scrollLeft = scrollLeft; 5128 5129 if ( footer ) { 5130 scrollFoot.scrollLeft = scrollLeft; 5131 } 5132 } ); 5133 } 5134 5135 $(scrollBody).css( 5136 scrollY && scroll.bCollapse ? 'max-height' : 'height', 5137 scrollY 5138 ); 5139 5140 settings.nScrollHead = scrollHead; 5141 settings.nScrollBody = scrollBody; 5142 settings.nScrollFoot = scrollFoot; 5143 5144 // On redraw - align columns 5145 settings.aoDrawCallback.push( { 5146 "fn": _fnScrollDraw, 5147 "sName": "scrolling" 5148 } ); 5149 5150 return scroller[0]; 5151 } 5152 5153 5154 5155 /** 5156 * Update the header, footer and body tables for resizing - i.e. column 5157 * alignment. 5158 * 5159 * Welcome to the most horrible function DataTables. The process that this 5160 * function follows is basically: 5161 * 1. Re-create the table inside the scrolling div 5162 * 2. Take live measurements from the DOM 5163 * 3. Apply the measurements to align the columns 5164 * 4. Clean up 5165 * 5166 * @param {object} settings dataTables settings object 5167 * @memberof DataTable#oApi 5168 */ 5169 function _fnScrollDraw ( settings ) 5170 { 5171 // Given that this is such a monster function, a lot of variables are use 5172 // to try and keep the minimised size as small as possible 5173 var 5174 scroll = settings.oScroll, 5175 scrollX = scroll.sX, 5176 scrollXInner = scroll.sXInner, 5177 scrollY = scroll.sY, 5178 barWidth = scroll.iBarWidth, 5179 divHeader = $(settings.nScrollHead), 5180 divHeaderStyle = divHeader[0].style, 5181 divHeaderInner = divHeader.children('div'), 5182 divHeaderInnerStyle = divHeaderInner[0].style, 5183 divHeaderTable = divHeaderInner.children('table'), 5184 divBodyEl = settings.nScrollBody, 5185 divBody = $(divBodyEl), 5186 divBodyStyle = divBodyEl.style, 5187 divFooter = $(settings.nScrollFoot), 5188 divFooterInner = divFooter.children('div'), 5189 divFooterTable = divFooterInner.children('table'), 5190 header = $(settings.nTHead), 5191 table = $(settings.nTable), 5192 tableEl = table[0], 5193 tableStyle = tableEl.style, 5194 footer = settings.nTFoot ? $(settings.nTFoot) : null, 5195 browser = settings.oBrowser, 5196 ie67 = browser.bScrollOversize, 5197 dtHeaderCells = _pluck( settings.aoColumns, 'nTh' ), 5198 headerTrgEls, footerTrgEls, 5199 headerSrcEls, footerSrcEls, 5200 headerCopy, footerCopy, 5201 headerWidths=[], footerWidths=[], 5202 headerContent=[], footerContent=[], 5203 idx, correction, sanityWidth, 5204 zeroOut = function(nSizer) { 5205 var style = nSizer.style; 5206 style.paddingTop = "0"; 5207 style.paddingBottom = "0"; 5208 style.borderTopWidth = "0"; 5209 style.borderBottomWidth = "0"; 5210 style.height = 0; 5211 }; 5212 5213 // If the scrollbar visibility has changed from the last draw, we need to 5214 // adjust the column sizes as the table width will have changed to account 5215 // for the scrollbar 5216 var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight; 5217 5218 if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) { 5219 settings.scrollBarVis = scrollBarVis; 5220 _fnAdjustColumnSizing( settings ); 5221 return; // adjust column sizing will call this function again 5222 } 5223 else { 5224 settings.scrollBarVis = scrollBarVis; 5225 } 5226 5227 /* 5228 * 1. Re-create the table inside the scrolling div 5229 */ 5230 5231 // Remove the old minimised thead and tfoot elements in the inner table 5232 table.children('thead, tfoot').remove(); 5233 5234 if ( footer ) { 5235 footerCopy = footer.clone().prependTo( table ); 5236 footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized 5237 footerSrcEls = footerCopy.find('tr'); 5238 } 5239 5240 // Clone the current header and footer elements and then place it into the inner table 5241 headerCopy = header.clone().prependTo( table ); 5242 headerTrgEls = header.find('tr'); // original header is in its own table 5243 headerSrcEls = headerCopy.find('tr'); 5244 headerCopy.find('th, td').removeAttr('tabindex'); 5245 5246 5247 /* 5248 * 2. Take live measurements from the DOM - do not alter the DOM itself! 5249 */ 5250 5251 // Remove old sizing and apply the calculated column widths 5252 // Get the unique column headers in the newly created (cloned) header. We want to apply the 5253 // calculated sizes to this header 5254 if ( ! scrollX ) 5255 { 5256 divBodyStyle.width = '100%'; 5257 divHeader[0].style.width = '100%'; 5258 } 5259 5260 $.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) { 5261 idx = _fnVisibleToColumnIndex( settings, i ); 5262 el.style.width = settings.aoColumns[idx].sWidth; 5263 } ); 5264 5265 if ( footer ) { 5266 _fnApplyToChildren( function(n) { 5267 n.style.width = ""; 5268 }, footerSrcEls ); 5269 } 5270 5271 // Size the table as a whole 5272 sanityWidth = table.outerWidth(); 5273 if ( scrollX === "" ) { 5274 // No x scrolling 5275 tableStyle.width = "100%"; 5276 5277 // IE7 will make the width of the table when 100% include the scrollbar 5278 // - which is shouldn't. When there is a scrollbar we need to take this 5279 // into account. 5280 if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight || 5281 divBody.css('overflow-y') == "scroll") 5282 ) { 5283 tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth); 5284 } 5285 5286 // Recalculate the sanity width 5287 sanityWidth = table.outerWidth(); 5288 } 5289 else if ( scrollXInner !== "" ) { 5290 // legacy x scroll inner has been given - use it 5291 tableStyle.width = _fnStringToCss(scrollXInner); 5292 5293 // Recalculate the sanity width 5294 sanityWidth = table.outerWidth(); 5295 } 5296 5297 // Hidden header should have zero height, so remove padding and borders. Then 5298 // set the width based on the real headers 5299 5300 // Apply all styles in one pass 5301 _fnApplyToChildren( zeroOut, headerSrcEls ); 5302 5303 // Read all widths in next pass 5304 _fnApplyToChildren( function(nSizer) { 5305 headerContent.push( nSizer.innerHTML ); 5306 headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) ); 5307 }, headerSrcEls ); 5308 5309 // Apply all widths in final pass 5310 _fnApplyToChildren( function(nToSize, i) { 5311 // Only apply widths to the DataTables detected header cells - this 5312 // prevents complex headers from having contradictory sizes applied 5313 if ( $.inArray( nToSize, dtHeaderCells ) !== -1 ) { 5314 nToSize.style.width = headerWidths[i]; 5315 } 5316 }, headerTrgEls ); 5317 5318 $(headerSrcEls).height(0); 5319 5320 /* Same again with the footer if we have one */ 5321 if ( footer ) 5322 { 5323 _fnApplyToChildren( zeroOut, footerSrcEls ); 5324 5325 _fnApplyToChildren( function(nSizer) { 5326 footerContent.push( nSizer.innerHTML ); 5327 footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) ); 5328 }, footerSrcEls ); 5329 5330 _fnApplyToChildren( function(nToSize, i) { 5331 nToSize.style.width = footerWidths[i]; 5332 }, footerTrgEls ); 5333 5334 $(footerSrcEls).height(0); 5335 } 5336 5337 5338 /* 5339 * 3. Apply the measurements 5340 */ 5341 5342 // "Hide" the header and footer that we used for the sizing. We need to keep 5343 // the content of the cell so that the width applied to the header and body 5344 // both match, but we want to hide it completely. We want to also fix their 5345 // width to what they currently are 5346 _fnApplyToChildren( function(nSizer, i) { 5347 nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent[i]+'</div>'; 5348 nSizer.style.width = headerWidths[i]; 5349 }, headerSrcEls ); 5350 5351 if ( footer ) 5352 { 5353 _fnApplyToChildren( function(nSizer, i) { 5354 nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+footerContent[i]+'</div>'; 5355 nSizer.style.width = footerWidths[i]; 5356 }, footerSrcEls ); 5357 } 5358 5359 // Sanity check that the table is of a sensible width. If not then we are going to get 5360 // misalignment - try to prevent this by not allowing the table to shrink below its min width 5361 if ( table.outerWidth() < sanityWidth ) 5362 { 5363 // The min width depends upon if we have a vertical scrollbar visible or not */ 5364 correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight || 5365 divBody.css('overflow-y') == "scroll")) ? 5366 sanityWidth+barWidth : 5367 sanityWidth; 5368 5369 // IE6/7 are a law unto themselves... 5370 if ( ie67 && (divBodyEl.scrollHeight > 5371 divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll") 5372 ) { 5373 tableStyle.width = _fnStringToCss( correction-barWidth ); 5374 } 5375 5376 // And give the user a warning that we've stopped the table getting too small 5377 if ( scrollX === "" || scrollXInner !== "" ) { 5378 _fnLog( settings, 1, 'Possible column misalignment', 6 ); 5379 } 5380 } 5381 else 5382 { 5383 correction = '100%'; 5384 } 5385 5386 // Apply to the container elements 5387 divBodyStyle.width = _fnStringToCss( correction ); 5388 divHeaderStyle.width = _fnStringToCss( correction ); 5389 5390 if ( footer ) { 5391 settings.nScrollFoot.style.width = _fnStringToCss( correction ); 5392 } 5393 5394 5395 /* 5396 * 4. Clean up 5397 */ 5398 if ( ! scrollY ) { 5399 /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting 5400 * the scrollbar height from the visible display, rather than adding it on. We need to 5401 * set the height in order to sort this. Don't want to do it in any other browsers. 5402 */ 5403 if ( ie67 ) { 5404 divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth ); 5405 } 5406 } 5407 5408 /* Finally set the width's of the header and footer tables */ 5409 var iOuterWidth = table.outerWidth(); 5410 divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth ); 5411 divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth ); 5412 5413 // Figure out if there are scrollbar present - if so then we need a the header and footer to 5414 // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar) 5415 var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll"; 5416 var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' ); 5417 divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px"; 5418 5419 if ( footer ) { 5420 divFooterTable[0].style.width = _fnStringToCss( iOuterWidth ); 5421 divFooterInner[0].style.width = _fnStringToCss( iOuterWidth ); 5422 divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px"; 5423 } 5424 5425 // Correct DOM ordering for colgroup - comes before the thead 5426 table.children('colgroup').insertBefore( table.children('thead') ); 5427 5428 /* Adjust the position of the header in case we loose the y-scrollbar */ 5429 divBody.scroll(
vendor: 11,594 bytes, lines 5429-5827
5429); 5430 5431 // If sorting or filtering has occurred, jump the scrolling back to the top 5432 // only if we aren't holding the position 5433 if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) { 5434 divBodyEl.scrollTop = 0; 5435 } 5436 } 5437 5438 5439 5440 /** 5441 * Apply a given function to the display child nodes of an element array (typically 5442 * TD children of TR rows 5443 * @param {function} fn Method to apply to the objects 5444 * @param array {nodes} an1 List of elements to look through for display children 5445 * @param array {nodes} an2 Another list (identical structure to the first) - optional 5446 * @memberof DataTable#oApi 5447 */ 5448 function _fnApplyToChildren( fn, an1, an2 ) 5449 { 5450 var index=0, i=0, iLen=an1.length; 5451 var nNode1, nNode2; 5452 5453 while ( i < iLen ) { 5454 nNode1 = an1[i].firstChild; 5455 nNode2 = an2 ? an2[i].firstChild : null; 5456 5457 while ( nNode1 ) { 5458 if ( nNode1.nodeType === 1 ) { 5459 if ( an2 ) { 5460 fn( nNode1, nNode2, index ); 5461 } 5462 else { 5463 fn( nNode1, index ); 5464 } 5465 5466 index++; 5467 } 5468 5469 nNode1 = nNode1.nextSibling; 5470 nNode2 = an2 ? nNode2.nextSibling : null; 5471 } 5472 5473 i++; 5474 } 5475 } 5476 5477 5478 5479 var __re_html_remove = /<.*?>/g; 5480 5481 5482 /** 5483 * Calculate the width of columns for the table 5484 * @param {object} oSettings dataTables settings object 5485 * @memberof DataTable#oApi 5486 */ 5487 function _fnCalculateColumnWidths ( oSettings ) 5488 { 5489 var 5490 table = oSettings.nTable, 5491 columns = oSettings.aoColumns, 5492 scroll = oSettings.oScroll, 5493 scrollY = scroll.sY, 5494 scrollX = scroll.sX, 5495 scrollXInner = scroll.sXInner, 5496 columnCount = columns.length, 5497 visibleColumns = _fnGetColumns( oSettings, 'bVisible' ), 5498 headerCells = $('th', oSettings.nTHead), 5499 tableWidthAttr = table.getAttribute('width'), // from DOM element 5500 tableContainer = table.parentNode, 5501 userInputs = false, 5502 i, column, columnIdx, width, outerWidth, 5503 browser = oSettings.oBrowser, 5504 ie67 = browser.bScrollOversize; 5505 5506 var styleWidth = table.style.width; 5507 if ( styleWidth && styleWidth.indexOf('%') !== -1 ) { 5508 tableWidthAttr = styleWidth; 5509 } 5510 5511 /* Convert any user input sizes into pixel sizes */ 5512 for ( i=0 ; i<visibleColumns.length ; i++ ) { 5513 column = columns[ visibleColumns[i] ]; 5514 5515 if ( column.sWidth !== null ) { 5516 column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer ); 5517 5518 userInputs = true; 5519 } 5520 } 5521 5522 /* If the number of columns in the DOM equals the number that we have to 5523 * process in DataTables, then we can use the offsets that are created by 5524 * the web- browser. No custom sizes can be set in order for this to happen, 5525 * nor scrolling used 5526 */ 5527 if ( ie67 || ! userInputs && ! scrollX && ! scrollY && 5528 columnCount == _fnVisbleColumns( oSettings ) && 5529 columnCount == headerCells.length 5530 ) { 5531 for ( i=0 ; i<columnCount ; i++ ) { 5532 var colIdx = _fnVisibleToColumnIndex( oSettings, i ); 5533 5534 if ( colIdx !== null ) { 5535 columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() ); 5536 } 5537 } 5538 } 5539 else 5540 { 5541 // Otherwise construct a single row, worst case, table with the widest 5542 // node in the data, assign any user defined widths, then insert it into 5543 // the DOM and allow the browser to do all the hard work of calculating 5544 // table widths 5545 var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table 5546 .css( 'visibility', 'hidden' ) 5547 .removeAttr( 'id' ); 5548 5549 // Clean up the table body 5550 tmpTable.find('tbody tr').remove(); 5551 var tr = $('<tr/>').appendTo( tmpTable.find('tbody') ); 5552 5553 // Clone the table header and footer - we can't use the header / footer 5554 // from the cloned table, since if scrolling is active, the table's 5555 // real header and footer are contained in different table tags 5556 tmpTable.find('thead, tfoot').remove(); 5557 tmpTable 5558 .append( $(oSettings.nTHead).clone() ) 5559 .append( $(oSettings.nTFoot).clone() ); 5560 5561 // Remove any assigned widths from the footer (from scrolling) 5562 tmpTable.find('tfoot th, tfoot td').css('width', ''); 5563 5564 // Apply custom sizing to the cloned header 5565 headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] ); 5566 5567 for ( i=0 ; i<visibleColumns.length ; i++ ) { 5568 column = columns[ visibleColumns[i] ]; 5569 5570 headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ? 5571 _fnStringToCss( column.sWidthOrig ) : 5572 ''; 5573 5574 // For scrollX we need to force the column width otherwise the 5575 // browser will collapse it. If this width is smaller than the 5576 // width the column requires, then it will have no effect 5577 if ( column.sWidthOrig && scrollX ) { 5578 $( headerCells[i] ).append( $('<div/>').css( { 5579 width: column.sWidthOrig, 5580 margin: 0, 5581 padding: 0, 5582 border: 0, 5583 height: 1 5584 } ) ); 5585 } 5586 } 5587 5588 // Find the widest cell for each column and put it into the table 5589 if ( oSettings.aoData.length ) { 5590 for ( i=0 ; i<visibleColumns.length ; i++ ) { 5591 columnIdx = visibleColumns[i]; 5592 column = columns[ columnIdx ]; 5593 5594 $( _fnGetWidestNode( oSettings, columnIdx ) ) 5595 .clone( false ) 5596 .append( column.sContentPadding ) 5597 .appendTo( tr ); 5598 } 5599 } 5600 5601 // Tidy the temporary table - remove name attributes so there aren't 5602 // duplicated in the dom (radio elements for example) 5603 $('[name]', tmpTable).removeAttr('name'); 5604 5605 // Table has been built, attach to the document so we can work with it. 5606 // A holding element is used, positioned at the top of the container 5607 // with minimal height, so it has no effect on if the container scrolls 5608 // or not. Otherwise it might trigger scrolling when it actually isn't 5609 // needed 5610 var holder = $('<div/>').css( scrollX || scrollY ? 5611 { 5612 position: 'absolute', 5613 top: 0, 5614 left: 0, 5615 height: 1, 5616 right: 0, 5617 overflow: 'hidden' 5618 } : 5619 {} 5620 ) 5621 .append( tmpTable ) 5622 .appendTo( tableContainer ); 5623 5624 // When scrolling (X or Y) we want to set the width of the table as 5625 // appropriate. However, when not scrolling leave the table width as it 5626 // is. This results in slightly different, but I think correct behaviour 5627 if ( scrollX && scrollXInner ) { 5628 tmpTable.width( scrollXInner ); 5629 } 5630 else if ( scrollX ) { 5631 tmpTable.css( 'width', 'auto' ); 5632 tmpTable.removeAttr('width'); 5633 5634 // If there is no width attribute or style, then allow the table to 5635 // collapse 5636 if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) { 5637 tmpTable.width( tableContainer.clientWidth ); 5638 } 5639 } 5640 else if ( scrollY ) { 5641 tmpTable.width( tableContainer.clientWidth ); 5642 } 5643 else if ( tableWidthAttr ) { 5644 tmpTable.width( tableWidthAttr ); 5645 } 5646 5647 // Get the width of each column in the constructed table - we need to 5648 // know the inner width (so it can be assigned to the other table's 5649 // cells) and the outer width so we can calculate the full width of the 5650 // table. This is safe since DataTables requires a unique cell for each 5651 // column, but if ever a header can span multiple columns, this will 5652 // need to be modified. 5653 var total = 0; 5654 for ( i=0 ; i<visibleColumns.length ; i++ ) { 5655 var cell = $(headerCells[i]); 5656 var border = cell.outerWidth() - cell.width(); 5657 5658 // Use getBounding... where possible (not IE8-) because it can give 5659 // sub-pixel accuracy, which we then want to round up! 5660 var bounding = browser.bBounding ? 5661 Math.ceil( headerCells[i].getBoundingClientRect().width ) : 5662 cell.outerWidth(); 5663 5664 // Total is tracked to remove any sub-pixel errors as the outerWidth 5665 // of the table might not equal the total given here (IE!). 5666 total += bounding; 5667 5668 // Width for each column to use 5669 columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border ); 5670 } 5671 5672 table.style.width = _fnStringToCss( total ); 5673 5674 // Finished with the table - ditch it 5675 holder.remove(); 5676 } 5677 5678 // If there is a width attr, we want to attach an event listener which 5679 // allows the table sizing to automatically adjust when the window is 5680 // resized. Use the width attr rather than CSS, since we can't know if the 5681 // CSS is a relative value or absolute - DOM read is always px. 5682 if ( tableWidthAttr ) { 5683 table.style.width = _fnStringToCss( tableWidthAttr ); 5684 } 5685 5686 if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) { 5687 var bindResize = function () { 5688 $(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () { 5689 _fnAdjustColumnSizing( oSettings ); 5690 } ) ); 5691 }; 5692 5693 // IE6/7 will crash if we bind a resize event handler on page load. 5694 // To be removed in 1.11 which drops IE6/7 support 5695 if ( ie67 ) { 5696 setTimeout( bindResize, 1000 ); 5697 } 5698 else { 5699 bindResize(); 5700 } 5701 5702 oSettings._reszEvt = true; 5703 } 5704 } 5705 5706 5707 /** 5708 * Throttle the calls to a function. Arguments and context are maintained for 5709 * the throttled function 5710 * @param {function} fn Function to be called 5711 * @param {int} [freq=200] call frequency in mS 5712 * @returns {function} wrapped function 5713 * @memberof DataTable#oApi 5714 */ 5715 var _fnThrottle = DataTable.util.throttle; 5716 5717 5718 /** 5719 * Convert a CSS unit width to pixels (e.g. 2em) 5720 * @param {string} width width to be converted 5721 * @param {node} parent parent to get the with for (required for relative widths) - optional 5722 * @returns {int} width in pixels 5723 * @memberof DataTable#oApi 5724 */ 5725 function _fnConvertToWidth ( width, parent ) 5726 { 5727 if ( ! width ) { 5728 return 0; 5729 } 5730 5731 var n = $('<div/>') 5732 .css( 'width', _fnStringToCss( width ) ) 5733 .appendTo( parent || document.body ); 5734 5735 var val = n[0].offsetWidth; 5736 n.remove(); 5737 5738 return val; 5739 } 5740 5741 5742 /** 5743 * Get the widest node 5744 * @param {object} settings dataTables settings object 5745 * @param {int} colIdx column of interest 5746 * @returns {node} widest table node 5747 * @memberof DataTable#oApi 5748 */ 5749 function _fnGetWidestNode( settings, colIdx ) 5750 { 5751 var idx = _fnGetMaxLenString( settings, colIdx ); 5752 if ( idx < 0 ) { 5753 return null; 5754 } 5755 5756 var data = settings.aoData[ idx ]; 5757 return ! data.nTr ? // Might not have been created when deferred rendering 5758 $('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] : 5759 data.anCells[ colIdx ]; 5760 } 5761 5762 5763 /** 5764 * Get the maximum strlen for each data column 5765 * @param {object} settings dataTables settings object 5766 * @param {int} colIdx column of interest 5767 * @returns {string} max string length for each column 5768 * @memberof DataTable#oApi 5769 */ 5770 function _fnGetMaxLenString( settings, colIdx ) 5771 { 5772 var s, max=-1, maxIdx = -1; 5773 5774 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 5775 s = _fnGetCellData( settings, i, colIdx, 'display' )+''; 5776 s = s.replace( __re_html_remove, '' ); 5777 s = s.replace( / /g, ' ' ); 5778 5779 if ( s.length > max ) { 5780 max = s.length; 5781 maxIdx = i; 5782 } 5783 } 5784 5785 return maxIdx; 5786 } 5787 5788 5789 /** 5790 * Append a CSS unit (only if required) to a string 5791 * @param {string} value to css-ify 5792 * @returns {string} value with css unit 5793 * @memberof DataTable#oApi 5794 */ 5795 function _fnStringToCss( s ) 5796 { 5797 if ( s === null ) { 5798 return '0px'; 5799 } 5800 5801 if ( typeof s == 'number' ) { 5802 return s < 0 ? 5803 '0px' : 5804 s+'px'; 5805 } 5806 5807 // Check it has a unit character already 5808 return s.match(/\d$/) ? 5809 s+'px' : 5810 s; 5811 } 5812 5813 5814 5815 function _fnSortFlatten ( settings ) 5816 { 5817 var 5818 i, iLen, k, kLen, 5819 aSort = [], 5820 aiOrig = [], 5821 aoColumns = settings.aoColumns, 5822 aDataSort, iCol, sType, srcCol, 5823 fixed = settings.aaSortingFixed, 5824 fixedObj = $.isPlainObject( fixed ), 5825 nestedSort = [], 5826 add = function ( a ) { 5827 if ( a.length && !
vendor: 39,694 bytes, lines 5827-7343
5827$.isArray( a[0] ) ) { 5828 // 1D array 5829 nestedSort.push( a ); 5830 } 5831 else { 5832 // 2D array 5833 $.merge( nestedSort, a ); 5834 } 5835 }; 5836 5837 // Build the sort array, with pre-fix and post-fix options if they have been 5838 // specified 5839 if ( $.isArray( fixed ) ) { 5840 add( fixed ); 5841 } 5842 5843 if ( fixedObj && fixed.pre ) { 5844 add( fixed.pre ); 5845 } 5846 5847 add( settings.aaSorting ); 5848 5849 if (fixedObj && fixed.post ) { 5850 add( fixed.post ); 5851 } 5852 5853 for ( i=0 ; i<nestedSort.length ; i++ ) 5854 { 5855 srcCol = nestedSort[i][0]; 5856 aDataSort = aoColumns[ srcCol ].aDataSort; 5857 5858 for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ ) 5859 { 5860 iCol = aDataSort[k]; 5861 sType = aoColumns[ iCol ].sType || 'string'; 5862 5863 if ( nestedSort[i]._idx === undefined ) { 5864 nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting ); 5865 } 5866 5867 aSort.push( { 5868 src: srcCol, 5869 col: iCol, 5870 dir: nestedSort[i][1], 5871 index: nestedSort[i]._idx, 5872 type: sType, 5873 formatter: DataTable.ext.type.order[ sType+"-pre" ] 5874 } ); 5875 } 5876 } 5877 5878 return aSort; 5879 } 5880 5881 /** 5882 * Change the order of the table 5883 * @param {object} oSettings dataTables settings object 5884 * @memberof DataTable#oApi 5885 * @todo This really needs split up! 5886 */ 5887 function _fnSort ( oSettings ) 5888 { 5889 var 5890 i, ien, iLen, j, jLen, k, kLen, 5891 sDataType, nTh, 5892 aiOrig = [], 5893 oExtSort = DataTable.ext.type.order, 5894 aoData = oSettings.aoData, 5895 aoColumns = oSettings.aoColumns, 5896 aDataSort, data, iCol, sType, oSort, 5897 formatters = 0, 5898 sortCol, 5899 displayMaster = oSettings.aiDisplayMaster, 5900 aSort; 5901 5902 // Resolve any column types that are unknown due to addition or invalidation 5903 // @todo Can this be moved into a 'data-ready' handler which is called when 5904 // data is going to be used in the table? 5905 _fnColumnTypes( oSettings ); 5906 5907 aSort = _fnSortFlatten( oSettings ); 5908 5909 for ( i=0, ien=aSort.length ; i<ien ; i++ ) { 5910 sortCol = aSort[i]; 5911 5912 // Track if we can use the fast sort algorithm 5913 if ( sortCol.formatter ) { 5914 formatters++; 5915 } 5916 5917 // Load the data needed for the sort, for each cell 5918 _fnSortData( oSettings, sortCol.col ); 5919 } 5920 5921 /* No sorting required if server-side or no sorting array */ 5922 if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 ) 5923 { 5924 // Create a value - key array of the current row positions such that we can use their 5925 // current position during the sort, if values match, in order to perform stable sorting 5926 for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) { 5927 aiOrig[ displayMaster[i] ] = i; 5928 } 5929 5930 /* Do the sort - here we want multi-column sorting based on a given data source (column) 5931 * and sorting function (from oSort) in a certain direction. It's reasonably complex to 5932 * follow on it's own, but this is what we want (example two column sorting): 5933 * fnLocalSorting = function(a,b){ 5934 * var iTest; 5935 * iTest = oSort['string-asc']('data11', 'data12'); 5936 * if (iTest !== 0) 5937 * return iTest; 5938 * iTest = oSort['numeric-desc']('data21', 'data22'); 5939 * if (iTest !== 0) 5940 * return iTest; 5941 * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] ); 5942 * } 5943 * Basically we have a test for each sorting column, if the data in that column is equal, 5944 * test the next column. If all columns match, then we use a numeric sort on the row 5945 * positions in the original data array to provide a stable sort. 5946 * 5947 * Note - I know it seems excessive to have two sorting methods, but the first is around 5948 * 15% faster, so the second is only maintained for backwards compatibility with sorting 5949 * methods which do not have a pre-sort formatting function. 5950 */ 5951 if ( formatters === aSort.length ) { 5952 // All sort types have formatting functions 5953 displayMaster.sort( function ( a, b ) { 5954 var 5955 x, y, k, test, sort, 5956 len=aSort.length, 5957 dataA = aoData[a]._aSortData, 5958 dataB = aoData[b]._aSortData; 5959 5960 for ( k=0 ; k<len ; k++ ) { 5961 sort = aSort[k]; 5962 5963 x = dataA[ sort.col ]; 5964 y = dataB[ sort.col ]; 5965 5966 test = x<y ? -1 : x>y ? 1 : 0; 5967 if ( test !== 0 ) { 5968 return sort.dir === 'asc' ? test : -test; 5969 } 5970 } 5971 5972 x = aiOrig[a]; 5973 y = aiOrig[b]; 5974 return x<y ? -1 : x>y ? 1 : 0; 5975 } ); 5976 } 5977 else { 5978 // Depreciated - remove in 1.11 (providing a plug-in option) 5979 // Not all sort types have formatting methods, so we have to call their sorting 5980 // methods. 5981 displayMaster.sort( function ( a, b ) { 5982 var 5983 x, y, k, l, test, sort, fn, 5984 len=aSort.length, 5985 dataA = aoData[a]._aSortData, 5986 dataB = aoData[b]._aSortData; 5987 5988 for ( k=0 ; k<len ; k++ ) { 5989 sort = aSort[k]; 5990 5991 x = dataA[ sort.col ]; 5992 y = dataB[ sort.col ]; 5993 5994 fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ]; 5995 test = fn( x, y ); 5996 if ( test !== 0 ) { 5997 return test; 5998 } 5999 } 6000 6001 x = aiOrig[a]; 6002 y = aiOrig[b]; 6003 return x<y ? -1 : x>y ? 1 : 0; 6004 } ); 6005 } 6006 } 6007 6008 /* Tell the draw function that we have sorted the data */ 6009 oSettings.bSorted = true; 6010 } 6011 6012 6013 function _fnSortAria ( settings ) 6014 { 6015 var label; 6016 var nextSort; 6017 var columns = settings.aoColumns; 6018 var aSort = _fnSortFlatten( settings ); 6019 var oAria = settings.oLanguage.oAria; 6020 6021 // ARIA attributes - need to loop all columns, to update all (removing old 6022 // attributes as needed) 6023 for ( var i=0, iLen=columns.length ; i<iLen ; i++ ) 6024 { 6025 var col = columns[i]; 6026 var asSorting = col.asSorting; 6027 var sTitle = col.sTitle.replace( /<.*?>/g, "" ); 6028 var th = col.nTh; 6029 6030 // IE7 is throwing an error when setting these properties with jQuery's 6031 // attr() and removeAttr() methods... 6032 th.removeAttribute('aria-sort'); 6033 6034 /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */ 6035 if ( col.bSortable ) { 6036 if ( aSort.length > 0 && aSort[0].col == i ) { 6037 th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" ); 6038 nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0]; 6039 } 6040 else { 6041 nextSort = asSorting[0]; 6042 } 6043 6044 label = sTitle + ( nextSort === "asc" ? 6045 oAria.sSortAscending : 6046 oAria.sSortDescending 6047 ); 6048 } 6049 else { 6050 label = sTitle; 6051 } 6052 6053 th.setAttribute('aria-label', label); 6054 } 6055 } 6056 6057 6058 /** 6059 * Function to run on user sort request 6060 * @param {object} settings dataTables settings object 6061 * @param {node} attachTo node to attach the handler to 6062 * @param {int} colIdx column sorting index 6063 * @param {boolean} [append=false] Append the requested sort to the existing 6064 * sort if true (i.e. multi-column sort) 6065 * @param {function} [callback] callback function 6066 * @memberof DataTable#oApi 6067 */ 6068 function _fnSortListener ( settings, colIdx, append, callback ) 6069 { 6070 var col = settings.aoColumns[ colIdx ]; 6071 var sorting = settings.aaSorting; 6072 var asSorting = col.asSorting; 6073 var nextSortIdx; 6074 var next = function ( a, overflow ) { 6075 var idx = a._idx; 6076 if ( idx === undefined ) { 6077 idx = $.inArray( a[1], asSorting ); 6078 } 6079 6080 return idx+1 < asSorting.length ? 6081 idx+1 : 6082 overflow ? 6083 null : 6084 0; 6085 }; 6086 6087 // Convert to 2D array if needed 6088 if ( typeof sorting[0] === 'number' ) { 6089 sorting = settings.aaSorting = [ sorting ]; 6090 } 6091 6092 // If appending the sort then we are multi-column sorting 6093 if ( append && settings.oFeatures.bSortMulti ) { 6094 // Are we already doing some kind of sort on this column? 6095 var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') ); 6096 6097 if ( sortIdx !== -1 ) { 6098 // Yes, modify the sort 6099 nextSortIdx = next( sorting[sortIdx], true ); 6100 6101 if ( nextSortIdx === null && sorting.length === 1 ) { 6102 nextSortIdx = 0; // can't remove sorting completely 6103 } 6104 6105 if ( nextSortIdx === null ) { 6106 sorting.splice( sortIdx, 1 ); 6107 } 6108 else { 6109 sorting[sortIdx][1] = asSorting[ nextSortIdx ]; 6110 sorting[sortIdx]._idx = nextSortIdx; 6111 } 6112 } 6113 else { 6114 // No sort on this column yet 6115 sorting.push( [ colIdx, asSorting[0], 0 ] ); 6116 sorting[sorting.length-1]._idx = 0; 6117 } 6118 } 6119 else if ( sorting.length && sorting[0][0] == colIdx ) { 6120 // Single column - already sorting on this column, modify the sort 6121 nextSortIdx = next( sorting[0] ); 6122 6123 sorting.length = 1; 6124 sorting[0][1] = asSorting[ nextSortIdx ]; 6125 sorting[0]._idx = nextSortIdx; 6126 } 6127 else { 6128 // Single column - sort only on this column 6129 sorting.length = 0; 6130 sorting.push( [ colIdx, asSorting[0] ] ); 6131 sorting[0]._idx = 0; 6132 } 6133 6134 // Run the sort by calling a full redraw 6135 _fnReDraw( settings ); 6136 6137 // callback used for async user interaction 6138 if ( typeof callback == 'function' ) { 6139 callback( settings ); 6140 } 6141 } 6142 6143 6144 /** 6145 * Attach a sort handler (click) to a node 6146 * @param {object} settings dataTables settings object 6147 * @param {node} attachTo node to attach the handler to 6148 * @param {int} colIdx column sorting index 6149 * @param {function} [callback] callback function 6150 * @memberof DataTable#oApi 6151 */ 6152 function _fnSortAttachListener ( settings, attachTo, colIdx, callback ) 6153 { 6154 var col = settings.aoColumns[ colIdx ]; 6155 6156 _fnBindAction( attachTo, {}, function (e) { 6157 /* If the column is not sortable - don't to anything */ 6158 if ( col.bSortable === false ) { 6159 return; 6160 } 6161 6162 // If processing is enabled use a timeout to allow the processing 6163 // display to be shown - otherwise to it synchronously 6164 if ( settings.oFeatures.bProcessing ) { 6165 _fnProcessingDisplay( settings, true ); 6166 6167 setTimeout( function() { 6168 _fnSortListener( settings, colIdx, e.shiftKey, callback ); 6169 6170 // In server-side processing, the draw callback will remove the 6171 // processing display 6172 if ( _fnDataSource( settings ) !== 'ssp' ) { 6173 _fnProcessingDisplay( settings, false ); 6174 } 6175 }, 0 ); 6176 } 6177 else { 6178 _fnSortListener( settings, colIdx, e.shiftKey, callback ); 6179 } 6180 } ); 6181 } 6182 6183 6184 /** 6185 * Set the sorting classes on table's body, Note: it is safe to call this function 6186 * when bSort and bSortClasses are false 6187 * @param {object} oSettings dataTables settings object 6188 * @memberof DataTable#oApi 6189 */ 6190 function _fnSortingClasses( settings ) 6191 { 6192 var oldSort = settings.aLastSort; 6193 var sortClass = settings.oClasses.sSortColumn; 6194 var sort = _fnSortFlatten( settings ); 6195 var features = settings.oFeatures; 6196 var i, ien, colIdx; 6197 6198 if ( features.bSort && features.bSortClasses ) { 6199 // Remove old sorting classes 6200 for ( i=0, ien=oldSort.length ; i<ien ; i++ ) { 6201 colIdx = oldSort[i].src; 6202 6203 // Remove column sorting 6204 $( _pluck( settings.aoData, 'anCells', colIdx ) ) 6205 .removeClass( sortClass + (i<2 ? i+1 : 3) ); 6206 } 6207 6208 // Add new column sorting 6209 for ( i=0, ien=sort.length ; i<ien ; i++ ) { 6210 colIdx = sort[i].src; 6211 6212 $( _pluck( settings.aoData, 'anCells', colIdx ) ) 6213 .addClass( sortClass + (i<2 ? i+1 : 3) ); 6214 } 6215 } 6216 6217 settings.aLastSort = sort; 6218 } 6219 6220 6221 // Get the data to sort a column, be it from cache, fresh (populating the 6222 // cache), or from a sort formatter 6223 function _fnSortData( settings, idx ) 6224 { 6225 // Custom sorting function - provided by the sort data type 6226 var column = settings.aoColumns[ idx ]; 6227 var customSort = DataTable.ext.order[ column.sSortDataType ]; 6228 var customData; 6229 6230 if ( customSort ) { 6231 customData = customSort.call( settings.oInstance, settings, idx, 6232 _fnColumnIndexToVisible( settings, idx ) 6233 ); 6234 } 6235 6236 // Use / populate cache 6237 var row, cellData; 6238 var formatter = DataTable.ext.type.order[ column.sType+"-pre" ]; 6239 6240 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 6241 row = settings.aoData[i]; 6242 6243 if ( ! row._aSortData ) { 6244 row._aSortData = []; 6245 } 6246 6247 if ( ! row._aSortData[idx] || customSort ) { 6248 cellData = customSort ? 6249 customData[i] : // If there was a custom sort function, use data from there 6250 _fnGetCellData( settings, i, idx, 'sort' ); 6251 6252 row._aSortData[ idx ] = formatter ? 6253 formatter( cellData ) : 6254 cellData; 6255 } 6256 } 6257 } 6258 6259 6260 6261 /** 6262 * Save the state of a table 6263 * @param {object} oSettings dataTables settings object 6264 * @memberof DataTable#oApi 6265 */ 6266 function _fnSaveState ( settings ) 6267 { 6268 if ( !settings.oFeatures.bStateSave || settings.bDestroying ) 6269 { 6270 return; 6271 } 6272 6273 /* Store the interesting variables */ 6274 var state = { 6275 time: +new Date(), 6276 start: settings._iDisplayStart, 6277 length: settings._iDisplayLength, 6278 order: $.extend( true, [], settings.aaSorting ), 6279 search: _fnSearchToCamel( settings.oPreviousSearch ), 6280 columns: $.map( settings.aoColumns, function ( col, i ) { 6281 return { 6282 visible: col.bVisible, 6283 search: _fnSearchToCamel( settings.aoPreSearchCols[i] ) 6284 }; 6285 } ) 6286 }; 6287 6288 _fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] ); 6289 6290 settings.oSavedState = state; 6291 settings.fnStateSaveCallback.call( settings.oInstance, settings, state ); 6292 } 6293 6294 6295 /** 6296 * Attempt to load a saved table state 6297 * @param {object} oSettings dataTables settings object 6298 * @param {object} oInit DataTables init object so we can override settings 6299 * @param {function} callback Callback to execute when the state has been loaded 6300 * @memberof DataTable#oApi 6301 */ 6302 function _fnLoadState ( settings, oInit, callback ) 6303 { 6304 var i, ien; 6305 var columns = settings.aoColumns; 6306 var loaded = function ( s ) { 6307 if ( ! s || ! s.time ) { 6308 callback(); 6309 return; 6310 } 6311 6312 // Allow custom and plug-in manipulation functions to alter the saved data set and 6313 // cancelling of loading by returning false 6314 var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, state] ); 6315 if ( $.inArray( false, abStateLoad ) !== -1 ) { 6316 callback(); 6317 return; 6318 } 6319 6320 // Reject old data 6321 var duration = settings.iStateDuration; 6322 if ( duration > 0 && s.time < +new Date() - (duration*1000) ) { 6323 callback(); 6324 return; 6325 } 6326 6327 // Number of columns have changed - all bets are off, no restore of settings 6328 if ( s.columns && columns.length !== s.columns.length ) { 6329 callback(); 6330 return; 6331 } 6332 6333 // Store the saved state so it might be accessed at any time 6334 settings.oLoadedState = $.extend( true, {}, state ); 6335 6336 // Restore key features - todo - for 1.11 this needs to be done by 6337 // subscribed events 6338 if ( s.start !== undefined ) { 6339 settings._iDisplayStart = s.start; 6340 settings.iInitDisplayStart = s.start; 6341 } 6342 if ( s.length !== undefined ) { 6343 settings._iDisplayLength = s.length; 6344 } 6345 6346 // Order 6347 if ( s.order !== undefined ) { 6348 settings.aaSorting = []; 6349 $.each( s.order, function ( i, col ) { 6350 settings.aaSorting.push( col[0] >= columns.length ? 6351 [ 0, col[1] ] : 6352 col 6353 ); 6354 } ); 6355 } 6356 6357 // Search 6358 if ( s.search !== undefined ) { 6359 $.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) ); 6360 } 6361 6362 // Columns 6363 // 6364 if ( s.columns ) { 6365 for ( i=0, ien=s.columns.length ; i<ien ; i++ ) { 6366 var col = s.columns[i]; 6367 6368 // Visibility 6369 if ( col.visible !== undefined ) { 6370 columns[i].bVisible = col.visible; 6371 } 6372 6373 // Search 6374 if ( col.search !== undefined ) { 6375 $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) ); 6376 } 6377 } 6378 } 6379 6380 _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, state] ); 6381 callback(); 6382 } 6383 6384 if ( ! settings.oFeatures.bStateSave ) { 6385 callback(); 6386 return; 6387 } 6388 6389 var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded ); 6390 6391 if ( state !== undefined ) { 6392 loaded( state ); 6393 } 6394 // otherwise, wait for the loaded callback to be executed 6395 } 6396 6397 6398 /** 6399 * Return the settings object for a particular table 6400 * @param {node} table table we are using as a dataTable 6401 * @returns {object} Settings object - or null if not found 6402 * @memberof DataTable#oApi 6403 */ 6404 function _fnSettingsFromNode ( table ) 6405 { 6406 var settings = DataTable.settings; 6407 var idx = $.inArray( table, _pluck( settings, 'nTable' ) ); 6408 6409 return idx !== -1 ? 6410 settings[ idx ] : 6411 null; 6412 } 6413 6414 6415 /** 6416 * Log an error message 6417 * @param {object} settings dataTables settings object 6418 * @param {int} level log error messages, or display them to the user 6419 * @param {string} msg error message 6420 * @param {int} tn Technical note id to get more information about the error. 6421 * @memberof DataTable#oApi 6422 */ 6423 function _fnLog( settings, level, msg, tn ) 6424 { 6425 msg = 'DataTables warning: '+ 6426 (settings ? 'table id='+settings.sTableId+' - ' : '')+msg; 6427 6428 if ( tn ) { 6429 msg += '. For more information about this error, please see '+ 6430 'http://datatables.net/tn/'+tn; 6431 } 6432 6433 if ( ! level ) { 6434 // Backwards compatibility pre 1.10 6435 var ext = DataTable.ext; 6436 var type = ext.sErrMode || ext.errMode; 6437 6438 if ( settings ) { 6439 _fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] ); 6440 } 6441 6442 if ( type == 'alert' ) { 6443 alert( msg ); 6444 } 6445 else if ( type == 'throw' ) { 6446 throw new Error(msg); 6447 } 6448 else if ( typeof type == 'function' ) { 6449 type( settings, tn, msg ); 6450 } 6451 } 6452 else if ( window.console && console.log ) { 6453 console.log( msg ); 6454 } 6455 } 6456 6457 6458 /** 6459 * See if a property is defined on one object, if so assign it to the other object 6460 * @param {object} ret target object 6461 * @param {object} src source object 6462 * @param {string} name property 6463 * @param {string} [mappedName] name to map too - optional, name used if not given 6464 * @memberof DataTable#oApi 6465 */ 6466 function _fnMap( ret, src, name, mappedName ) 6467 { 6468 if ( $.isArray( name ) ) { 6469 $.each( name, function (i, val) { 6470 if ( $.isArray( val ) ) { 6471 _fnMap( ret, src, val[0], val[1] ); 6472 } 6473 else { 6474 _fnMap( ret, src, val ); 6475 } 6476 } ); 6477 6478 return; 6479 } 6480 6481 if ( mappedName === undefined ) { 6482 mappedName = name; 6483 } 6484 6485 if ( src[name] !== undefined ) { 6486 ret[mappedName] = src[name]; 6487 } 6488 } 6489 6490 6491 /** 6492 * Extend objects - very similar to jQuery.extend, but deep copy objects, and 6493 * shallow copy arrays. The reason we need to do this, is that we don't want to 6494 * deep copy array init values (such as aaSorting) since the dev wouldn't be 6495 * able to override them, but we do want to deep copy arrays. 6496 * @param {object} out Object to extend 6497 * @param {object} extender Object from which the properties will be applied to 6498 * out 6499 * @param {boolean} breakRefs If true, then arrays will be sliced to take an 6500 * independent copy with the exception of the `data` or `aaData` parameters 6501 * if they are present. This is so you can pass in a collection to 6502 * DataTables and have that used as your data source without breaking the 6503 * references 6504 * @returns {object} out Reference, just for convenience - out === the return. 6505 * @memberof DataTable#oApi 6506 * @todo This doesn't take account of arrays inside the deep copied objects. 6507 */ 6508 function _fnExtend( out, extender, breakRefs ) 6509 { 6510 var val; 6511 6512 for ( var prop in extender ) { 6513 if ( extender.hasOwnProperty(prop) ) { 6514 val = extender[prop]; 6515 6516 if ( $.isPlainObject( val ) ) { 6517 if ( ! $.isPlainObject( out[prop] ) ) { 6518 out[prop] = {}; 6519 } 6520 $.extend( true, out[prop], val ); 6521 } 6522 else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) { 6523 out[prop] = val.slice(); 6524 } 6525 else { 6526 out[prop] = val; 6527 } 6528 } 6529 } 6530 6531 return out; 6532 } 6533 6534 6535 /** 6536 * Bind an event handers to allow a click or return key to activate the callback. 6537 * This is good for accessibility since a return on the keyboard will have the 6538 * same effect as a click, if the element has focus. 6539 * @param {element} n Element to bind the action to 6540 * @param {object} oData Data object to pass to the triggered function 6541 * @param {function} fn Callback function for when the event is triggered 6542 * @memberof DataTable#oApi 6543 */ 6544 function _fnBindAction( n, oData, fn ) 6545 { 6546 $(n) 6547 .on( 'click.DT', oData, function (e) { 6548 n.blur(); // Remove focus outline for mouse users 6549 fn(e); 6550 } ) 6551 .on( 'keypress.DT', oData, function (e){ 6552 if ( e.which === 13 ) { 6553 e.preventDefault(); 6554 fn(e); 6555 } 6556 } ) 6557 .on( 'selectstart.DT', function () { 6558 /* Take the brutal approach to cancelling text selection */ 6559 return false; 6560 } ); 6561 } 6562 6563 6564 /** 6565 * Register a callback function. Easily allows a callback function to be added to 6566 * an array store of callback functions that can then all be called together. 6567 * @param {object} oSettings dataTables settings object 6568 * @param {string} sStore Name of the array storage for the callbacks in oSettings 6569 * @param {function} fn Function to be called back 6570 * @param {string} sName Identifying name for the callback (i.e. a label) 6571 * @memberof DataTable#oApi 6572 */ 6573 function _fnCallbackReg( oSettings, sStore, fn, sName ) 6574 { 6575 if ( fn ) 6576 { 6577 oSettings[sStore].push( { 6578 "fn": fn, 6579 "sName": sName 6580 } ); 6581 } 6582 } 6583 6584 6585 /** 6586 * Fire callback functions and trigger events. Note that the loop over the 6587 * callback array store is done backwards! Further note that you do not want to 6588 * fire off triggers in time sensitive applications (for example cell creation) 6589 * as its slow. 6590 * @param {object} settings dataTables settings object 6591 * @param {string} callbackArr Name of the array storage for the callbacks in 6592 * oSettings 6593 * @param {string} eventName Name of the jQuery custom event to trigger. If 6594 * null no trigger is fired 6595 * @param {array} args Array of arguments to pass to the callback function / 6596 * trigger 6597 * @memberof DataTable#oApi 6598 */ 6599 function _fnCallbackFire( settings, callbackArr, eventName, args ) 6600 { 6601 var ret = []; 6602 6603 if ( callbackArr ) { 6604 ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) { 6605 return val.fn.apply( settings.oInstance, args ); 6606 } ); 6607 } 6608 6609 if ( eventName !== null ) { 6610 var e = $.Event( eventName+'.dt' ); 6611 6612 $(settings.nTable).trigger( e, args ); 6613 6614 ret.push( e.result ); 6615 } 6616 6617 return ret; 6618 } 6619 6620 6621 function _fnLengthOverflow ( settings ) 6622 { 6623 var 6624 start = settings._iDisplayStart, 6625 end = settings.fnDisplayEnd(), 6626 len = settings._iDisplayLength; 6627 6628 /* If we have space to show extra rows (backing up from the end point - then do so */ 6629 if ( start >= end ) 6630 { 6631 start = end - len; 6632 } 6633 6634 // Keep the start record on the current page 6635 start -= (start % len); 6636 6637 if ( len === -1 || start < 0 ) 6638 { 6639 start = 0; 6640 } 6641 6642 settings._iDisplayStart = start; 6643 } 6644 6645 6646 function _fnRenderer( settings, type ) 6647 { 6648 var renderer = settings.renderer; 6649 var host = DataTable.ext.renderer[type]; 6650 6651 if ( $.isPlainObject( renderer ) && renderer[type] ) { 6652 // Specific renderer for this type. If available use it, otherwise use 6653 // the default. 6654 return host[renderer[type]] || host._; 6655 } 6656 else if ( typeof renderer === 'string' ) { 6657 // Common renderer - if there is one available for this type use it, 6658 // otherwise use the default 6659 return host[renderer] || host._; 6660 } 6661 6662 // Use the default 6663 return host._; 6664 } 6665 6666 6667 /** 6668 * Detect the data source being used for the table. Used to simplify the code 6669 * a little (ajax) and to make it compress a little smaller. 6670 * 6671 * @param {object} settings dataTables settings object 6672 * @returns {string} Data source 6673 * @memberof DataTable#oApi 6674 */ 6675 function _fnDataSource ( settings ) 6676 { 6677 if ( settings.oFeatures.bServerSide ) { 6678 return 'ssp'; 6679 } 6680 else if ( settings.ajax || settings.sAjaxSource ) { 6681 return 'ajax'; 6682 } 6683 return 'dom'; 6684 } 6685 6686 6687 6688 6689 /** 6690 * Computed structure of the DataTables API, defined by the options passed to 6691 * `DataTable.Api.register()` when building the API. 6692 * 6693 * The structure is built in order to speed creation and extension of the Api 6694 * objects since the extensions are effectively pre-parsed. 6695 * 6696 * The array is an array of objects with the following structure, where this 6697 * base array represents the Api prototype base: 6698 * 6699 * [ 6700 * { 6701 * name: 'data' -- string - Property name 6702 * val: function () {}, -- function - Api method (or undefined if just an object 6703 * methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result 6704 * propExt: [ ... ] -- array - Array of Api object definitions to extend the property 6705 * }, 6706 * { 6707 * name: 'row' 6708 * val: {}, 6709 * methodExt: [ ... ], 6710 * propExt: [ 6711 * { 6712 * name: 'data' 6713 * val: function () {}, 6714 * methodExt: [ ... ], 6715 * propExt: [ ... ] 6716 * }, 6717 * ... 6718 * ] 6719 * } 6720 * ] 6721 * 6722 * @type {Array} 6723 * @ignore 6724 */ 6725 var __apiStruct = []; 6726 6727 6728 /** 6729 * `Array.prototype` reference. 6730 * 6731 * @type object 6732 * @ignore 6733 */ 6734 var __arrayProto = Array.prototype; 6735 6736 6737 /** 6738 * Abstraction for `context` parameter of the `Api` constructor to allow it to 6739 * take several different forms for ease of use. 6740 * 6741 * Each of the input parameter types will be converted to a DataTables settings 6742 * object where possible. 6743 * 6744 * @param {string|node|jQuery|object} mixed DataTable identifier. Can be one 6745 * of: 6746 * 6747 * * `string` - jQuery selector. Any DataTables' matching the given selector 6748 * with be found and used. 6749 * * `node` - `TABLE` node which has already been formed into a DataTable. 6750 * * `jQuery` - A jQuery object of `TABLE` nodes. 6751 * * `object` - DataTables settings object 6752 * * `DataTables.Api` - API instance 6753 * @return {array|null} Matching DataTables settings objects. `null` or 6754 * `undefined` is returned if no matching DataTable is found. 6755 * @ignore 6756 */ 6757 var _toSettings = function ( mixed ) 6758 { 6759 var idx, jq; 6760 var settings = DataTable.settings; 6761 var tables = $.map( settings, function (el, i) { 6762 return el.nTable; 6763 } ); 6764 6765 if ( ! mixed ) { 6766 return []; 6767 } 6768 else if ( mixed.nTable && mixed.oApi ) { 6769 // DataTables settings object 6770 return [ mixed ]; 6771 } 6772 else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) { 6773 // Table node 6774 idx = $.inArray( mixed, tables ); 6775 return idx !== -1 ? [ settings[idx] ] : null; 6776 } 6777 else if ( mixed && typeof mixed.settings === 'function' ) { 6778 return mixed.settings().toArray(); 6779 } 6780 else if ( typeof mixed === 'string' ) { 6781 // jQuery selector 6782 jq = $(mixed); 6783 } 6784 else if ( mixed instanceof $ ) { 6785 // jQuery object (also DataTables instance) 6786 jq = mixed; 6787 } 6788 6789 if ( jq ) { 6790 return jq.map( function(i) { 6791 idx = $.inArray( this, tables ); 6792 return idx !== -1 ? settings[idx] : null; 6793 } ).toArray(); 6794 } 6795 }; 6796 6797 6798 /** 6799 * DataTables API class - used to control and interface with one or more 6800 * DataTables enhanced tables. 6801 * 6802 * The API class is heavily based on jQuery, presenting a chainable interface 6803 * that you can use to interact with tables. Each instance of the API class has 6804 * a "context" - i.e. the tables that it will operate on. This could be a single 6805 * table, all tables on a page or a sub-set thereof. 6806 * 6807 * Additionally the API is designed to allow you to easily work with the data in 6808 * the tables, retrieving and manipulating it as required. This is done by 6809 * presenting the API class as an array like interface. The contents of the 6810 * array depend upon the actions requested by each method (for example 6811 * `rows().nodes()` will return an array of nodes, while `rows().data()` will 6812 * return an array of objects or arrays depending upon your table's 6813 * configuration). The API object has a number of array like methods (`push`, 6814 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`, 6815 * `unique` etc) to assist your working with the data held in a table. 6816 * 6817 * Most methods (those which return an Api instance) are chainable, which means 6818 * the return from a method call also has all of the methods available that the 6819 * top level object had. For example, these two calls are equivalent: 6820 * 6821 * // Not chained 6822 * api.row.add( {...} ); 6823 * api.draw(); 6824 * 6825 * // Chained 6826 * api.row.add( {...} ).draw(); 6827 * 6828 * @class DataTable.Api 6829 * @param {array|object|string|jQuery} context DataTable identifier. This is 6830 * used to define which DataTables enhanced tables this API will operate on. 6831 * Can be one of: 6832 * 6833 * * `string` - jQuery selector. Any DataTables' matching the given selector 6834 * with be found and used. 6835 * * `node` - `TABLE` node which has already been formed into a DataTable. 6836 * * `jQuery` - A jQuery object of `TABLE` nodes. 6837 * * `object` - DataTables settings object 6838 * @param {array} [data] Data to initialise the Api instance with. 6839 * 6840 * @example 6841 * // Direct initialisation during DataTables construction 6842 * var api = $('#example').DataTable(); 6843 * 6844 * @example 6845 * // Initialisation using a DataTables jQuery object 6846 * var api = $('#example').dataTable().api(); 6847 * 6848 * @example 6849 * // Initialisation as a constructor 6850 * var api = new $.fn.DataTable.Api( 'table.dataTable' ); 6851 */ 6852 _Api = function ( context, data ) 6853 { 6854 if ( ! (this instanceof _Api) ) { 6855 return new _Api( context, data ); 6856 } 6857 6858 var settings = []; 6859 var ctxSettings = function ( o ) { 6860 var a = _toSettings( o ); 6861 if ( a ) { 6862 settings = settings.concat( a ); 6863 } 6864 }; 6865 6866 if ( $.isArray( context ) ) { 6867 for ( var i=0, ien=context.length ; i<ien ; i++ ) { 6868 ctxSettings( context[i] ); 6869 } 6870 } 6871 else { 6872 ctxSettings( context ); 6873 } 6874 6875 // Remove duplicates 6876 this.context = _unique( settings ); 6877 6878 // Initial data 6879 if ( data ) { 6880 $.merge( this, data ); 6881 } 6882 6883 // selector 6884 this.selector = { 6885 rows: null, 6886 cols: null, 6887 opts: null 6888 }; 6889 6890 _Api.extend( this, this, __apiStruct ); 6891 }; 6892 6893 DataTable.Api = _Api; 6894 6895 // Don't destroy the existing prototype, just extend it. Required for jQuery 2's 6896 // isPlainObject. 6897 $.extend( _Api.prototype, { 6898 any: function () 6899 { 6900 return this.count() !== 0; 6901 }, 6902 6903 6904 concat: __arrayProto.concat, 6905 6906 6907 context: [], // array of table settings objects 6908 6909 6910 count: function () 6911 { 6912 return this.flatten().length; 6913 }, 6914 6915 6916 each: function ( fn ) 6917 { 6918 for ( var i=0, ien=this.length ; i<ien; i++ ) { 6919 fn.call( this, this[i], i, this ); 6920 } 6921 6922 return this; 6923 }, 6924 6925 6926 eq: function ( idx ) 6927 { 6928 var ctx = this.context; 6929 6930 return ctx.length > idx ? 6931 new _Api( ctx[idx], this[idx] ) : 6932 null; 6933 }, 6934 6935 6936 filter: function ( fn ) 6937 { 6938 var a = []; 6939 6940 if ( __arrayProto.filter ) { 6941 a = __arrayProto.filter.call( this, fn, this ); 6942 } 6943 else { 6944 // Compatibility for browsers without EMCA-252-5 (JS 1.6) 6945 for ( var i=0, ien=this.length ; i<ien ; i++ ) { 6946 if ( fn.call( this, this[i], i, this ) ) { 6947 a.push( this[i] ); 6948 } 6949 } 6950 } 6951 6952 return new _Api( this.context, a ); 6953 }, 6954 6955 6956 flatten: function () 6957 { 6958 var a = []; 6959 return new _Api( this.context, a.concat.apply( a, this.toArray() ) ); 6960 }, 6961 6962 6963 join: __arrayProto.join, 6964 6965 6966 indexOf: __arrayProto.indexOf || function (obj, start) 6967 { 6968 for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) { 6969 if ( this[i] === obj ) { 6970 return i; 6971 } 6972 } 6973 return -1; 6974 }, 6975 6976 iterator: function ( flatten, type, fn, alwaysNew ) { 6977 var 6978 a = [], ret, 6979 i, ien, j, jen, 6980 context = this.context, 6981 rows, items, item, 6982 selector = this.selector; 6983 6984 // Argument shifting 6985 if ( typeof flatten === 'string' ) { 6986 alwaysNew = fn; 6987 fn = type; 6988 type = flatten; 6989 flatten = false; 6990 } 6991 6992 for ( i=0, ien=context.length ; i<ien ; i++ ) { 6993 var apiInst = new _Api( context[i] ); 6994 6995 if ( type === 'table' ) { 6996 ret = fn.call( apiInst, context[i], i ); 6997 6998 if ( ret !== undefined ) { 6999 a.push( ret ); 7000 } 7001 } 7002 else if ( type === 'columns' || type === 'rows' ) { 7003 // this has same length as context - one entry for each table 7004 ret = fn.call( apiInst, context[i], this[i], i ); 7005 7006 if ( ret !== undefined ) { 7007 a.push( ret ); 7008 } 7009 } 7010 else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) { 7011 // columns and rows share the same structure. 7012 // 'this' is an array of column indexes for each context 7013 items = this[i]; 7014 7015 if ( type === 'column-rows' ) { 7016 rows = _selector_row_indexes( context[i], selector.opts ); 7017 } 7018 7019 for ( j=0, jen=items.length ; j<jen ; j++ ) { 7020 item = items[j]; 7021 7022 if ( type === 'cell' ) { 7023 ret = fn.call( apiInst, context[i], item.row, item.column, i, j ); 7024 } 7025 else { 7026 ret = fn.call( apiInst, context[i], item, i, j, rows ); 7027 } 7028 7029 if ( ret !== undefined ) { 7030 a.push( ret ); 7031 } 7032 } 7033 } 7034 } 7035 7036 if ( a.length || alwaysNew ) { 7037 var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a ); 7038 var apiSelector = api.selector; 7039 apiSelector.rows = selector.rows; 7040 apiSelector.cols = selector.cols; 7041 apiSelector.opts = selector.opts; 7042 return api; 7043 } 7044 return this; 7045 }, 7046 7047 7048 lastIndexOf: __arrayProto.lastIndexOf || function (obj, start) 7049 { 7050 // Bit cheeky... 7051 return this.indexOf.apply( this.toArray.reverse(), arguments ); 7052 }, 7053 7054 7055 length: 0, 7056 7057 7058 map: function ( fn ) 7059 { 7060 var a = []; 7061 7062 if ( __arrayProto.map ) { 7063 a = __arrayProto.map.call( this, fn, this ); 7064 } 7065 else { 7066 // Compatibility for browsers without EMCA-252-5 (JS 1.6) 7067 for ( var i=0, ien=this.length ; i<ien ; i++ ) { 7068 a.push( fn.call( this, this[i], i ) ); 7069 } 7070 } 7071 7072 return new _Api( this.context, a ); 7073 }, 7074 7075 7076 pluck: function ( prop ) 7077 { 7078 return this.map( function ( el ) { 7079 return el[ prop ]; 7080 } ); 7081 }, 7082 7083 pop: __arrayProto.pop, 7084 7085 7086 push: __arrayProto.push, 7087 7088 7089 // Does not return an API instance 7090 reduce: __arrayProto.reduce || function ( fn, init ) 7091 { 7092 return _fnReduce( this, fn, init, 0, this.length, 1 ); 7093 }, 7094 7095 7096 reduceRight: __arrayProto.reduceRight || function ( fn, init ) 7097 { 7098 return _fnReduce( this, fn, init, this.length-1, -1, -1 ); 7099 }, 7100 7101 7102 reverse: __arrayProto.reverse, 7103 7104 7105 // Object with rows, columns and opts 7106 selector: null, 7107 7108 7109 shift: __arrayProto.shift, 7110 7111 7112 sort: __arrayProto.sort, // ? name - order? 7113 7114 7115 splice: __arrayProto.splice, 7116 7117 7118 toArray: function () 7119 { 7120 return __arrayProto.slice.call( this ); 7121 }, 7122 7123 7124 to$: function () 7125 { 7126 return $( this ); 7127 }, 7128 7129 7130 toJQuery: function () 7131 { 7132 return $( this ); 7133 }, 7134 7135 7136 unique: function () 7137 { 7138 return new _Api( this.context, _unique(this) ); 7139 }, 7140 7141 7142 unshift: __arrayProto.unshift 7143 } ); 7144 7145 7146 _Api.extend = function ( scope, obj, ext ) 7147 { 7148 // Only extend API instances and static properties of the API 7149 if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) { 7150 return; 7151 } 7152 7153 var 7154 i, ien, 7155 j, jen, 7156 struct, inner, 7157 methodScoping = function ( scope, fn, struc ) { 7158 return function () { 7159 var ret = fn.apply( scope, arguments ); 7160 7161 // Method extension 7162 _Api.extend( ret, ret, struc.methodExt ); 7163 return ret; 7164 }; 7165 }; 7166 7167 for ( i=0, ien=ext.length ; i<ien ; i++ ) { 7168 struct = ext[i]; 7169 7170 // Value 7171 obj[ struct.name ] = typeof struct.val === 'function' ? 7172 methodScoping( scope, struct.val, struct ) : 7173 $.isPlainObject( struct.val ) ? 7174 {} : 7175 struct.val; 7176 7177 obj[ struct.name ].__dt_wrapper = true; 7178 7179 // Property extension 7180 _Api.extend( scope, obj[ struct.name ], struct.propExt ); 7181 } 7182 }; 7183 7184 7185 // @todo - Is there need for an augment function? 7186 // _Api.augment = function ( inst, name ) 7187 // { 7188 // // Find src object in the structure from the name 7189 // var parts = name.split('.'); 7190 7191 // _Api.extend( inst, obj ); 7192 // }; 7193 7194 7195 // [ 7196 // { 7197 // name: 'data' -- string - Property name 7198 // val: function () {}, -- function - Api method (or undefined if just an object 7199 // methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result 7200 // propExt: [ ... ] -- array - Array of Api object definitions to extend the property 7201 // }, 7202 // { 7203 // name: 'row' 7204 // val: {}, 7205 // methodExt: [ ... ], 7206 // propExt: [ 7207 // { 7208 // name: 'data' 7209 // val: function () {}, 7210 // methodExt: [ ... ], 7211 // propExt: [ ... ] 7212 // }, 7213 // ... 7214 // ] 7215 // } 7216 // ] 7217 7218 _Api.register = _api_register = function ( name, val ) 7219 { 7220 if ( $.isArray( name ) ) { 7221 for ( var j=0, jen=name.length ; j<jen ; j++ ) { 7222 _Api.register( name[j], val ); 7223 } 7224 return; 7225 } 7226 7227 var 7228 i, ien, 7229 heir = name.split('.'), 7230 struct = __apiStruct, 7231 key, method; 7232 7233 var find = function ( src, name ) { 7234 for ( var i=0, ien=src.length ; i<ien ; i++ ) { 7235 if ( src[i].name === name ) { 7236 return src[i]; 7237 } 7238 } 7239 return null; 7240 }; 7241 7242 for ( i=0, ien=heir.length ; i<ien ; i++ ) { 7243 method = heir[i].indexOf('()') !== -1; 7244 key = method ? 7245 heir[i].replace('()', '') : 7246 heir[i]; 7247 7248 var src = find( struct, key ); 7249 if ( ! src ) { 7250 src = { 7251 name: key, 7252 val: {}, 7253 methodExt: [], 7254 propExt: [] 7255 }; 7256 struct.push( src ); 7257 } 7258 7259 if ( i === ien-1 ) { 7260 src.val = val; 7261 } 7262 else { 7263 struct = method ? 7264 src.methodExt : 7265 src.propExt; 7266 } 7267 } 7268 }; 7269 7270 7271 _Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) { 7272 _Api.register( pluralName, val ); 7273 7274 _Api.register( singularName, function () { 7275 var ret = val.apply( this, arguments ); 7276 7277 if ( ret === this ) { 7278 // Returned item is the API instance that was passed in, return it 7279 return this; 7280 } 7281 else if ( ret instanceof _Api ) { 7282 // New API instance returned, want the value from the first item 7283 // in the returned array for the singular result. 7284 return ret.length ? 7285 $.isArray( ret[0] ) ? 7286 new _Api( ret.context, ret[0] ) : // Array results are 'enhanced' 7287 ret[0] : 7288 undefined; 7289 } 7290 7291 // Non-API return - just fire it back 7292 return ret; 7293 } ); 7294 }; 7295 7296 7297 /** 7298 * Selector for HTML tables. Apply the given selector to the give array of 7299 * DataTables settings objects. 7300 * 7301 * @param {string|integer} [selector] jQuery selector string or integer 7302 * @param {array} Array of DataTables settings objects to be filtered 7303 * @return {array} 7304 * @ignore 7305 */ 7306 var __table_selector = function ( selector, a ) 7307 { 7308 // Integer is used to pick out a table by index 7309 if ( typeof selector === 'number' ) { 7310 return [ a[ selector ] ]; 7311 } 7312 7313 // Perform a jQuery selector on the table nodes 7314 var nodes = $.map( a, function (el, i) { 7315 return el.nTable; 7316 } ); 7317 7318 return $(nodes) 7319 .filter( selector ) 7320 .map( function (i) { 7321 // Need to translate back from the table node to the settings 7322 var idx = $.inArray( this, nodes ); 7323 return a[ idx ]; 7324 } ) 7325 .toArray(); 7326 }; 7327 7328 7329 7330 /** 7331 * Context selector for the API's context (i.e. the tables the API instance 7332 * refers to. 7333 * 7334 * @name DataTable.Api#tables 7335 * @param {string|integer} [selector] Selector to pick which tables the iterator 7336 * should operate on. If not given, all tables in the current context are 7337 * used. This can be given as a jQuery selector (for example `':gt(0)'`) to 7338 * select multiple tables or as an integer to select a single table. 7339 * @returns {DataTable.Api} Returns a new API instance if a selector is given. 7340 */ 7341 _api_register( 'tables()', function ( selector ) { 7342 // A new instance is created if there was a selector specified 7343 return selector
vendor: 9,632 bytes, lines 7343-7691
7343 ? 7344 new _Api( __table_selector( selector, this.context ) ) : 7345 this; 7346 } ); 7347 7348 7349 _api_register( 'table()', function ( selector ) { 7350 var tables = this.tables( selector ); 7351 var ctx = tables.context; 7352 7353 // Truncate to the first matched table 7354 return ctx.length ? 7355 new _Api( ctx[0] ) : 7356 tables; 7357 } ); 7358 7359 7360 _api_registerPlural( 'tables().nodes()', 'table().node()' , function () { 7361 return this.iterator( 'table', function ( ctx ) { 7362 return ctx.nTable; 7363 }, 1 ); 7364 } ); 7365 7366 7367 _api_registerPlural( 'tables().body()', 'table().body()' , function () { 7368 return this.iterator( 'table', function ( ctx ) { 7369 return ctx.nTBody; 7370 }, 1 ); 7371 } ); 7372 7373 7374 _api_registerPlural( 'tables().header()', 'table().header()' , function () { 7375 return this.iterator( 'table', function ( ctx ) { 7376 return ctx.nTHead; 7377 }, 1 ); 7378 } ); 7379 7380 7381 _api_registerPlural( 'tables().footer()', 'table().footer()' , function () { 7382 return this.iterator( 'table', function ( ctx ) { 7383 return ctx.nTFoot; 7384 }, 1 ); 7385 } ); 7386 7387 7388 _api_registerPlural( 'tables().containers()', 'table().container()' , function () { 7389 return this.iterator( 'table', function ( ctx ) { 7390 return ctx.nTableWrapper; 7391 }, 1 ); 7392 } ); 7393 7394 7395 7396 /** 7397 * Redraw the tables in the current context. 7398 */ 7399 _api_register( 'draw()', function ( paging ) { 7400 return this.iterator( 'table', function ( settings ) { 7401 if ( paging === 'page' ) { 7402 _fnDraw( settings ); 7403 } 7404 else { 7405 if ( typeof paging === 'string' ) { 7406 paging = paging === 'full-hold' ? 7407 false : 7408 true; 7409 } 7410 7411 _fnReDraw( settings, paging===false ); 7412 } 7413 } ); 7414 } ); 7415 7416 7417 7418 /** 7419 * Get the current page index. 7420 * 7421 * @return {integer} Current page index (zero based) 7422 *//** 7423 * Set the current page. 7424 * 7425 * Note that if you attempt to show a page which does not exist, DataTables will 7426 * not throw an error, but rather reset the paging. 7427 * 7428 * @param {integer|string} action The paging action to take. This can be one of: 7429 * * `integer` - The page index to jump to 7430 * * `string` - An action to take: 7431 * * `first` - Jump to first page. 7432 * * `next` - Jump to the next page 7433 * * `previous` - Jump to previous page 7434 * * `last` - Jump to the last page. 7435 * @returns {DataTables.Api} this 7436 */ 7437 _api_register( 'page()', function ( action ) { 7438 if ( action === undefined ) { 7439 return this.page.info().page; // not an expensive call 7440 } 7441 7442 // else, have an action to take on all tables 7443 return this.iterator( 'table', function ( settings ) { 7444 _fnPageChange( settings, action ); 7445 } ); 7446 } ); 7447 7448 7449 /** 7450 * Paging information for the first table in the current context. 7451 * 7452 * If you require paging information for another table, use the `table()` method 7453 * with a suitable selector. 7454 * 7455 * @return {object} Object with the following properties set: 7456 * * `page` - Current page index (zero based - i.e. the first page is `0`) 7457 * * `pages` - Total number of pages 7458 * * `start` - Display index for the first record shown on the current page 7459 * * `end` - Display index for the last record shown on the current page 7460 * * `length` - Display length (number of records). Note that generally `start 7461 * + length = end`, but this is not always true, for example if there are 7462 * only 2 records to show on the final page, with a length of 10. 7463 * * `recordsTotal` - Full data set length 7464 * * `recordsDisplay` - Data set length once the current filtering criterion 7465 * are applied. 7466 */ 7467 _api_register( 'page.info()', function ( action ) { 7468 if ( this.context.length === 0 ) { 7469 return undefined; 7470 } 7471 7472 var 7473 settings = this.context[0], 7474 start = settings._iDisplayStart, 7475 len = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1, 7476 visRecords = settings.fnRecordsDisplay(), 7477 all = len === -1; 7478 7479 return { 7480 "page": all ? 0 : Math.floor( start / len ), 7481 "pages": all ? 1 : Math.ceil( visRecords / len ), 7482 "start": start, 7483 "end": settings.fnDisplayEnd(), 7484 "length": len, 7485 "recordsTotal": settings.fnRecordsTotal(), 7486 "recordsDisplay": visRecords, 7487 "serverSide": _fnDataSource( settings ) === 'ssp' 7488 }; 7489 } ); 7490 7491 7492 /** 7493 * Get the current page length. 7494 * 7495 * @return {integer} Current page length. Note `-1` indicates that all records 7496 * are to be shown. 7497 *//** 7498 * Set the current page length. 7499 * 7500 * @param {integer} Page length to set. Use `-1` to show all records. 7501 * @returns {DataTables.Api} this 7502 */ 7503 _api_register( 'page.len()', function ( len ) { 7504 // Note that we can't call this function 'length()' because `length` 7505 // is a Javascript property of functions which defines how many arguments 7506 // the function expects. 7507 if ( len === undefined ) { 7508 return this.context.length !== 0 ? 7509 this.context[0]._iDisplayLength : 7510 undefined; 7511 } 7512 7513 // else, set the page length 7514 return this.iterator( 'table', function ( settings ) { 7515 _fnLengthChange( settings, len ); 7516 } ); 7517 } ); 7518 7519 7520 7521 var __reload = function ( settings, holdPosition, callback ) { 7522 // Use the draw event to trigger a callback 7523 if ( callback ) { 7524 var api = new _Api( settings ); 7525 7526 api.one( 'draw', function () { 7527 callback( api.ajax.json() ); 7528 } ); 7529 } 7530 7531 if ( _fnDataSource( settings ) == 'ssp' ) { 7532 _fnReDraw( settings, holdPosition ); 7533 } 7534 else { 7535 _fnProcessingDisplay( settings, true ); 7536 7537 // Cancel an existing request 7538 var xhr = settings.jqXHR; 7539 if ( xhr && xhr.readyState !== 4 ) { 7540 xhr.abort(); 7541 } 7542 7543 // Trigger xhr 7544 _fnBuildAjax( settings, [], function( json ) { 7545 _fnClearTable( settings ); 7546 7547 var data = _fnAjaxDataSrc( settings, json ); 7548 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 7549 _fnAddData( settings, data[i] ); 7550 } 7551 7552 _fnReDraw( settings, holdPosition ); 7553 _fnProcessingDisplay( settings, false ); 7554 } ); 7555 } 7556 }; 7557 7558 7559 /** 7560 * Get the JSON response from the last Ajax request that DataTables made to the 7561 * server. Note that this returns the JSON from the first table in the current 7562 * context. 7563 * 7564 * @return {object} JSON received from the server. 7565 */ 7566 _api_register( 'ajax.json()', function () { 7567 var ctx = this.context; 7568 7569 if ( ctx.length > 0 ) { 7570 return ctx[0].json; 7571 } 7572 7573 // else return undefined; 7574 } ); 7575 7576 7577 /** 7578 * Get the data submitted in the last Ajax request 7579 */ 7580 _api_register( 'ajax.params()', function () { 7581 var ctx = this.context; 7582 7583 if ( ctx.length > 0 ) { 7584 return ctx[0].oAjaxData; 7585 } 7586 7587 // else return undefined; 7588 } ); 7589 7590 7591 /** 7592 * Reload tables from the Ajax data source. Note that this function will 7593 * automatically re-draw the table when the remote data has been loaded. 7594 * 7595 * @param {boolean} [reset=true] Reset (default) or hold the current paging 7596 * position. A full re-sort and re-filter is performed when this method is 7597 * called, which is why the pagination reset is the default action. 7598 * @returns {DataTables.Api} this 7599 */ 7600 _api_register( 'ajax.reload()', function ( callback, resetPaging ) { 7601 return this.iterator( 'table', function (settings) { 7602 __reload( settings, resetPaging===false, callback ); 7603 } ); 7604 } ); 7605 7606 7607 /** 7608 * Get the current Ajax URL. Note that this returns the URL from the first 7609 * table in the current context. 7610 * 7611 * @return {string} Current Ajax source URL 7612 *//** 7613 * Set the Ajax URL. Note that this will set the URL for all tables in the 7614 * current context. 7615 * 7616 * @param {string} url URL to set. 7617 * @returns {DataTables.Api} this 7618 */ 7619 _api_register( 'ajax.url()', function ( url ) { 7620 var ctx = this.context; 7621 7622 if ( url === undefined ) { 7623 // get 7624 if ( ctx.length === 0 ) { 7625 return undefined; 7626 } 7627 ctx = ctx[0]; 7628 7629 return ctx.ajax ? 7630 $.isPlainObject( ctx.ajax ) ? 7631 ctx.ajax.url : 7632 ctx.ajax : 7633 ctx.sAjaxSource; 7634 } 7635 7636 // set 7637 return this.iterator( 'table', function ( settings ) { 7638 if ( $.isPlainObject( settings.ajax ) ) { 7639 settings.ajax.url = url; 7640 } 7641 else { 7642 settings.ajax = url; 7643 } 7644 // No need to consider sAjaxSource here since DataTables gives priority 7645 // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any 7646 // value of `sAjaxSource` redundant. 7647 } ); 7648 } ); 7649 7650 7651 /** 7652 * Load data from the newly set Ajax URL. Note that this method is only 7653 * available when `ajax.url()` is used to set a URL. Additionally, this method 7654 * has the same effect as calling `ajax.reload()` but is provided for 7655 * convenience when setting a new URL. Like `ajax.reload()` it will 7656 * automatically redraw the table once the remote data has been loaded. 7657 * 7658 * @returns {DataTables.Api} this 7659 */ 7660 _api_register( 'ajax.url().load()', function ( callback, resetPaging ) { 7661 // Same as a reload, but makes sense to present it for easy access after a 7662 // url change 7663 return this.iterator( 'table', function ( ctx ) { 7664 __reload( ctx, resetPaging===false, callback ); 7665 } ); 7666 } ); 7667 7668 7669 7670 7671 var _selector_run = function ( type, selector, selectFn, settings, opts ) 7672 { 7673 var 7674 out = [], res, 7675 a, i, ien, j, jen, 7676 selectorType = typeof selector; 7677 7678 // Can't just check for isArray here, as an API or jQuery instance might be 7679 // given with their array like look 7680 if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) { 7681 selector = [ selector ]; 7682 } 7683 7684 for ( i=0, ien=selector.length ; i<ien ; i++ ) { 7685 // Only split on simple strings - complex expressions will be jQuery selectors 7686 a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ? 7687 selector[i].split(',') : 7688 [ selector[i] ]; 7689 7690 for ( j=0, jen=a.length ; j<jen ; j++ ) { 7691 res = selectFn( typeof a[j] === 'string' ?
vendor: 44,990 bytes, lines 7691-9391
7691$.trim(a[j]) : a[j] ); 7692 7693 if ( res && res.length ) { 7694 out = out.concat( res ); 7695 } 7696 } 7697 } 7698 7699 // selector extensions 7700 var ext = _ext.selector[ type ]; 7701 if ( ext.length ) { 7702 for ( i=0, ien=ext.length ; i<ien ; i++ ) { 7703 out = ext[i]( settings, opts, out ); 7704 } 7705 } 7706 7707 return _unique( out ); 7708 }; 7709 7710 7711 var _selector_opts = function ( opts ) 7712 { 7713 if ( ! opts ) { 7714 opts = {}; 7715 } 7716 7717 // Backwards compatibility for 1.9- which used the terminology filter rather 7718 // than search 7719 if ( opts.filter && opts.search === undefined ) { 7720 opts.search = opts.filter; 7721 } 7722 7723 return $.extend( { 7724 search: 'none', 7725 order: 'current', 7726 page: 'all' 7727 }, opts ); 7728 }; 7729 7730 7731 var _selector_first = function ( inst ) 7732 { 7733 // Reduce the API instance to the first item found 7734 for ( var i=0, ien=inst.length ; i<ien ; i++ ) { 7735 if ( inst[i].length > 0 ) { 7736 // Assign the first element to the first item in the instance 7737 // and truncate the instance and context 7738 inst[0] = inst[i]; 7739 inst[0].length = 1; 7740 inst.length = 1; 7741 inst.context = [ inst.context[i] ]; 7742 7743 return inst; 7744 } 7745 } 7746 7747 // Not found - return an empty instance 7748 inst.length = 0; 7749 return inst; 7750 }; 7751 7752 7753 var _selector_row_indexes = function ( settings, opts ) 7754 { 7755 var 7756 i, ien, tmp, a=[], 7757 displayFiltered = settings.aiDisplay, 7758 displayMaster = settings.aiDisplayMaster; 7759 7760 var 7761 search = opts.search, // none, applied, removed 7762 order = opts.order, // applied, current, index (original - compatibility with 1.9) 7763 page = opts.page; // all, current 7764 7765 if ( _fnDataSource( settings ) == 'ssp' ) { 7766 // In server-side processing mode, most options are irrelevant since 7767 // rows not shown don't exist and the index order is the applied order 7768 // Removed is a special case - for consistency just return an empty 7769 // array 7770 return search === 'removed' ? 7771 [] : 7772 _range( 0, displayMaster.length ); 7773 } 7774 else if ( page == 'current' ) { 7775 // Current page implies that order=current and fitler=applied, since it is 7776 // fairly senseless otherwise, regardless of what order and search actually 7777 // are 7778 for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) { 7779 a.push( displayFiltered[i] ); 7780 } 7781 } 7782 else if ( order == 'current' || order == 'applied' ) { 7783 a = search == 'none' ? 7784 displayMaster.slice() : // no search 7785 search == 'applied' ? 7786 displayFiltered.slice() : // applied search 7787 $.map( displayMaster, function (el, i) { // removed search 7788 return $.inArray( el, displayFiltered ) === -1 ? el : null; 7789 } ); 7790 } 7791 else if ( order == 'index' || order == 'original' ) { 7792 for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 7793 if ( search == 'none' ) { 7794 a.push( i ); 7795 } 7796 else { // applied | removed 7797 tmp = $.inArray( i, displayFiltered ); 7798 7799 if ((tmp === -1 && search == 'removed') || 7800 (tmp >= 0 && search == 'applied') ) 7801 { 7802 a.push( i ); 7803 } 7804 } 7805 } 7806 } 7807 7808 return a; 7809 }; 7810 7811 7812 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 7813 * Rows 7814 * 7815 * {} - no selector - use all available rows 7816 * {integer} - row aoData index 7817 * {node} - TR node 7818 * {string} - jQuery selector to apply to the TR elements 7819 * {array} - jQuery array of nodes, or simply an array of TR nodes 7820 * 7821 */ 7822 7823 7824 var __row_selector = function ( settings, selector, opts ) 7825 { 7826 var rows; 7827 var run = function ( sel ) { 7828 var selInt = _intVal( sel ); 7829 var i, ien; 7830 7831 // Short cut - selector is a number and no options provided (default is 7832 // all records, so no need to check if the index is in there, since it 7833 // must be - dev error if the index doesn't exist). 7834 if ( selInt !== null && ! opts ) { 7835 return [ selInt ]; 7836 } 7837 7838 if ( ! rows ) { 7839 rows = _selector_row_indexes( settings, opts ); 7840 } 7841 7842 if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) { 7843 // Selector - integer 7844 return [ selInt ]; 7845 } 7846 else if ( sel === null || sel === undefined || sel === '' ) { 7847 // Selector - none 7848 return rows; 7849 } 7850 7851 // Selector - function 7852 if ( typeof sel === 'function' ) { 7853 return $.map( rows, function (idx) { 7854 var row = settings.aoData[ idx ]; 7855 return sel( idx, row._aData, row.nTr ) ? idx : null; 7856 } ); 7857 } 7858 7859 // Get nodes in the order from the `rows` array with null values removed 7860 var nodes = _removeEmpty( 7861 _pluck_order( settings.aoData, rows, 'nTr' ) 7862 ); 7863 7864 // Selector - node 7865 if ( sel.nodeName ) { 7866 if ( sel._DT_RowIndex !== undefined ) { 7867 return [ sel._DT_RowIndex ]; // Property added by DT for fast lookup 7868 } 7869 else if ( sel._DT_CellIndex ) { 7870 return [ sel._DT_CellIndex.row ]; 7871 } 7872 else { 7873 var host = $(sel).closest('*[data-dt-row]'); 7874 return host.length ? 7875 [ host.data('dt-row') ] : 7876 []; 7877 } 7878 } 7879 7880 // ID selector. Want to always be able to select rows by id, regardless 7881 // of if the tr element has been created or not, so can't rely upon 7882 // jQuery here - hence a custom implementation. This does not match 7883 // Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything, 7884 // but to select it using a CSS selector engine (like Sizzle or 7885 // querySelect) it would need to need to be escaped for some characters. 7886 // DataTables simplifies this for row selectors since you can select 7887 // only a row. A # indicates an id any anything that follows is the id - 7888 // unescaped. 7889 if ( typeof sel === 'string' && sel.charAt(0) === '#' ) { 7890 // get row index from id 7891 var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ]; 7892 if ( rowObj !== undefined ) { 7893 return [ rowObj.idx ]; 7894 } 7895 7896 // need to fall through to jQuery in case there is DOM id that 7897 // matches 7898 } 7899 7900 // Selector - jQuery selector string, array of nodes or jQuery object/ 7901 // As jQuery's .filter() allows jQuery objects to be passed in filter, 7902 // it also allows arrays, so this will cope with all three options 7903 return $(nodes) 7904 .filter( sel ) 7905 .map( function () { 7906 return this._DT_RowIndex; 7907 } ) 7908 .toArray(); 7909 }; 7910 7911 return _selector_run( 'row', selector, run, settings, opts ); 7912 }; 7913 7914 7915 _api_register( 'rows()', function ( selector, opts ) { 7916 // argument shifting 7917 if ( selector === undefined ) { 7918 selector = ''; 7919 } 7920 else if ( $.isPlainObject( selector ) ) { 7921 opts = selector; 7922 selector = ''; 7923 } 7924 7925 opts = _selector_opts( opts ); 7926 7927 var inst = this.iterator( 'table', function ( settings ) { 7928 return __row_selector( settings, selector, opts ); 7929 }, 1 ); 7930 7931 // Want argument shifting here and in __row_selector? 7932 inst.selector.rows = selector; 7933 inst.selector.opts = opts; 7934 7935 return inst; 7936 } ); 7937 7938 _api_register( 'rows().nodes()', function () { 7939 return this.iterator( 'row', function ( settings, row ) { 7940 return settings.aoData[ row ].nTr || undefined; 7941 }, 1 ); 7942 } ); 7943 7944 _api_register( 'rows().data()', function () { 7945 return this.iterator( true, 'rows', function ( settings, rows ) { 7946 return _pluck_order( settings.aoData, rows, '_aData' ); 7947 }, 1 ); 7948 } ); 7949 7950 _api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) { 7951 return this.iterator( 'row', function ( settings, row ) { 7952 var r = settings.aoData[ row ]; 7953 return type === 'search' ? r._aFilterData : r._aSortData; 7954 }, 1 ); 7955 } ); 7956 7957 _api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) { 7958 return this.iterator( 'row', function ( settings, row ) { 7959 _fnInvalidate( settings, row, src ); 7960 } ); 7961 } ); 7962 7963 _api_registerPlural( 'rows().indexes()', 'row().index()', function () { 7964 return this.iterator( 'row', function ( settings, row ) { 7965 return row; 7966 }, 1 ); 7967 } ); 7968 7969 _api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) { 7970 var a = []; 7971 var context = this.context; 7972 7973 // `iterator` will drop undefined values, but in this case we want them 7974 for ( var i=0, ien=context.length ; i<ien ; i++ ) { 7975 for ( var j=0, jen=this[i].length ; j<jen ; j++ ) { 7976 var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData ); 7977 a.push( (hash === true ? '#' : '' )+ id ); 7978 } 7979 } 7980 7981 return new _Api( context, a ); 7982 } ); 7983 7984 _api_registerPlural( 'rows().remove()', 'row().remove()', function () { 7985 var that = this; 7986 7987 this.iterator( 'row', function ( settings, row, thatIdx ) { 7988 var data = settings.aoData; 7989 var rowData = data[ row ]; 7990 var i, ien, j, jen; 7991 var loopRow, loopCells; 7992 7993 data.splice( row, 1 ); 7994 7995 // Update the cached indexes 7996 for ( i=0, ien=data.length ; i<ien ; i++ ) { 7997 loopRow = data[i]; 7998 loopCells = loopRow.anCells; 7999 8000 // Rows 8001 if ( loopRow.nTr !== null ) { 8002 loopRow.nTr._DT_RowIndex = i; 8003 } 8004 8005 // Cells 8006 if ( loopCells !== null ) { 8007 for ( j=0, jen=loopCells.length ; j<jen ; j++ ) { 8008 loopCells[j]._DT_CellIndex.row = i; 8009 } 8010 } 8011 } 8012 8013 // Delete from the display arrays 8014 _fnDeleteIndex( settings.aiDisplayMaster, row ); 8015 _fnDeleteIndex( settings.aiDisplay, row ); 8016 _fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes 8017 8018 // Check for an 'overflow' they case for displaying the table 8019 _fnLengthOverflow( settings ); 8020 8021 // Remove the row's ID reference if there is one 8022 var id = settings.rowIdFn( rowData._aData ); 8023 if ( id !== undefined ) { 8024 delete settings.aIds[ id ]; 8025 } 8026 } ); 8027 8028 this.iterator( 'table', function ( settings ) { 8029 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 8030 settings.aoData[i].idx = i; 8031 } 8032 } ); 8033 8034 return this; 8035 } ); 8036 8037 8038 _api_register( 'rows.add()', function ( rows ) { 8039 var newRows = this.iterator( 'table', function ( settings ) { 8040 var row, i, ien; 8041 var out = []; 8042 8043 for ( i=0, ien=rows.length ; i<ien ; i++ ) { 8044 row = rows[i]; 8045 8046 if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) { 8047 out.push( _fnAddTr( settings, row )[0] ); 8048 } 8049 else { 8050 out.push( _fnAddData( settings, row ) ); 8051 } 8052 } 8053 8054 return out; 8055 }, 1 ); 8056 8057 // Return an Api.rows() extended instance, so rows().nodes() etc can be used 8058 var modRows = this.rows( -1 ); 8059 modRows.pop(); 8060 $.merge( modRows, newRows ); 8061 8062 return modRows; 8063 } ); 8064 8065 8066 8067 8068 8069 /** 8070 * 8071 */ 8072 _api_register( 'row()', function ( selector, opts ) { 8073 return _selector_first( this.rows( selector, opts ) ); 8074 } ); 8075 8076 8077 _api_register( 'row().data()', function ( data ) { 8078 var ctx = this.context; 8079 8080 if ( data === undefined ) { 8081 // Get 8082 return ctx.length && this.length ? 8083 ctx[0].aoData[ this[0] ]._aData : 8084 undefined; 8085 } 8086 8087 // Set 8088 ctx[0].aoData[ this[0] ]._aData = data; 8089 8090 // Automatically invalidate 8091 _fnInvalidate( ctx[0], this[0], 'data' ); 8092 8093 return this; 8094 } ); 8095 8096 8097 _api_register( 'row().node()', function () { 8098 var ctx = this.context; 8099 8100 return ctx.length && this.length ? 8101 ctx[0].aoData[ this[0] ].nTr || null : 8102 null; 8103 } ); 8104 8105 8106 _api_register( 'row.add()', function ( row ) { 8107 // Allow a jQuery object to be passed in - only a single row is added from 8108 // it though - the first element in the set 8109 if ( row instanceof $ && row.length ) { 8110 row = row[0]; 8111 } 8112 8113 var rows = this.iterator( 'table', function ( settings ) { 8114 if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) { 8115 return _fnAddTr( settings, row )[0]; 8116 } 8117 return _fnAddData( settings, row ); 8118 } ); 8119 8120 // Return an Api.rows() extended instance, with the newly added row selected 8121 return this.row( rows[0] ); 8122 } ); 8123 8124 8125 8126 var __details_add = function ( ctx, row, data, klass ) 8127 { 8128 // Convert to array of TR elements 8129 var rows = []; 8130 var addRow = function ( r, k ) { 8131 // Recursion to allow for arrays of jQuery objects 8132 if ( $.isArray( r ) || r instanceof $ ) { 8133 for ( var i=0, ien=r.length ; i<ien ; i++ ) { 8134 addRow( r[i], k ); 8135 } 8136 return; 8137 } 8138 8139 // If we get a TR element, then just add it directly - up to the dev 8140 // to add the correct number of columns etc 8141 if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) { 8142 rows.push( r ); 8143 } 8144 else { 8145 // Otherwise create a row with a wrapper 8146 var created = $('<tr><td/></tr>').addClass( k ); 8147 $('td', created) 8148 .addClass( k ) 8149 .html( r ) 8150 [0].colSpan = _fnVisbleColumns( ctx ); 8151 8152 rows.push( created[0] ); 8153 } 8154 }; 8155 8156 addRow( data, klass ); 8157 8158 if ( row._details ) { 8159 row._details.detach(); 8160 } 8161 8162 row._details = $(rows); 8163 8164 // If the children were already shown, that state should be retained 8165 if ( row._detailsShow ) { 8166 row._details.insertAfter( row.nTr ); 8167 } 8168 }; 8169 8170 8171 var __details_remove = function ( api, idx ) 8172 { 8173 var ctx = api.context; 8174 8175 if ( ctx.length ) { 8176 var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ]; 8177 8178 if ( row && row._details ) { 8179 row._details.remove(); 8180 8181 row._detailsShow = undefined; 8182 row._details = undefined; 8183 } 8184 } 8185 }; 8186 8187 8188 var __details_display = function ( api, show ) { 8189 var ctx = api.context; 8190 8191 if ( ctx.length && api.length ) { 8192 var row = ctx[0].aoData[ api[0] ]; 8193 8194 if ( row._details ) { 8195 row._detailsShow = show; 8196 8197 if ( show ) { 8198 row._details.insertAfter( row.nTr ); 8199 } 8200 else { 8201 row._details.detach(); 8202 } 8203 8204 __details_events( ctx[0] ); 8205 } 8206 } 8207 }; 8208 8209 8210 var __details_events = function ( settings ) 8211 { 8212 var api = new _Api( settings ); 8213 var namespace = '.dt.DT_details'; 8214 var drawEvent = 'draw'+namespace; 8215 var colvisEvent = 'column-visibility'+namespace; 8216 var destroyEvent = 'destroy'+namespace; 8217 var data = settings.aoData; 8218 8219 api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent ); 8220 8221 if ( _pluck( data, '_details' ).length > 0 ) { 8222 // On each draw, insert the required elements into the document 8223 api.on( drawEvent, function ( e, ctx ) { 8224 if ( settings !== ctx ) { 8225 return; 8226 } 8227 8228 api.rows( {page:'current'} ).eq(0).each( function (idx) { 8229 // Internal data grab 8230 var row = data[ idx ]; 8231 8232 if ( row._detailsShow ) { 8233 row._details.insertAfter( row.nTr ); 8234 } 8235 } ); 8236 } ); 8237 8238 // Column visibility change - update the colspan 8239 api.on( colvisEvent, function ( e, ctx, idx, vis ) { 8240 if ( settings !== ctx ) { 8241 return; 8242 } 8243 8244 // Update the colspan for the details rows (note, only if it already has 8245 // a colspan) 8246 var row, visible = _fnVisbleColumns( ctx ); 8247 8248 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 8249 row = data[i]; 8250 8251 if ( row._details ) { 8252 row._details.children('td[colspan]').attr('colspan', visible ); 8253 } 8254 } 8255 } ); 8256 8257 // Table destroyed - nuke any child rows 8258 api.on( destroyEvent, function ( e, ctx ) { 8259 if ( settings !== ctx ) { 8260 return; 8261 } 8262 8263 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 8264 if ( data[i]._details ) { 8265 __details_remove( api, i ); 8266 } 8267 } 8268 } ); 8269 } 8270 }; 8271 8272 // Strings for the method names to help minification 8273 var _emp = ''; 8274 var _child_obj = _emp+'row().child'; 8275 var _child_mth = _child_obj+'()'; 8276 8277 // data can be: 8278 // tr 8279 // string 8280 // jQuery or array of any of the above 8281 _api_register( _child_mth, function ( data, klass ) { 8282 var ctx = this.context; 8283 8284 if ( data === undefined ) { 8285 // get 8286 return ctx.length && this.length ? 8287 ctx[0].aoData[ this[0] ]._details : 8288 undefined; 8289 } 8290 else if ( data === true ) { 8291 // show 8292 this.child.show(); 8293 } 8294 else if ( data === false ) { 8295 // remove 8296 __details_remove( this ); 8297 } 8298 else if ( ctx.length && this.length ) { 8299 // set 8300 __details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass ); 8301 } 8302 8303 return this; 8304 } ); 8305 8306 8307 _api_register( [ 8308 _child_obj+'.show()', 8309 _child_mth+'.show()' // only when `child()` was called with parameters (without 8310 ], function ( show ) { // it returns an object and this method is not executed) 8311 __details_display( this, true ); 8312 return this; 8313 } ); 8314 8315 8316 _api_register( [ 8317 _child_obj+'.hide()', 8318 _child_mth+'.hide()' // only when `child()` was called with parameters (without 8319 ], function () { // it returns an object and this method is not executed) 8320 __details_display( this, false ); 8321 return this; 8322 } ); 8323 8324 8325 _api_register( [ 8326 _child_obj+'.remove()', 8327 _child_mth+'.remove()' // only when `child()` was called with parameters (without 8328 ], function () { // it returns an object and this method is not executed) 8329 __details_remove( this ); 8330 return this; 8331 } ); 8332 8333 8334 _api_register( _child_obj+'.isShown()', function () { 8335 var ctx = this.context; 8336 8337 if ( ctx.length && this.length ) { 8338 // _detailsShown as false or undefined will fall through to return false 8339 return ctx[0].aoData[ this[0] ]._detailsShow || false; 8340 } 8341 return false; 8342 } ); 8343 8344 8345 8346 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 8347 * Columns 8348 * 8349 * {integer} - column index (>=0 count from left, <0 count from right) 8350 * "{integer}:visIdx" - visible column index (i.e. translate to column index) (>=0 count from left, <0 count from right) 8351 * "{integer}:visible" - alias for {integer}:visIdx (>=0 count from left, <0 count from right) 8352 * "{string}:name" - column name 8353 * "{string}" - jQuery selector on column header nodes 8354 * 8355 */ 8356 8357 // can be an array of these items, comma separated list, or an array of comma 8358 // separated lists 8359 8360 var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/; 8361 8362 8363 // r1 and r2 are redundant - but it means that the parameters match for the 8364 // iterator callback in columns().data() 8365 var __columnData = function ( settings, column, r1, r2, rows ) { 8366 var a = []; 8367 for ( var row=0, ien=rows.length ; row<ien ; row++ ) { 8368 a.push( _fnGetCellData( settings, rows[row], column ) ); 8369 } 8370 return a; 8371 }; 8372 8373 8374 var __column_selector = function ( settings, selector, opts ) 8375 { 8376 var 8377 columns = settings.aoColumns, 8378 names = _pluck( columns, 'sName' ), 8379 nodes = _pluck( columns, 'nTh' ); 8380 8381 var run = function ( s ) { 8382 var selInt = _intVal( s ); 8383 8384 // Selector - all 8385 if ( s === '' ) { 8386 return _range( columns.length ); 8387 } 8388 8389 // Selector - index 8390 if ( selInt !== null ) { 8391 return [ selInt >= 0 ? 8392 selInt : // Count from left 8393 columns.length + selInt // Count from right (+ because its a negative value) 8394 ]; 8395 } 8396 8397 // Selector = function 8398 if ( typeof s === 'function' ) { 8399 var rows = _selector_row_indexes( settings, opts ); 8400 8401 return $.map( columns, function (col, idx) { 8402 return s( 8403 idx, 8404 __columnData( settings, idx, 0, 0, rows ), 8405 nodes[ idx ] 8406 ) ? idx : null; 8407 } ); 8408 } 8409 8410 // jQuery or string selector 8411 var match = typeof s === 'string' ? 8412 s.match( __re_column_selector ) : 8413 ''; 8414 8415 if ( match ) { 8416 switch( match[2] ) { 8417 case 'visIdx': 8418 case 'visible': 8419 var idx = parseInt( match[1], 10 ); 8420 // Visible index given, convert to column index 8421 if ( idx < 0 ) { 8422 // Counting from the right 8423 var visColumns = $.map( columns, function (col,i) { 8424 return col.bVisible ? i : null; 8425 } ); 8426 return [ visColumns[ visColumns.length + idx ] ]; 8427 } 8428 // Counting from the left 8429 return [ _fnVisibleToColumnIndex( settings, idx ) ]; 8430 8431 case 'name': 8432 // match by name. `names` is column index complete and in order 8433 return $.map( names, function (name, i) { 8434 return name === match[1] ? i : null; 8435 } ); 8436 8437 default: 8438 return []; 8439 } 8440 } 8441 8442 // Cell in the table body 8443 if ( s.nodeName && s._DT_CellIndex ) { 8444 return [ s._DT_CellIndex.column ]; 8445 } 8446 8447 // jQuery selector on the TH elements for the columns 8448 var jqResult = $( nodes ) 8449 .filter( s ) 8450 .map( function () { 8451 return $.inArray( this, nodes ); // `nodes` is column index complete and in order 8452 } ) 8453 .toArray(); 8454 8455 if ( jqResult.length || ! s.nodeName ) { 8456 return jqResult; 8457 } 8458 8459 // Otherwise a node which might have a `dt-column` data attribute, or be 8460 // a child or such an element 8461 var host = $(s).closest('*[data-dt-column]'); 8462 return host.length ? 8463 [ host.data('dt-column') ] : 8464 []; 8465 }; 8466 8467 return _selector_run( 'column', selector, run, settings, opts ); 8468 }; 8469 8470 8471 var __setColumnVis = function ( settings, column, vis ) { 8472 var 8473 cols = settings.aoColumns, 8474 col = cols[ column ], 8475 data = settings.aoData, 8476 row, cells, i, ien, tr; 8477 8478 // Get 8479 if ( vis === undefined ) { 8480 return col.bVisible; 8481 } 8482 8483 // Set 8484 // No change 8485 if ( col.bVisible === vis ) { 8486 return; 8487 } 8488 8489 if ( vis ) { 8490 // Insert column 8491 // Need to decide if we should use appendChild or insertBefore 8492 var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 ); 8493 8494 for ( i=0, ien=data.length ; i<ien ; i++ ) { 8495 tr = data[i].nTr; 8496 cells = data[i].anCells; 8497 8498 if ( tr ) { 8499 // insertBefore can act like appendChild if 2nd arg is null 8500 tr.insertBefore( cells[ column ], cells[ insertBefore ] || null ); 8501 } 8502 } 8503 } 8504 else { 8505 // Remove column 8506 $( _pluck( settings.aoData, 'anCells', column ) ).detach(); 8507 } 8508 8509 // Common actions 8510 col.bVisible = vis; 8511 _fnDrawHead( settings, settings.aoHeader ); 8512 _fnDrawHead( settings, settings.aoFooter ); 8513 8514 _fnSaveState( settings ); 8515 }; 8516 8517 8518 _api_register( 'columns()', function ( selector, opts ) { 8519 // argument shifting 8520 if ( selector === undefined ) { 8521 selector = ''; 8522 } 8523 else if ( $.isPlainObject( selector ) ) { 8524 opts = selector; 8525 selector = ''; 8526 } 8527 8528 opts = _selector_opts( opts ); 8529 8530 var inst = this.iterator( 'table', function ( settings ) { 8531 return __column_selector( settings, selector, opts ); 8532 }, 1 ); 8533 8534 // Want argument shifting here and in _row_selector? 8535 inst.selector.cols = selector; 8536 inst.selector.opts = opts; 8537 8538 return inst; 8539 } ); 8540 8541 _api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) { 8542 return this.iterator( 'column', function ( settings, column ) { 8543 return settings.aoColumns[column].nTh; 8544 }, 1 ); 8545 } ); 8546 8547 _api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) { 8548 return this.iterator( 'column', function ( settings, column ) { 8549 return settings.aoColumns[column].nTf; 8550 }, 1 ); 8551 } ); 8552 8553 _api_registerPlural( 'columns().data()', 'column().data()', function () { 8554 return this.iterator( 'column-rows', __columnData, 1 ); 8555 } ); 8556 8557 _api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () { 8558 return this.iterator( 'column', function ( settings, column ) { 8559 return settings.aoColumns[column].mData; 8560 }, 1 ); 8561 } ); 8562 8563 _api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) { 8564 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) { 8565 return _pluck_order( settings.aoData, rows, 8566 type === 'search' ? '_aFilterData' : '_aSortData', column 8567 ); 8568 }, 1 ); 8569 } ); 8570 8571 _api_registerPlural( 'columns().nodes()', 'column().nodes()', function () { 8572 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) { 8573 return _pluck_order( settings.aoData, rows, 'anCells', column ) ; 8574 }, 1 ); 8575 } ); 8576 8577 _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) { 8578 var ret = this.iterator( 'column', function ( settings, column ) { 8579 if ( vis === undefined ) { 8580 return settings.aoColumns[ column ].bVisible; 8581 } // else 8582 __setColumnVis( settings, column, vis ); 8583 } ); 8584 8585 // Group the column visibility changes 8586 if ( vis !== undefined ) { 8587 // Second loop once the first is done for events 8588 this.iterator( 'column', function ( settings, column ) { 8589 _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] ); 8590 } ); 8591 8592 if ( calc === undefined || calc ) { 8593 this.columns.adjust(); 8594 } 8595 } 8596 8597 return ret; 8598 } ); 8599 8600 _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) { 8601 return this.iterator( 'column', function ( settings, column ) { 8602 return type === 'visible' ? 8603 _fnColumnIndexToVisible( settings, column ) : 8604 column; 8605 }, 1 ); 8606 } ); 8607 8608 _api_register( 'columns.adjust()', function () { 8609 return this.iterator( 'table', function ( settings ) { 8610 _fnAdjustColumnSizing( settings ); 8611 }, 1 ); 8612 } ); 8613 8614 _api_register( 'column.index()', function ( type, idx ) { 8615 if ( this.context.length !== 0 ) { 8616 var ctx = this.context[0]; 8617 8618 if ( type === 'fromVisible' || type === 'toData' ) { 8619 return _fnVisibleToColumnIndex( ctx, idx ); 8620 } 8621 else if ( type === 'fromData' || type === 'toVisible' ) { 8622 return _fnColumnIndexToVisible( ctx, idx ); 8623 } 8624 } 8625 } ); 8626 8627 _api_register( 'column()', function ( selector, opts ) { 8628 return _selector_first( this.columns( selector, opts ) ); 8629 } ); 8630 8631 8632 8633 var __cell_selector = function ( settings, selector, opts ) 8634 { 8635 var data = settings.aoData; 8636 var rows = _selector_row_indexes( settings, opts ); 8637 var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) ); 8638 var allCells = $( [].concat.apply([], cells) ); 8639 var row; 8640 var columns = settings.aoColumns.length; 8641 var a, i, ien, j, o, host; 8642 8643 var run = function ( s ) { 8644 var fnSelector = typeof s === 'function'; 8645 8646 if ( s === null || s === undefined || fnSelector ) { 8647 // All cells and function selectors 8648 a = []; 8649 8650 for ( i=0, ien=rows.length ; i<ien ; i++ ) { 8651 row = rows[i]; 8652 8653 for ( j=0 ; j<columns ; j++ ) { 8654 o = { 8655 row: row, 8656 column: j 8657 }; 8658 8659 if ( fnSelector ) { 8660 // Selector - function 8661 host = data[ row ]; 8662 8663 if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) { 8664 a.push( o ); 8665 } 8666 } 8667 else { 8668 // Selector - all 8669 a.push( o ); 8670 } 8671 } 8672 } 8673 8674 return a; 8675 } 8676 8677 // Selector - index 8678 if ( $.isPlainObject( s ) ) { 8679 return [s]; 8680 } 8681 8682 // Selector - jQuery filtered cells 8683 var jqResult = allCells 8684 .filter( s ) 8685 .map( function (i, el) { 8686 return { // use a new object, in case someone changes the values 8687 row: el._DT_CellIndex.row, 8688 column: el._DT_CellIndex.column 8689 }; 8690 } ) 8691 .toArray(); 8692 8693 if ( jqResult.length || ! s.nodeName ) { 8694 return jqResult; 8695 } 8696 8697 // Otherwise the selector is a node, and there is one last option - the 8698 // element might be a child of an element which has dt-row and dt-column 8699 // data attributes 8700 host = $(s).closest('*[data-dt-row]'); 8701 return host.length ? 8702 [ { 8703 row: host.data('dt-row'), 8704 column: host.data('dt-column') 8705 } ] : 8706 []; 8707 }; 8708 8709 return _selector_run( 'cell', selector, run, settings, opts ); 8710 }; 8711 8712 8713 8714 8715 _api_register( 'cells()', function ( rowSelector, columnSelector, opts ) { 8716 // Argument shifting 8717 if ( $.isPlainObject( rowSelector ) ) { 8718 // Indexes 8719 if ( rowSelector.row === undefined ) { 8720 // Selector options in first parameter 8721 opts = rowSelector; 8722 rowSelector = null; 8723 } 8724 else { 8725 // Cell index objects in first parameter 8726 opts = columnSelector; 8727 columnSelector = null; 8728 } 8729 } 8730 if ( $.isPlainObject( columnSelector ) ) { 8731 opts = columnSelector; 8732 columnSelector = null; 8733 } 8734 8735 // Cell selector 8736 if ( columnSelector === null || columnSelector === undefined ) { 8737 return this.iterator( 'table', function ( settings ) { 8738 return __cell_selector( settings, rowSelector, _selector_opts( opts ) ); 8739 } ); 8740 } 8741 8742 // Row + column selector 8743 var columns = this.columns( columnSelector, opts ); 8744 var rows = this.rows( rowSelector, opts ); 8745 var a, i, ien, j, jen; 8746 8747 var cells = this.iterator( 'table', function ( settings, idx ) { 8748 a = []; 8749 8750 for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) { 8751 for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) { 8752 a.push( { 8753 row: rows[idx][i], 8754 column: columns[idx][j] 8755 } ); 8756 } 8757 } 8758 8759 return a; 8760 }, 1 ); 8761 8762 $.extend( cells.selector, { 8763 cols: columnSelector, 8764 rows: rowSelector, 8765 opts: opts 8766 } ); 8767 8768 return cells; 8769 } ); 8770 8771 8772 _api_registerPlural( 'cells().nodes()', 'cell().node()', function () { 8773 return this.iterator( 'cell', function ( settings, row, column ) { 8774 var data = settings.aoData[ row ]; 8775 8776 return data && data.anCells ? 8777 data.anCells[ column ] : 8778 undefined; 8779 }, 1 ); 8780 } ); 8781 8782 8783 _api_register( 'cells().data()', function () { 8784 return this.iterator( 'cell', function ( settings, row, column ) { 8785 return _fnGetCellData( settings, row, column ); 8786 }, 1 ); 8787 } ); 8788 8789 8790 _api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) { 8791 type = type === 'search' ? '_aFilterData' : '_aSortData'; 8792 8793 return this.iterator( 'cell', function ( settings, row, column ) { 8794 return settings.aoData[ row ][ type ][ column ]; 8795 }, 1 ); 8796 } ); 8797 8798 8799 _api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) { 8800 return this.iterator( 'cell', function ( settings, row, column ) { 8801 return _fnGetCellData( settings, row, column, type ); 8802 }, 1 ); 8803 } ); 8804 8805 8806 _api_registerPlural( 'cells().indexes()', 'cell().index()', function () { 8807 return this.iterator( 'cell', function ( settings, row, column ) { 8808 return { 8809 row: row, 8810 column: column, 8811 columnVisible: _fnColumnIndexToVisible( settings, column ) 8812 }; 8813 }, 1 ); 8814 } ); 8815 8816 8817 _api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) { 8818 return this.iterator( 'cell', function ( settings, row, column ) { 8819 _fnInvalidate( settings, row, src, column ); 8820 } ); 8821 } ); 8822 8823 8824 8825 _api_register( 'cell()', function ( rowSelector, columnSelector, opts ) { 8826 return _selector_first( this.cells( rowSelector, columnSelector, opts ) ); 8827 } ); 8828 8829 8830 _api_register( 'cell().data()', function ( data ) { 8831 var ctx = this.context; 8832 var cell = this[0]; 8833 8834 if ( data === undefined ) { 8835 // Get 8836 return ctx.length && cell.length ? 8837 _fnGetCellData( ctx[0], cell[0].row, cell[0].column ) : 8838 undefined; 8839 } 8840 8841 // Set 8842 _fnSetCellData( ctx[0], cell[0].row, cell[0].column, data ); 8843 _fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column ); 8844 8845 return this; 8846 } ); 8847 8848 8849 8850 /** 8851 * Get current ordering (sorting) that has been applied to the table. 8852 * 8853 * @returns {array} 2D array containing the sorting information for the first 8854 * table in the current context. Each element in the parent array represents 8855 * a column being sorted upon (i.e. multi-sorting with two columns would have 8856 * 2 inner arrays). The inner arrays may have 2 or 3 elements. The first is 8857 * the column index that the sorting condition applies to, the second is the 8858 * direction of the sort (`desc` or `asc`) and, optionally, the third is the 8859 * index of the sorting order from the `column.sorting` initialisation array. 8860 *//** 8861 * Set the ordering for the table. 8862 * 8863 * @param {integer} order Column index to sort upon. 8864 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`) 8865 * @returns {DataTables.Api} this 8866 *//** 8867 * Set the ordering for the table. 8868 * 8869 * @param {array} order 1D array of sorting information to be applied. 8870 * @param {array} [...] Optional additional sorting conditions 8871 * @returns {DataTables.Api} this 8872 *//** 8873 * Set the ordering for the table. 8874 * 8875 * @param {array} order 2D array of sorting information to be applied. 8876 * @returns {DataTables.Api} this 8877 */ 8878 _api_register( 'order()', function ( order, dir ) { 8879 var ctx = this.context; 8880 8881 if ( order === undefined ) { 8882 // get 8883 return ctx.length !== 0 ? 8884 ctx[0].aaSorting : 8885 undefined; 8886 } 8887 8888 // set 8889 if ( typeof order === 'number' ) { 8890 // Simple column / direction passed in 8891 order = [ [ order, dir ] ]; 8892 } 8893 else if ( order.length && ! $.isArray( order[0] ) ) { 8894 // Arguments passed in (list of 1D arrays) 8895 order = Array.prototype.slice.call( arguments ); 8896 } 8897 // otherwise a 2D array was passed in 8898 8899 return this.iterator( 'table', function ( settings ) { 8900 settings.aaSorting = order.slice(); 8901 } ); 8902 } ); 8903 8904 8905 /** 8906 * Attach a sort listener to an element for a given column 8907 * 8908 * @param {node|jQuery|string} node Identifier for the element(s) to attach the 8909 * listener to. This can take the form of a single DOM node, a jQuery 8910 * collection of nodes or a jQuery selector which will identify the node(s). 8911 * @param {integer} column the column that a click on this node will sort on 8912 * @param {function} [callback] callback function when sort is run 8913 * @returns {DataTables.Api} this 8914 */ 8915 _api_register( 'order.listener()', function ( node, column, callback ) { 8916 return this.iterator( 'table', function ( settings ) { 8917 _fnSortAttachListener( settings, node, column, callback ); 8918 } ); 8919 } ); 8920 8921 8922 _api_register( 'order.fixed()', function ( set ) { 8923 if ( ! set ) { 8924 var ctx = this.context; 8925 var fixed = ctx.length ? 8926 ctx[0].aaSortingFixed : 8927 undefined; 8928 8929 return $.isArray( fixed ) ? 8930 { pre: fixed } : 8931 fixed; 8932 } 8933 8934 return this.iterator( 'table', function ( settings ) { 8935 settings.aaSortingFixed = $.extend( true, {}, set ); 8936 } ); 8937 } ); 8938 8939 8940 // Order by the selected column(s) 8941 _api_register( [ 8942 'columns().order()', 8943 'column().order()' 8944 ], function ( dir ) { 8945 var that = this; 8946 8947 return this.iterator( 'table', function ( settings, i ) { 8948 var sort = []; 8949 8950 $.each( that[i], function (j, col) { 8951 sort.push( [ col, dir ] ); 8952 } ); 8953 8954 settings.aaSorting = sort; 8955 } ); 8956 } ); 8957 8958 8959 8960 _api_register( 'search()', function ( input, regex, smart, caseInsen ) { 8961 var ctx = this.context; 8962 8963 if ( input === undefined ) { 8964 // get 8965 return ctx.length !== 0 ? 8966 ctx[0].oPreviousSearch.sSearch : 8967 undefined; 8968 } 8969 8970 // set 8971 return this.iterator( 'table', function ( settings ) { 8972 if ( ! settings.oFeatures.bFilter ) { 8973 return; 8974 } 8975 8976 _fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, { 8977 "sSearch": input+"", 8978 "bRegex": regex === null ? false : regex, 8979 "bSmart": smart === null ? true : smart, 8980 "bCaseInsensitive": caseInsen === null ? true : caseInsen 8981 } ), 1 ); 8982 } ); 8983 } ); 8984 8985 8986 _api_registerPlural( 8987 'columns().search()', 8988 'column().search()', 8989 function ( input, regex, smart, caseInsen ) { 8990 return this.iterator( 'column', function ( settings, column ) { 8991 var preSearch = settings.aoPreSearchCols; 8992 8993 if ( input === undefined ) { 8994 // get 8995 return preSearch[ column ].sSearch; 8996 } 8997 8998 // set 8999 if ( ! settings.oFeatures.bFilter ) { 9000 return; 9001 } 9002 9003 $.extend( preSearch[ column ], { 9004 "sSearch": input+"", 9005 "bRegex": regex === null ? false : regex, 9006 "bSmart": smart === null ? true : smart, 9007 "bCaseInsensitive": caseInsen === null ? true : caseInsen 9008 } ); 9009 9010 _fnFilterComplete( settings, settings.oPreviousSearch, 1 ); 9011 } ); 9012 } 9013 ); 9014 9015 /* 9016 * State API methods 9017 */ 9018 9019 _api_register( 'state()', function () { 9020 return this.context.length ? 9021 this.context[0].oSavedState : 9022 null; 9023 } ); 9024 9025 9026 _api_register( 'state.clear()', function () { 9027 return this.iterator( 'table', function ( settings ) { 9028 // Save an empty object 9029 settings.fnStateSaveCallback.call( settings.oInstance, settings, {} ); 9030 } ); 9031 } ); 9032 9033 9034 _api_register( 'state.loaded()', function () { 9035 return this.context.length ? 9036 this.context[0].oLoadedState : 9037 null; 9038 } ); 9039 9040 9041 _api_register( 'state.save()', function () { 9042 return this.iterator( 'table', function ( settings ) { 9043 _fnSaveState( settings ); 9044 } ); 9045 } ); 9046 9047 9048 9049 /** 9050 * Provide a common method for plug-ins to check the version of DataTables being 9051 * used, in order to ensure compatibility. 9052 * 9053 * @param {string} version Version string to check for, in the format "X.Y.Z". 9054 * Note that the formats "X" and "X.Y" are also acceptable. 9055 * @returns {boolean} true if this version of DataTables is greater or equal to 9056 * the required version, or false if this version of DataTales is not 9057 * suitable 9058 * @static 9059 * @dtopt API-Static 9060 * 9061 * @example 9062 * alert( $.fn.dataTable.versionCheck( '1.9.0' ) ); 9063 */ 9064 DataTable.versionCheck = DataTable.fnVersionCheck = function( version ) 9065 { 9066 var aThis = DataTable.version.split('.'); 9067 var aThat = version.split('.'); 9068 var iThis, iThat; 9069 9070 for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) { 9071 iThis = parseInt( aThis[i], 10 ) || 0; 9072 iThat = parseInt( aThat[i], 10 ) || 0; 9073 9074 // Parts are the same, keep comparing 9075 if (iThis === iThat) { 9076 continue; 9077 } 9078 9079 // Parts are different, return immediately 9080 return iThis > iThat; 9081 } 9082 9083 return true; 9084 }; 9085 9086 9087 /** 9088 * Check if a `<table>` node is a DataTable table already or not. 9089 * 9090 * @param {node|jquery|string} table Table node, jQuery object or jQuery 9091 * selector for the table to test. Note that if more than more than one 9092 * table is passed on, only the first will be checked 9093 * @returns {boolean} true the table given is a DataTable, or false otherwise 9094 * @static 9095 * @dtopt API-Static 9096 * 9097 * @example 9098 * if ( ! $.fn.DataTable.isDataTable( '#example' ) ) { 9099 * $('#example').dataTable(); 9100 * } 9101 */ 9102 DataTable.isDataTable = DataTable.fnIsDataTable = function ( table ) 9103 { 9104 var t = $(table).get(0); 9105 var is = false; 9106 9107 if ( table instanceof DataTable.Api ) { 9108 return true; 9109 } 9110 9111 $.each( DataTable.settings, function (i, o) { 9112 var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null; 9113 var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null; 9114 9115 if ( o.nTable === t || head === t || foot === t ) { 9116 is = true; 9117 } 9118 } ); 9119 9120 return is; 9121 }; 9122 9123 9124 /** 9125 * Get all DataTable tables that have been initialised - optionally you can 9126 * select to get only currently visible tables. 9127 * 9128 * @param {boolean} [visible=false] Flag to indicate if you want all (default) 9129 * or visible tables only. 9130 * @returns {array} Array of `table` nodes (not DataTable instances) which are 9131 * DataTables 9132 * @static 9133 * @dtopt API-Static 9134 * 9135 * @example 9136 * $.each( $.fn.dataTable.tables(true), function () { 9137 * $(table).DataTable().columns.adjust(); 9138 * } ); 9139 */ 9140 DataTable.tables = DataTable.fnTables = function ( visible ) 9141 { 9142 var api = false; 9143 9144 if ( $.isPlainObject( visible ) ) { 9145 api = visible.api; 9146 visible = visible.visible; 9147 } 9148 9149 var a = $.map( DataTable.settings, function (o) { 9150 if ( !visible || (visible && $(o.nTable).is(':visible')) ) { 9151 return o.nTable; 9152 } 9153 } ); 9154 9155 return api ? 9156 new _Api( a ) : 9157 a; 9158 }; 9159 9160 9161 /** 9162 * Convert from camel case parameters to Hungarian notation. This is made public 9163 * for the extensions to provide the same ability as DataTables core to accept 9164 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase 9165 * parameters. 9166 * 9167 * @param {object} src The model object which holds all parameters that can be 9168 * mapped. 9169 * @param {object} user The object to convert from camel case to Hungarian. 9170 * @param {boolean} force When set to `true`, properties which already have a 9171 * Hungarian value in the `user` object will be overwritten. Otherwise they 9172 * won't be. 9173 */ 9174 DataTable.camelToHungarian = _fnCamelToHungarian; 9175 9176 9177 9178 /** 9179 * 9180 */ 9181 _api_register( '$()', function ( selector, opts ) { 9182 var 9183 rows = this.rows( opts ).nodes(), // Get all rows 9184 jqRows = $(rows); 9185 9186 return $( [].concat( 9187 jqRows.filter( selector ).toArray(), 9188 jqRows.find( selector ).toArray() 9189 ) ); 9190 } ); 9191 9192 9193 // jQuery functions to operate on the tables 9194 $.each( [ 'on', 'one', 'off' ], function (i, key) { 9195 _api_register( key+'()', function ( /* event, handler */ ) { 9196 var args = Array.prototype.slice.call(arguments); 9197 9198 // Add the `dt` namespace automatically if it isn't already present 9199 args[0] = $.map( args[0].split( /\s/ ), function ( e ) { 9200 return ! e.match(/\.dt\b/) ? 9201 e+'.dt' : 9202 e; 9203 } ).join( ' ' ); 9204 9205 var inst = $( this.tables().nodes() ); 9206 inst[key].apply( inst, args ); 9207 return this; 9208 } ); 9209 } ); 9210 9211 9212 _api_register( 'clear()', function () { 9213 return this.iterator( 'table', function ( settings ) { 9214 _fnClearTable( settings ); 9215 } ); 9216 } ); 9217 9218 9219 _api_register( 'settings()', function () { 9220 return new _Api( this.context, this.context ); 9221 } ); 9222 9223 9224 _api_register( 'init()', function () { 9225 var ctx = this.context; 9226 return ctx.length ? ctx[0].oInit : null; 9227 } ); 9228 9229 9230 _api_register( 'data()', function () { 9231 return this.iterator( 'table', function ( settings ) { 9232 return _pluck( settings.aoData, '_aData' ); 9233 } ).flatten(); 9234 } ); 9235 9236 9237 _api_register( 'destroy()', function ( remove ) { 9238 remove = remove || false; 9239 9240 return this.iterator( 'table', function ( settings ) { 9241 var orig = settings.nTableWrapper.parentNode; 9242 var classes = settings.oClasses; 9243 var table = settings.nTable; 9244 var tbody = settings.nTBody; 9245 var thead = settings.nTHead; 9246 var tfoot = settings.nTFoot; 9247 var jqTable = $(table); 9248 var jqTbody = $(tbody); 9249 var jqWrapper = $(settings.nTableWrapper); 9250 var rows = $.map( settings.aoData, function (r) { return r.nTr; } ); 9251 var i, ien; 9252 9253 // Flag to note that the table is currently being destroyed - no action 9254 // should be taken 9255 settings.bDestroying = true; 9256 9257 // Fire off the destroy callbacks for plug-ins etc 9258 _fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] ); 9259 9260 // If not being removed from the document, make all columns visible 9261 if ( ! remove ) { 9262 new _Api( settings ).columns().visible( true ); 9263 } 9264 9265 // Blitz all `DT` namespaced events (these are internal events, the 9266 // lowercase, `dt` events are user subscribed and they are responsible 9267 // for removing them 9268 jqWrapper.off('.DT').find(':not(tbody *)').off('.DT'); 9269 $(window).off('.DT-'+settings.sInstance); 9270 9271 // When scrolling we had to break the table up - restore it 9272 if ( table != thead.parentNode ) { 9273 jqTable.children('thead').detach(); 9274 jqTable.append( thead ); 9275 } 9276 9277 if ( tfoot && table != tfoot.parentNode ) { 9278 jqTable.children('tfoot').detach(); 9279 jqTable.append( tfoot ); 9280 } 9281 9282 settings.aaSorting = []; 9283 settings.aaSortingFixed = []; 9284 _fnSortingClasses( settings ); 9285 9286 $( rows ).removeClass( settings.asStripeClasses.join(' ') ); 9287 9288 $('th, td', thead).removeClass( classes.sSortable+' '+ 9289 classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone 9290 ); 9291 9292 if ( settings.bJUI ) { 9293 $('th span.'+classes.sSortIcon+ ', td span.'+classes.sSortIcon, thead).detach(); 9294 $('th, td', thead).each( function () { 9295 var wrapper = $('div.'+classes.sSortJUIWrapper, this); 9296 $(this).append( wrapper.contents() ); 9297 wrapper.detach(); 9298 } ); 9299 } 9300 9301 // Add the TR elements back into the table in their original order 9302 jqTbody.children().detach(); 9303 jqTbody.append( rows ); 9304 9305 // Remove the DataTables generated nodes, events and classes 9306 var removedMethod = remove ? 'remove' : 'detach'; 9307 jqTable[ removedMethod ](); 9308 jqWrapper[ removedMethod ](); 9309 9310 // If we need to reattach the table to the document 9311 if ( ! remove && orig ) { 9312 // insertBefore acts like appendChild if !arg[1] 9313 orig.insertBefore( table, settings.nTableReinsertBefore ); 9314 9315 // Restore the width of the original table - was read from the style property, 9316 // so we can restore directly to that 9317 jqTable 9318 .css( 'width', settings.sDestroyWidth ) 9319 .removeClass( classes.sTable ); 9320 9321 // If the were originally stripe classes - then we add them back here. 9322 // Note this is not fool proof (for example if not all rows had stripe 9323 // classes - but it's a good effort without getting carried away 9324 ien = settings.asDestroyStripes.length; 9325 9326 if ( ien ) { 9327 jqTbody.children().each( function (i) { 9328 $(this).addClass( settings.asDestroyStripes[i % ien] ); 9329 } ); 9330 } 9331 } 9332 9333 /* Remove the settings object from the settings array */ 9334 var idx = $.inArray( settings, DataTable.settings ); 9335 if ( idx !== -1 ) { 9336 DataTable.settings.splice( idx, 1 ); 9337 } 9338 } ); 9339 } ); 9340 9341 9342 // Add the `every()` method for rows, columns and cells in a compact form 9343 $.each( [ 'column', 'row', 'cell' ], function ( i, type ) { 9344 _api_register( type+'s().every()', function ( fn ) { 9345 var opts = this.selector.opts; 9346 var api = this; 9347 9348 return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) { 9349 // Rows and columns: 9350 // arg1 - index 9351 // arg2 - table counter 9352 // arg3 - loop counter 9353 // arg4 - undefined 9354 // Cells: 9355 // arg1 - row index 9356 // arg2 - column index 9357 // arg3 - table counter 9358 // arg4 - loop counter 9359 fn.call( 9360 api[ type ]( 9361 arg1, 9362 type==='cell' ? arg2 : opts, 9363 type==='cell' ? opts : undefined 9364 ), 9365 arg1, arg2, arg3, arg4 9366 ); 9367 } ); 9368 } ); 9369 } ); 9370 9371 9372 // i18n method for extensions to be able to use the language object from the 9373 // DataTable 9374 _api_register( 'i18n()', function ( token, def, plural ) { 9375 var ctx = this.context[0]; 9376 var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage ); 9377 9378 if ( resolved === undefined ) { 9379 resolved = def; 9380 } 9381 9382 if ( plural !== undefined && $.isPlainObject( resolved ) ) { 9383 resolved = resolved[ plural ] !== undefined ? 9384 resolved[ plural ] : 9385 resolved._; 9386 } 9387 9388 return resolved.replace( '%d', plural ); // nb: plural might be undefined, 9389 } ); 9390 9391 /**
9392 * Version string for plug-ins to check compatibility. Allowed format is 9393 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used 9394 * only for non-release builds. See http://semver.org/ for more information. 9395 * @member 9396 * @type string 9397 * @default Version number 9398 */ 9399 DataTable.version = "1.10.13"; 9400 9401 /** 9402 * Private data store, containing all of the settings objects that are 9403 * created for the tables on a given page. 9404 * 9405 * Note that the `DataTable.settings` object is aliased to 9406 * `jQuery.fn.dataTableExt` through which it may be accessed and 9407 * manipulated, or `jQuery.fn.dataTable.settings`. 9408 * @member 9409 * @type array 9410 * @default [] 9411 * @private 9412 */ 9413 DataTable.settings = []; 9414 9415 /** 9416 * Object models container, for the various models that DataTables has 9417 * available to it. These models define the objects that are used to hold 9418 * the active state and configuration of the table. 9419 * @namespace 9420 */ 9421 DataTable.models = {}; 9422 9423 9424 9425 /** 9426 * Template object for the way in which DataTables holds information about 9427 * search information for the global filter and individual column filters. 9428 * @namespace 9429 */ 9430 DataTable.models.oSearch = { 9431 /** 9432 * Flag to indicate if the filtering should be case insensitive or not 9433 * @type boolean 9434 * @default true 9435 */ 9436 "bCaseInsensitive": true, 9437 9438 /** 9439 * Applied search term 9440 * @type string 9441 * @default <i>Empty string</i> 9442 */ 9443 "sSearch": "", 9444 9445 /** 9446 * Flag to indicate if the search term should be interpreted as a 9447 * regular expression (true) or not (false) and therefore and special 9448 * regex characters escaped. 9449 * @type boolean 9450 * @default false 9451 */ 9452 "bRegex": false, 9453 9454 /** 9455 * Flag to indicate if DataTables is to use its smart filtering or not. 9456 * @type boolean 9457 * @default true 9458 */ 9459 "bSmart": true 9460 }; 9461 9462 9463 9464 9465 /** 9466 * Template object for the way in which DataTables holds information about 9467 * each individual row. This is the object format used for the settings 9468 * aoData array. 9469 * @namespace 9470 */ 9471 DataTable.models.oRow = { 9472 /** 9473 * TR element for the row 9474 * @type node 9475 * @default null 9476 */ 9477 "nTr": null, 9478 9479 /** 9480 * Array of TD elements for each row. This is null until the row has been 9481 * created. 9482 * @type array nodes 9483 * @default [] 9484 */ 9485 "anCells": null, 9486 9487 /** 9488 * Data object from the original data source for the row. This is either 9489 * an array if using the traditional form of DataTables, or an object if 9490 * using mData options. The exact type will depend on the passed in 9491 * data from the data source, or will be an array if using DOM a data 9492 * source. 9493 * @type array|object 9494 * @default [] 9495 */ 9496 "_aData": [], 9497 9498 /** 9499 * Sorting data cache - this array is ostensibly the same length as the 9500 * number of columns (although each index is generated only as it is 9501 * needed), and holds the data that is used for sorting each column in the 9502 * row. We do this cache generation at the start of the sort in order that 9503 * the formatting of the sort data need be done only once for each cell 9504 * per sort. This array should not be read from or written to by anything 9505 * other than the master sorting methods. 9506 * @type array 9507 * @default null 9508 * @private 9509 */ 9510 "_aSortData": null, 9511 9512 /** 9513 * Per cell filtering data cache. As per the sort data cache, used to 9514 * increase the performance of the filtering in DataTables 9515 * @type array 9516 * @default null 9517 * @private 9518 */ 9519 "_aFilterData": null, 9520 9521 /** 9522 * Filtering data cache. This is the same as the cell filtering cache, but 9523 * in this case a string rather than an array. This is easily computed with 9524 * a join on `_aFilterData`, but is provided as a cache so the join isn't 9525 * needed on every search (memory traded for performance) 9526 * @type array 9527 * @default null 9528 * @private 9529 */ 9530 "_sFilterRow": null, 9531 9532 /** 9533 * Cache of the class name that DataTables has applied to the row, so we 9534 * can quickly look at this variable rather than needing to do a DOM check 9535 * on className for the nTr property. 9536 * @type string 9537 * @default <i>Empty string</i> 9538 * @private 9539 */ 9540 "_sRowStripe": "", 9541 9542 /** 9543 * Denote if the original data source was from the DOM, or the data source 9544 * object. This is used for invalidating data, so DataTables can 9545 * automatically read data from the original source, unless uninstructed 9546 * otherwise. 9547 * @type string 9548 * @default null 9549 * @private 9550 */ 9551 "src": null, 9552 9553 /** 9554 * Index in the aoData array. This saves an indexOf lookup when we have the 9555 * object, but want to know the index 9556 * @type integer 9557 * @default -1 9558 * @private 9559 */ 9560 "idx": -1 9561 }; 9562 9563 9564 /** 9565 * Template object for the column information object in DataTables. This object 9566 * is held in the settings aoColumns array and contains all the information that 9567 * DataTables needs about each individual column. 9568 * 9569 * Note that this object is related to {@link DataTable.defaults.column} 9570 * but this one is the internal data store for DataTables's cache of columns. 9571 * It should NOT be manipulated outside of DataTables. Any configuration should 9572 * be done through the initialisation options. 9573 * @namespace 9574 */ 9575 DataTable.models.oColumn = { 9576 /** 9577 * Column index. This could be worked out on-the-fly with $.inArray, but it 9578 * is faster to just hold it as a variable 9579 * @type integer 9580 * @default null 9581 */ 9582 "idx": null, 9583 9584 /** 9585 * A list of the columns that sorting should occur on when this column 9586 * is sorted. That this property is an array allows multi-column s
9586orting 9587 * to be defined for a column (for example first name / last name columns 9588 * would benefit from this). The values are integers pointing to the 9589 * columns to be sorted on (typically it will be a single integer pointing 9590 * at itself, but that doesn't need to be the case). 9591 * @type array 9592 */ 9593 "aDataSort": null, 9594 9595 /** 9596 * Define the sorting directions that are applied to the column, in sequence 9597 * as the column is repeatedly sorted upon - i.e. the first value is used 9598 * as the sorting direction when the column if first sorted (clicked on). 9599 * Sort it again (click again) and it will move on to the next index. 9600 * Repeat until loop. 9601 * @type array 9602 */ 9603 "asSorting": null, 9604 9605 /** 9606 * Flag to indicate if the column is searchable, and thus should be included 9607 * in the filtering or not. 9608 * @type boolean 9609 */ 9610 "bSearchable": null, 9611 9612 /** 9613 * Flag to indicate if the column is sortable or not. 9614 * @type boolean 9615 */ 9616 "bSortable": null, 9617 9618 /** 9619 * Flag to indicate if the column is currently visible in the table or not 9620 * @type boolean 9621 */ 9622 "bVisible": null, 9623 9624 /** 9625 * Store for manual type assignment using the `column.type` option. This 9626 * is held in store so we can manipulate the column's `sType` property. 9627 * @type string 9628 * @default null 9629 * @private 9630 */ 9631 "_sManualType": null, 9632 9633 /** 9634 * Flag to indicate if HTML5 data attributes should be used as the data 9635 * source for filtering or sorting. True is either are. 9636 * @type boolean 9637 * @default false 9638 * @private 9639 */ 9640 "_bAttrSrc": false, 9641 9642 /** 9643 * Developer definable function that is called whenever a cell is created (Ajax source, 9644 * etc) or processed for input (DOM source). This can be used as a compliment to mRender 9645 * allowing you to modify the DOM element (add background colour for example) when the 9646 * element is available. 9647 * @type function 9648 * @param {element} nTd The TD node that has been created 9649 * @param {*} sData The Data for the cell 9650 * @param {array|object} oData The data for the whole row 9651 * @param {int} iRow The row index for the aoData data store 9652 * @default null 9653 */ 9654 "fnCreatedCell": null, 9655 9656 /** 9657 * Function to get data from a cell in a column. You should <b>never</b> 9658 * access data directly through _aData internally in DataTables - always use 9659 * the method attached to this property. It allows mData to function as 9660 * required. This function is automatically assigned by the column 9661 * initialisation method 9662 * @type function 9663 * @param {array|object} oData The data array/object for the array 9664 * (i.e. aoData[]._aData) 9665 * @param {string} sSpecific The specific data type you want to get - 9666 * 'display', 'type' 'filter' 'sort' 9667 * @returns {*} The data for the cell from the given row's data 9668 * @default null 9669 */ 9670 "fnGetData": null, 9671 9672 /** 9673 * Function to set data for a cell in the column. You should <b>never</b> 9674 * set the data directly to _aData internally in DataTables - always use 9675 * this method. It allows mData to function as required. This function 9676 * is automatically assigned by the column initialisation method 9677 * @type function 9678 * @param {array|object} oData The data array/object for the array 9679 * (i.e. aoData[]._aData) 9680 * @param {*} sValue Value to set 9681 * @default null 9682 */ 9683 "fnSetData": null, 9684 9685 /** 9686 * Property to read the value for the cells in the column from the data 9687 * source array / object. If null, then the default content is used, if a 9688 * function is given then the return from the function is used. 9689 * @type function|int|string|null 9690 * @default null 9691 */ 9692 "mData": null, 9693 9694 /** 9695 * Partner property to mData which is used (only when defined) to get 9696 * the data - i.e. it is basically the same as mData, but without the 9697 * 'set' option, and also the data fed to it is the result from mData. 9698 * This is the rendering method to match the data method of mData. 9699 * @type function|int|string|null 9700 * @default null 9701 */ 9702 "mRender": null, 9703 9704 /** 9705 * Unique header TH/TD element for this column - this is what the sorting 9706 * listener is attached to (if sorting is enabled.) 9707 * @type node 9708 * @default null 9709 */ 9710 "nTh": null, 9711 9712 /** 9713 * Unique footer TH/TD element for this column (if there is one). Not used
9714 * in DataTables as such, but can be used for plug-ins to reference the 9715 * footer for each column. 9716 * @type node 9717 * @default null 9718 */ 9719 "nTf": null, 9720 9721 /** 9722 * The class to apply to all TD elements in the table's TBODY for the column 9723 * @type string 9724 * @default null 9725 */ 9726 "sClass": null, 9727 9728 /** 9729 * When DataTables calculates the column widths to assign to each column, 9730 * it finds the longest string in each column and then constructs a 9731 * temporary table and reads the widths from that. The problem with this 9732 * is that "mmm" is much wider then "iiii", but the latter is a longer 9733 * string - thus the calculation can go wrong (doing it properly and putting 9734 * it into an DOM object and measuring that is horribly(!) slow). Thus as 9735 * a "work around" we provide this option. It will append its value to the 9736 * text that is found to be the longest string for the column - i.e. padding. 9737 * @type string 9738 */ 9739 "sContentPadding": null, 9740 9741 /** 9742 * Allows a default value to be given for a column's data, and will be used 9743 * whenever a null data source is encountered (this can be because mData 9744 * is set to null, or because the data source itself is null). 9745 * @type string 9746 * @default null 9747 */ 9748 "sDefaultContent": null, 9749 9750 /** 9751 * Name for the column, allowing reference to the column by name as well as 9752 * by index (needs a lookup to work by name). 9753 * @type string 9754 */ 9755 "sName": null, 9756 9757 /** 9758 * Custom sorting data type - defines which of the available plug-ins in 9759 * afnSortData the custom sorting will use - if any is defined. 9760 * @type string 9761 * @default std 9762 */ 9763 "sSortDataType": 'std', 9764 9765 /** 9766 * Class to be applied to the header element when sorting on this column 9767 * @type string 9768 * @default null 9769 */ 9770 "sSortingClass": null, 9771 9772 /** 9773 * Class to be applied to the header element when sorting on this column - 9774 * when jQuery UI theming is used. 9775 * @type string 9776 * @default null 9777 */ 9778 "sSortingClassJUI": null, 9779 9780 /** 9781 * Title of the column - what is seen in the TH element (nTh). 9782 * @type string 9783 */ 9784 "sTitle": null, 9785 9786 /** 9787 * Column sorting and filtering type 9788 * @type string 9789 * @default null 9790 */ 9791 "sType": null, 9792 9793 /** 9794 * Width of the column 9795 * @type string 9796 * @default null 9797 */ 9798 "sWidth": null, 9799 9800 /** 9801 * Width of the column when it was first "encountered" 9802 * @type string 9803 * @default null 9804 */ 9805 "sWidthOrig": null 9806 }; 9807 9808 9809 /* 9810 * Developer note: The properties of the object below are given in Hungarian 9811 * notation, that was used as the interface for DataTables prior to v1.10, however 9812 * from v1.10 onwards the primary interface is camel case. In order to avoid 9813 * breaking backwards compatibility utterly with this change, the Hungarian 9814 * version is still, internally the primary interface, but is is not documented 9815 * - hence the @name tags in each doc comment. This allows a Javascript function 9816 * to create a map from Hungarian notation to camel case (going the other direction 9817 * would require each property to be listed, which would at around 3K to the size 9818 * of DataTables, while this method is about a 0.5K hit
vendor: 16,919 bytes, lines 9818-10329
9818. 9819 * 9820 * Ultimately this does pave the way for Hungarian notation to be dropped 9821 * completely, but that is a massive amount of work and will break current 9822 * installs (therefore is on-hold until v2). 9823 */ 9824 9825 /** 9826 * Initialisation options that can be given to DataTables at initialisation 9827 * time. 9828 * @namespace 9829 */ 9830 DataTable.defaults = { 9831 /** 9832 * An array of data to use for the table, passed in at initialisation which 9833 * will be used in preference to any data which is already in the DOM. This is 9834 * particularly useful for constructing tables purely in Javascript, for 9835 * example with a custom Ajax call. 9836 * @type array 9837 * @default null 9838 * 9839 * @dtopt Option 9840 * @name DataTable.defaults.data 9841 * 9842 * @example 9843 * // Using a 2D array data source 9844 * $(document).ready( function () { 9845 * $('#example').dataTable( { 9846 * "data": [ 9847 * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'], 9848 * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'], 9849 * ], 9850 * "columns": [ 9851 * { "title": "Engine" }, 9852 * { "title": "Browser" }, 9853 * { "title": "Platform" }, 9854 * { "title": "Version" }, 9855 * { "title": "Grade" } 9856 * ] 9857 * } ); 9858 * } ); 9859 * 9860 * @example 9861 * // Using an array of objects as a data source (`data`) 9862 * $(document).ready( function () { 9863 * $('#example').dataTable( { 9864 * "data": [ 9865 * { 9866 * "engine": "Trident", 9867 * "browser": "Internet Explorer 4.0", 9868 * "platform": "Win 95+", 9869 * "version": 4, 9870 * "grade": "X" 9871 * }, 9872 * { 9873 * "engine": "Trident", 9874 * "browser": "Internet Explorer 5.0", 9875 * "platform": "Win 95+", 9876 * "version": 5, 9877 * "grade": "C" 9878 * } 9879 * ], 9880 * "columns": [ 9881 * { "title": "Engine", "data": "engine" }, 9882 * { "title": "Browser", "data": "browser" }, 9883 * { "title": "Platform", "data": "platform" }, 9884 * { "title": "Version", "data": "version" }, 9885 * { "title": "Grade", "data": "grade" } 9886 * ] 9887 * } ); 9888 * } ); 9889 */ 9890 "aaData": null, 9891 9892 9893 /** 9894 * If ordering is enabled, then DataTables will perform a first pass sort on 9895 * initialisation. You can define which column(s) the sort is performed 9896 * upon, and the sorting direction, with this variable. The `sorting` array 9897 * should contain an array for each column to be sorted initially containing 9898 * the column's index and a direction string ('asc' or 'desc'). 9899 * @type array 9900 * @default [[0,'asc']] 9901 * 9902 * @dtopt Option 9903 * @name DataTable.defaults.order 9904 * 9905 * @example 9906 * // Sort by 3rd column first, and then 4th column 9907 * $(document).ready( function() { 9908 * $('#example').dataTable( { 9909 * "order": [[2,'asc'], [3,'desc']] 9910 * } ); 9911 * } ); 9912 * 9913 * // No initial sorting 9914 * $(document).ready( function() { 9915 * $('#example').dataTable( { 9916 * "order": [] 9917 * } ); 9918 * } ); 9919 */ 9920 "aaSorting": [[0,'asc']], 9921 9922 9923 /** 9924 * This parameter is basically identical to the `sorting` parameter, but 9925 * cannot be overridden by user interaction with the table. What this means 9926 * is that you could have a column (visible or hidden) which the sorting 9927 * will always be forced on first - any sorting after that (from the user) 9928 * will then be performed as required. This can be useful for grouping rows 9929 * together. 9930 * @type array 9931 * @default null 9932 * 9933 * @dtopt Option 9934 * @name DataTable.defaults.orderFixed 9935 * 9936 * @example 9937 * $(document).ready( function() { 9938 * $('#example').dataTable( { 9939 * "orderFixed": [[0,'asc']] 9940 * } ); 9941 * } ) 9942 */ 9943 "aaSortingFixed": [], 9944 9945 9946 /** 9947 * DataTables can be instructed to load data to display in the table from a 9948 * Ajax source. This option defines how that Ajax call is made and where to. 9949 * 9950 * The `ajax` property has three different modes of operation, depending on 9951 * how it is defined. These are: 9952 * 9953 * * `string` - Set the URL from where the data should be loaded from. 9954 * * `object` - Define properties for `jQuery.ajax`. 9955 * * `function` - Custom data get function 9956 * 9957 * `string` 9958 * -------- 9959 * 9960 * As a string, the `ajax` property simply defines the URL from which 9961 * DataTables will load data. 9962 * 9963 * `object` 9964 * -------- 9965 * 9966 * As an object, the parameters in the object are passed to 9967 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control 9968 * of the Ajax request. DataTables has a number of default parameters which 9969 * you can override using this option. Please refer to the jQuery 9970 * documentation for a full description of the options available, although 9971 * the following parameters provide additional options in DataTables or 9972 * require special consideration: 9973 * 9974 * * `data` - As with jQuery, `data` can be provided as an object, but it 9975 * can also be used as a function to manipulate the data DataTables sends 9976 * to the server. The function takes a single parameter, an object of 9977 * parameters with the values that DataTables has readied for sending. An 9978 * object may be returned which will be merged into the DataTables 9979 * defaults, or you can add the items to the object that was passed in and 9980 * not return anything from the function. This supersedes `fnServerParams` 9981 * from DataTables 1.9-. 9982 * 9983 * * `dataSrc` - By default DataTables will look for the property `data` (or 9984 * `aaData` for compatibility with DataTables 1.9-) when obtaining data 9985 * from an Ajax source or for server-side processing - this parameter 9986 * allows that property to be changed. You can use Javascript dotted 9987 * object notation to get a data source for multiple levels of nesting, or 9988 * it my be used as a function. As a function it takes a single parameter, 9989 * the JSON returned from the server, which can be manipulated as 9990 * required, with the returned value being that used by DataTables as the 9991 * data source for the table. This supersedes `sAjaxDataProp` from 9992 * DataTables 1.9-. 9993 * 9994 * * `success` - Should not be overridden it is used internally in 9995 * DataTables. To manipulate / transform the data returned by the server 9996 * use `ajax.dataSrc`, or use `ajax` as a function (see below). 9997 * 9998 * `function` 9999 * ---------- 10000 * 10001 * As a function, making the Ajax call is left up to yourself allowing 10002 * complete control of the Ajax request. Indeed, if desired, a method other 10003 * than Ajax could be used to obtain the required data, such as Web storage 10004 * or an AIR database. 10005 * 10006 * The function is given four parameters and no return is required. The 10007 * parameters are: 10008 * 10009 * 1. _object_ - Data to send to the server 10010 * 2. _function_ - Callback function that must be executed when the required 10011 * data has been obtained. That data should be passed into the callback 10012 * as the only parameter 10013 * 3. _object_ - DataTables settings object for the table 10014 * 10015 * Note that this supersedes `fnServerData` from DataTables 1.9-. 10016 * 10017 * @type string|object|function 10018 * @default null 10019 * 10020 * @dtopt Option 10021 * @name DataTable.defaults.ajax 10022 * @since 1.10.0 10023 * 10024 * @example 10025 * // Get JSON data from a file via Ajax. 10026 * // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default). 10027 * $('#example').dataTable( { 10028 * "ajax": "data.json" 10029 * } ); 10030 * 10031 * @example 10032 * // Get JSON data from a file via Ajax, using `dataSrc` to change 10033 * // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`) 10034 * $('#example').dataTable( { 10035 * "ajax": { 10036 * "url": "data.json", 10037 * "dataSrc": "tableData" 10038 * } 10039 * } ); 10040 * 10041 * @example 10042 * // Get JSON data from a file via Ajax, using `dataSrc` to read data 10043 * // from a plain array rather than an array in an object 10044 * $('#example').dataTable( { 10045 * "ajax": { 10046 * "url": "data.json", 10047 * "dataSrc": "" 10048 * } 10049 * } ); 10050 * 10051 * @example 10052 * // Manipulate the data returned from the server - add a link to data 10053 * // (note this can, should, be done using `render` for the column - this 10054 * // is just a simple example of how the data can be manipulated). 10055 * $('#example').dataTable( { 10056 * "ajax": { 10057 * "url": "data.json", 10058 * "dataSrc": function ( json ) { 10059 * for ( var i=0, ien=json.length ; i<ien ; i++ ) { 10060 * json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>'; 10061 * } 10062 * return json; 10063 * } 10064 * } 10065 * } ); 10066 * 10067 * @example 10068 * // Add data to the request 10069 * $('#example').dataTable( { 10070 * "ajax": { 10071 * "url": "data.json", 10072 * "data": function ( d ) { 10073 * return { 10074 * "extra_search": $('#extra').val() 10075 * }; 10076 * } 10077 * } 10078 * } ); 10079 * 10080 * @example 10081 * // Send request as POST 10082 * $('#example').dataTable( { 10083 * "ajax": { 10084 * "url": "data.json", 10085 * "type": "POST" 10086 * } 10087 * } ); 10088 * 10089 * @example 10090 * // Get the data from localStorage (could interface with a form for 10091 * // adding, editing and removing rows). 10092 * $('#example').dataTable( { 10093 * "ajax": function (data, callback, settings) { 10094 * callback( 10095 * JSON.parse( localStorage.getItem('dataTablesData') ) 10096 * ); 10097 * } 10098 * } ); 10099 */ 10100 "ajax": null, 10101 10102 10103 /** 10104 * This parameter allows you to readily specify the entries in the length drop 10105 * down menu that DataTables shows when pagination is enabled. It can be 10106 * either a 1D array of options which will be used for both the displayed 10107 * option and the value, or a 2D array which will use the array in the first 10108 * position as the value, and the array in the second position as the 10109 * displayed options (useful for language strings such as 'All'). 10110 * 10111 * Note that the `pageLength` property will be automatically set to the 10112 * first value given in this array, unless `pageLength` is also provided. 10113 * @type array 10114 * @default [ 10, 25, 50, 100 ] 10115 * 10116 * @dtopt Option 10117 * @name DataTable.defaults.lengthMenu 10118 * 10119 * @example 10120 * $(document).ready( function() { 10121 * $('#example').dataTable( { 10122 * "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]] 10123 * } ); 10124 * } ); 10125 */ 10126 "aLengthMenu": [ 10, 25, 50, 100 ], 10127 10128 10129 /** 10130 * The `columns` option in the initialisation parameter allows you to define 10131 * details about the way individual columns behave. For a full list of 10132 * column options that can be set, please see 10133 * {@link DataTable.defaults.column}. Note that if you use `columns` to 10134 * define your columns, you must have an entry in the array for every single 10135 * column that you have in your table (these can be null if you don't which 10136 * to specify any options). 10137 * @member 10138 * 10139 * @name DataTable.defaults.column 10140 */ 10141 "aoColumns": null, 10142 10143 /** 10144 * Very similar to `columns`, `columnDefs` allows you to target a specific 10145 * column, multiple columns, or all columns, using the `targets` property of 10146 * each object in the array. This allows great flexibility when creating 10147 * tables, as the `columnDefs` arrays can be of any length, targeting the 10148 * columns you specifically want. `columnDefs` may use any of the column 10149 * options available: {@link DataTable.defaults.column}, but it _must_ 10150 * have `targets` defined in each object in the array. Values in the `targets` 10151 * array may be: 10152 * <ul> 10153 * <li>a string - class name will be matched on the TH for the column</li> 10154 * <li>0 or a positive integer - column index counting from the left</li> 10155 * <li>a negative integer - column index counting from the right</li> 10156 * <li>the string "_all" - all columns (i.e. assign a default)</li> 10157 * </ul> 10158 * @member 10159 * 10160 * @name DataTable.defaults.columnDefs 10161 */ 10162 "aoColumnDefs": null, 10163 10164 10165 /** 10166 * Basically the same as `search`, this parameter defines the individual column 10167 * filtering state at initialisation time. The array must be of the same size 10168 * as the number of columns, and each element be an object with the parameters 10169 * `search` and `escapeRegex` (the latter is optional). 'null' is also 10170 * accepted and the default will be used. 10171 * @type array 10172 * @default [] 10173 * 10174 * @dtopt Option 10175 * @name DataTable.defaults.searchCols 10176 * 10177 * @example 10178 * $(document).ready( function() { 10179 * $('#example').dataTable( { 10180 * "searchCols": [ 10181 * null, 10182 * { "search": "My filter" }, 10183 * null, 10184 * { "search": "^[0-9]", "escapeRegex": false } 10185 * ] 10186 * } ); 10187 * } ) 10188 */ 10189 "aoSearchCols": [], 10190 10191 10192 /** 10193 * An array of CSS classes that should be applied to displayed rows. This 10194 * array may be of any length, and DataTables will apply each class 10195 * sequentially, looping when required. 10196 * @type array 10197 * @default null <i>Will take the values determined by the `oClasses.stripe*` 10198 * options</i> 10199 * 10200 * @dtopt Option 10201 * @name DataTable.defaults.stripeClasses 10202 * 10203 * @example 10204 * $(document).ready( function() { 10205 * $('#example').dataTable( { 10206 * "stripeClasses": [ 'strip1', 'strip2', 'strip3' ] 10207 * } ); 10208 * } ) 10209 */ 10210 "asStripeClasses": null, 10211 10212 10213 /** 10214 * Enable or disable automatic column width calculation. This can be disabled 10215 * as an optimisation (it takes some time to calculate the widths) if the 10216 * tables widths are passed in using `columns`. 10217 * @type boolean 10218 * @default true 10219 * 10220 * @dtopt Features 10221 * @name DataTable.defaults.autoWidth 10222 * 10223 * @example 10224 * $(document).ready( function () { 10225 * $('#example').dataTable( { 10226 * "autoWidth": false 10227 * } ); 10228 * } ); 10229 */ 10230 "bAutoWidth": true, 10231 10232 10233 /** 10234 * Deferred rendering can provide DataTables with a huge speed boost when you 10235 * are using an Ajax or JS data source for the table. This option, when set to 10236 * true, will cause DataTables to defer the creation of the table elements for 10237 * each row until they are needed for a draw - saving a significant amount of 10238 * time. 10239 * @type boolean 10240 * @default false 10241 * 10242 * @dtopt Features 10243 * @name DataTable.defaults.deferRender 10244 * 10245 * @example 10246 * $(document).ready( function() { 10247 * $('#example').dataTable( { 10248 * "ajax": "sources/arrays.txt", 10249 * "deferRender": true 10250 * } ); 10251 * } ); 10252 */ 10253 "bDeferRender": false, 10254 10255 10256 /** 10257 * Replace a DataTable which matches the given selector and replace it with 10258 * one which has the properties of the new initialisation object passed. If no 10259 * table matches the selector, then the new DataTable will be constructed as 10260 * per normal. 10261 * @type boolean 10262 * @default false 10263 * 10264 * @dtopt Options 10265 * @name DataTable.defaults.destroy 10266 * 10267 * @example 10268 * $(document).ready( function() { 10269 * $('#example').dataTable( { 10270 * "srollY": "200px", 10271 * "paginate": false 10272 * } ); 10273 * 10274 * // Some time later.... 10275 * $('#example').dataTable( { 10276 * "filter": false, 10277 * "destroy": true 10278 * } ); 10279 * } ); 10280 */ 10281 "bDestroy": false, 10282 10283 10284 /** 10285 * Enable or disable filtering of data. Filtering in DataTables is "smart" in 10286 * that it allows the end user to input multiple words (space separated) and 10287 * will match a row containing those words, even if not in the order that was 10288 * specified (this allow matching across multiple columns). Note that if you 10289 * wish to use filtering in DataTables this must remain 'true' - to remove the 10290 * default filtering input box and retain filtering abilities, please use 10291 * {@link DataTable.defaults.dom}. 10292 * @type boolean 10293 * @default true 10294 * 10295 * @dtopt Features 10296 * @name DataTable.defaults.searching 10297 * 10298 * @example 10299 * $(document).ready( function () { 10300 * $('#example').dataTable( { 10301 * "searching": false 10302 * } ); 10303 * } ); 10304 */ 10305 "bFilter": true, 10306 10307 10308 /** 10309 * Enable or disable the table information display. This shows information 10310 * about the data that is currently visible on the page, including information 10311 * about filtered data if that action is being performed. 10312 * @type boolean 10313 * @default true 10314 * 10315 * @dtopt Features 10316 * @name DataTable.defaults.info 10317 * 10318 * @example 10319 * $(document).ready( function () { 10320 * $('#example').dataTable( { 10321 * "info": false 10322 * } ); 10323 * } ); 10324 */ 10325 "bInfo": true, 10326 10327 10328 /** 10329 *
10329Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some 10330 * slightly different and additional mark-up from what DataTables has 10331 * traditionally used). 10332 * @type boolean 10333 * @default false 10334 * 10335 * @dtopt Features 10336 * @name DataTable.defaults.jQueryUI 10337 * 10338 * @example 10339 * $(document).ready( function() { 10340 * $('#example').dataTable( { 10341 * "jQueryUI": true 10342 * } ); 10343 * } ); 10344 */ 10345 "bJQueryUI": fals
vendor: 40,186 bytes, lines 10345-11614
10345e, 10346 10347 10348 /** 10349 * Allows the end user to select the size of a formatted page from a select 10350 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`). 10351 * @type boolean 10352 * @default true 10353 * 10354 * @dtopt Features 10355 * @name DataTable.defaults.lengthChange 10356 * 10357 * @example 10358 * $(document).ready( function () { 10359 * $('#example').dataTable( { 10360 * "lengthChange": false 10361 * } ); 10362 * } ); 10363 */ 10364 "bLengthChange": true, 10365 10366 10367 /** 10368 * Enable or disable pagination. 10369 * @type boolean 10370 * @default true 10371 * 10372 * @dtopt Features 10373 * @name DataTable.defaults.paging 10374 * 10375 * @example 10376 * $(document).ready( function () { 10377 * $('#example').dataTable( { 10378 * "paging": false 10379 * } ); 10380 * } ); 10381 */ 10382 "bPaginate": true, 10383 10384 10385 /** 10386 * Enable or disable the display of a 'processing' indicator when the table is 10387 * being processed (e.g. a sort). This is particularly useful for tables with 10388 * large amounts of data where it can take a noticeable amount of time to sort 10389 * the entries. 10390 * @type boolean 10391 * @default false 10392 * 10393 * @dtopt Features 10394 * @name DataTable.defaults.processing 10395 * 10396 * @example 10397 * $(document).ready( function () { 10398 * $('#example').dataTable( { 10399 * "processing": true 10400 * } ); 10401 * } ); 10402 */ 10403 "bProcessing": false, 10404 10405 10406 /** 10407 * Retrieve the DataTables object for the given selector. Note that if the 10408 * table has already been initialised, this parameter will cause DataTables 10409 * to simply return the object that has already been set up - it will not take 10410 * account of any changes you might have made to the initialisation object 10411 * passed to DataTables (setting this parameter to true is an acknowledgement 10412 * that you understand this). `destroy` can be used to reinitialise a table if 10413 * you need. 10414 * @type boolean 10415 * @default false 10416 * 10417 * @dtopt Options 10418 * @name DataTable.defaults.retrieve 10419 * 10420 * @example 10421 * $(document).ready( function() { 10422 * initTable(); 10423 * tableActions(); 10424 * } ); 10425 * 10426 * function initTable () 10427 * { 10428 * return $('#example').dataTable( { 10429 * "scrollY": "200px", 10430 * "paginate": false, 10431 * "retrieve": true 10432 * } ); 10433 * } 10434 * 10435 * function tableActions () 10436 * { 10437 * var table = initTable(); 10438 * // perform API operations with oTable 10439 * } 10440 */ 10441 "bRetrieve": false, 10442 10443 10444 /** 10445 * When vertical (y) scrolling is enabled, DataTables will force the height of 10446 * the table's viewport to the given height at all times (useful for layout). 10447 * However, this can look odd when filtering data down to a small data set, 10448 * and the footer is left "floating" further down. This parameter (when 10449 * enabled) will cause DataTables to collapse the table's viewport down when 10450 * the result set will fit within the given Y height. 10451 * @type boolean 10452 * @default false 10453 * 10454 * @dtopt Options 10455 * @name DataTable.defaults.scrollCollapse 10456 * 10457 * @example 10458 * $(document).ready( function() { 10459 * $('#example').dataTable( { 10460 * "scrollY": "200", 10461 * "scrollCollapse": true 10462 * } ); 10463 * } ); 10464 */ 10465 "bScrollCollapse": false, 10466 10467 10468 /** 10469 * Configure DataTables to use server-side processing. Note that the 10470 * `ajax` parameter must also be given in order to give DataTables a 10471 * source to obtain the required data for each draw. 10472 * @type boolean 10473 * @default false 10474 * 10475 * @dtopt Features 10476 * @dtopt Server-side 10477 * @name DataTable.defaults.serverSide 10478 * 10479 * @example 10480 * $(document).ready( function () { 10481 * $('#example').dataTable( { 10482 * "serverSide": true, 10483 * "ajax": "xhr.php" 10484 * } ); 10485 * } ); 10486 */ 10487 "bServerSide": false, 10488 10489 10490 /** 10491 * Enable or disable sorting of columns. Sorting of individual columns can be 10492 * disabled by the `sortable` option for each column. 10493 * @type boolean 10494 * @default true 10495 * 10496 * @dtopt Features 10497 * @name DataTable.defaults.ordering 10498 * 10499 * @example 10500 * $(document).ready( function () { 10501 * $('#example').dataTable( { 10502 * "ordering": false 10503 * } ); 10504 * } ); 10505 */ 10506 "bSort": true, 10507 10508 10509 /** 10510 * Enable or display DataTables' ability to sort multiple columns at the 10511 * same time (activated by shift-click by the user). 10512 * @type boolean 10513 * @default true 10514 * 10515 * @dtopt Options 10516 * @name DataTable.defaults.orderMulti 10517 * 10518 * @example 10519 * // Disable multiple column sorting ability 10520 * $(document).ready( function () { 10521 * $('#example').dataTable( { 10522 * "orderMulti": false 10523 * } ); 10524 * } ); 10525 */ 10526 "bSortMulti": true, 10527 10528 10529 /** 10530 * Allows control over whether DataTables should use the top (true) unique 10531 * cell that is found for a single column, or the bottom (false - default). 10532 * This is useful when using complex headers. 10533 * @type boolean 10534 * @default false 10535 * 10536 * @dtopt Options 10537 * @name DataTable.defaults.orderCellsTop 10538 * 10539 * @example 10540 * $(document).ready( function() { 10541 * $('#example').dataTable( { 10542 * "orderCellsTop": true 10543 * } ); 10544 * } ); 10545 */ 10546 "bSortCellsTop": false, 10547 10548 10549 /** 10550 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and 10551 * `sorting\_3` to the columns which are currently being sorted on. This is 10552 * presented as a feature switch as it can increase processing time (while 10553 * classes are removed and added) so for large data sets you might want to 10554 * turn this off. 10555 * @type boolean 10556 * @default true 10557 * 10558 * @dtopt Features 10559 * @name DataTable.defaults.orderClasses 10560 * 10561 * @example 10562 * $(document).ready( function () { 10563 * $('#example').dataTable( { 10564 * "orderClasses": false 10565 * } ); 10566 * } ); 10567 */ 10568 "bSortClasses": true, 10569 10570 10571 /** 10572 * Enable or disable state saving. When enabled HTML5 `localStorage` will be 10573 * used to save table display information such as pagination information, 10574 * display length, filtering and sorting. As such when the end user reloads 10575 * the page the display display will match what thy had previously set up. 10576 * 10577 * Due to the use of `localStorage` the default state saving is not supported 10578 * in IE6 or 7. If state saving is required in those browsers, use 10579 * `stateSaveCallback` to provide a storage solution such as cookies. 10580 * @type boolean 10581 * @default false 10582 * 10583 * @dtopt Features 10584 * @name DataTable.defaults.stateSave 10585 * 10586 * @example 10587 * $(document).ready( function () { 10588 * $('#example').dataTable( { 10589 * "stateSave": true 10590 * } ); 10591 * } ); 10592 */ 10593 "bStateSave": false, 10594 10595 10596 /** 10597 * This function is called when a TR element is created (and all TD child 10598 * elements have been inserted), or registered if using a DOM source, allowing 10599 * manipulation of the TR element (adding classes etc). 10600 * @type function 10601 * @param {node} row "TR" element for the current row 10602 * @param {array} data Raw data array for this row 10603 * @param {int} dataIndex The index of this row in the internal aoData array 10604 * 10605 * @dtopt Callbacks 10606 * @name DataTable.defaults.createdRow 10607 * 10608 * @example 10609 * $(document).ready( function() { 10610 * $('#example').dataTable( { 10611 * "createdRow": function( row, data, dataIndex ) { 10612 * // Bold the grade for all 'A' grade browsers 10613 * if ( data[4] == "A" ) 10614 * { 10615 * $('td:eq(4)', row).html( '<b>A</b>' ); 10616 * } 10617 * } 10618 * } ); 10619 * } ); 10620 */ 10621 "fnCreatedRow": null, 10622 10623 10624 /** 10625 * This function is called on every 'draw' event, and allows you to 10626 * dynamically modify any aspect you want about the created DOM. 10627 * @type function 10628 * @param {object} settings DataTables settings object 10629 * 10630 * @dtopt Callbacks 10631 * @name DataTable.defaults.drawCallback 10632 * 10633 * @example 10634 * $(document).ready( function() { 10635 * $('#example').dataTable( { 10636 * "drawCallback": function( settings ) { 10637 * alert( 'DataTables has redrawn the table' ); 10638 * } 10639 * } ); 10640 * } ); 10641 */ 10642 "fnDrawCallback": null, 10643 10644 10645 /** 10646 * Identical to fnHeaderCallback() but for the table footer this function 10647 * allows you to modify the table footer on every 'draw' event. 10648 * @type function 10649 * @param {node} foot "TR" element for the footer 10650 * @param {array} data Full table data (as derived from the original HTML) 10651 * @param {int} start Index for the current display starting point in the 10652 * display array 10653 * @param {int} end Index for the current display ending point in the 10654 * display array 10655 * @param {array int} display Index array to translate the visual position 10656 * to the full data array 10657 * 10658 * @dtopt Callbacks 10659 * @name DataTable.defaults.footerCallback 10660 * 10661 * @example 10662 * $(document).ready( function() { 10663 * $('#example').dataTable( { 10664 * "footerCallback": function( tfoot, data, start, end, display ) { 10665 * tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start; 10666 * } 10667 * } ); 10668 * } ) 10669 */ 10670 "fnFooterCallback": null, 10671 10672 10673 /** 10674 * When rendering large numbers in the information element for the table 10675 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers 10676 * to have a comma separator for the 'thousands' units (e.g. 1 million is 10677 * rendered as "1,000,000") to help readability for the end user. This 10678 * function will override the default method DataTables uses. 10679 * @type function 10680 * @member 10681 * @param {int} toFormat number to be formatted 10682 * @returns {string} formatted string for DataTables to show the number 10683 * 10684 * @dtopt Callbacks 10685 * @name DataTable.defaults.formatNumber 10686 * 10687 * @example 10688 * // Format a number using a single quote for the separator (note that 10689 * // this can also be done with the language.thousands option) 10690 * $(document).ready( function() { 10691 * $('#example').dataTable( { 10692 * "formatNumber": function ( toFormat ) { 10693 * return toFormat.toString().replace( 10694 * /\B(?=(\d{3})+(?!\d))/g, "'" 10695 * ); 10696 * }; 10697 * } ); 10698 * } ); 10699 */ 10700 "fnFormatNumber": function ( toFormat ) { 10701 return toFormat.toString().replace( 10702 /\B(?=(\d{3})+(?!\d))/g, 10703 this.oLanguage.sThousands 10704 ); 10705 }, 10706 10707 10708 /** 10709 * This function is called on every 'draw' event, and allows you to 10710 * dynamically modify the header row. This can be used to calculate and 10711 * display useful information about the table. 10712 * @type function 10713 * @param {node} head "TR" element for the header 10714 * @param {array} data Full table data (as derived from the original HTML) 10715 * @param {int} start Index for the current display starting point in the 10716 * display array 10717 * @param {int} end Index for the current display ending point in the 10718 * display array 10719 * @param {array int} display Index array to translate the visual position 10720 * to the full data array 10721 * 10722 * @dtopt Callbacks 10723 * @name DataTable.defaults.headerCallback 10724 * 10725 * @example 10726 * $(document).ready( function() { 10727 * $('#example').dataTable( { 10728 * "fheaderCallback": function( head, data, start, end, display ) { 10729 * head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records"; 10730 * } 10731 * } ); 10732 * } ) 10733 */ 10734 "fnHeaderCallback": null, 10735 10736 10737 /** 10738 * The information element can be used to convey information about the current 10739 * state of the table. Although the internationalisation options presented by 10740 * DataTables are quite capable of dealing with most customisations, there may 10741 * be times where you wish to customise the string further. This callback 10742 * allows you to do exactly that. 10743 * @type function 10744 * @param {object} oSettings DataTables settings object 10745 * @param {int} start Starting position in data for the draw 10746 * @param {int} end End position in data for the draw 10747 * @param {int} max Total number of rows in the table (regardless of 10748 * filtering) 10749 * @param {int} total Total number of rows in the data set, after filtering 10750 * @param {string} pre The string that DataTables has formatted using it's 10751 * own rules 10752 * @returns {string} The string to be displayed in the information element. 10753 * 10754 * @dtopt Callbacks 10755 * @name DataTable.defaults.infoCallback 10756 * 10757 * @example 10758 * $('#example').dataTable( { 10759 * "infoCallback": function( settings, start, end, max, total, pre ) { 10760 * return start +" to "+ end; 10761 * } 10762 * } ); 10763 */ 10764 "fnInfoCallback": null, 10765 10766 10767 /** 10768 * Called when the table has been initialised. Normally DataTables will 10769 * initialise sequentially and there will be no need for this function, 10770 * however, this does not hold true when using external language information 10771 * since that is obtained using an async XHR call. 10772 * @type function 10773 * @param {object} settings DataTables settings object 10774 * @param {object} json The JSON object request from the server - only 10775 * present if client-side Ajax sourced data is used 10776 * 10777 * @dtopt Callbacks 10778 * @name DataTable.defaults.initComplete 10779 * 10780 * @example 10781 * $(document).ready( function() { 10782 * $('#example').dataTable( { 10783 * "initComplete": function(settings, json) { 10784 * alert( 'DataTables has finished its initialisation.' ); 10785 * } 10786 * } ); 10787 * } ) 10788 */ 10789 "fnInitComplete": null, 10790 10791 10792 /** 10793 * Called at the very start of each table draw and can be used to cancel the 10794 * draw by returning false, any other return (including undefined) results in 10795 * the full draw occurring). 10796 * @type function 10797 * @param {object} settings DataTables settings object 10798 * @returns {boolean} False will cancel the draw, anything else (including no 10799 * return) will allow it to complete. 10800 * 10801 * @dtopt Callbacks 10802 * @name DataTable.defaults.preDrawCallback 10803 * 10804 * @example 10805 * $(document).ready( function() { 10806 * $('#example').dataTable( { 10807 * "preDrawCallback": function( settings ) { 10808 * if ( $('#test').val() == 1 ) { 10809 * return false; 10810 * } 10811 * } 10812 * } ); 10813 * } ); 10814 */ 10815 "fnPreDrawCallback": null, 10816 10817 10818 /** 10819 * This function allows you to 'post process' each row after it have been 10820 * generated for each table draw, but before it is rendered on screen. This 10821 * function might be used for setting the row class name etc. 10822 * @type function 10823 * @param {node} row "TR" element for the current row 10824 * @param {array} data Raw data array for this row 10825 * @param {int} displayIndex The display index for the current table draw 10826 * @param {int} displayIndexFull The index of the data in the full list of 10827 * rows (after filtering) 10828 * 10829 * @dtopt Callbacks 10830 * @name DataTable.defaults.rowCallback 10831 * 10832 * @example 10833 * $(document).ready( function() { 10834 * $('#example').dataTable( { 10835 * "rowCallback": function( row, data, displayIndex, displayIndexFull ) { 10836 * // Bold the grade for all 'A' grade browsers 10837 * if ( data[4] == "A" ) { 10838 * $('td:eq(4)', row).html( '<b>A</b>' ); 10839 * } 10840 * } 10841 * } ); 10842 * } ); 10843 */ 10844 "fnRowCallback": null, 10845 10846 10847 /** 10848 * __Deprecated__ The functionality provided by this parameter has now been 10849 * superseded by that provided through `ajax`, which should be used instead. 10850 * 10851 * This parameter allows you to override the default function which obtains 10852 * the data from the server so something more suitable for your application. 10853 * For example you could use POST data, or pull information from a Gears or 10854 * AIR database. 10855 * @type function 10856 * @member 10857 * @param {string} source HTTP source to obtain the data from (`ajax`) 10858 * @param {array} data A key/value pair object containing the data to send 10859 * to the server 10860 * @param {function} callback to be called on completion of the data get 10861 * process that will draw the data on the page. 10862 * @param {object} settings DataTables settings object 10863 * 10864 * @dtopt Callbacks 10865 * @dtopt Server-side 10866 * @name DataTable.defaults.serverData 10867 * 10868 * @deprecated 1.10. Please use `ajax` for this functionality now. 10869 */ 10870 "fnServerData": null, 10871 10872 10873 /** 10874 * __Deprecated__ The functionality provided by this parameter has now been 10875 * superseded by that provided through `ajax`, which should be used instead. 10876 * 10877 * It is often useful to send extra data to the server when making an Ajax 10878 * request - for example custom filtering information, and this callback 10879 * function makes it trivial to send extra information to the server. The 10880 * passed in parameter is the data set that has been constructed by 10881 * DataTables, and you can add to this or modify it as you require. 10882 * @type function 10883 * @param {array} data Data array (array of objects which are name/value 10884 * pairs) that has been constructed by DataTables and will be sent to the 10885 * server. In the case of Ajax sourced data with server-side processing 10886 * this will be an empty array, for server-side processing there will be a 10887 * significant number of parameters! 10888 * @returns {undefined} Ensure that you modify the data array passed in, 10889 * as this is passed by reference. 10890 * 10891 * @dtopt Callbacks 10892 * @dtopt Server-side 10893 * @name DataTable.defaults.serverParams 10894 * 10895 * @deprecated 1.10. Please use `ajax` for this functionality now. 10896 */ 10897 "fnServerParams": null, 10898 10899 10900 /** 10901 * Load the table state. With this function you can define from where, and how, the 10902 * state of a table is loaded. By default DataTables will load from `localStorage` 10903 * but you might wish to use a server-side database or cookies. 10904 * @type function 10905 * @member 10906 * @param {object} settings DataTables settings object 10907 * @param {object} callback Callback that can be executed when done. It 10908 * should be passed the loaded state object. 10909 * @return {object} The DataTables state object to be loaded 10910 * 10911 * @dtopt Callbacks 10912 * @name DataTable.defaults.stateLoadCallback 10913 * 10914 * @example 10915 * $(document).ready( function() { 10916 * $('#example').dataTable( { 10917 * "stateSave": true, 10918 * "stateLoadCallback": function (settings, callback) { 10919 * $.ajax( { 10920 * "url": "/state_load", 10921 * "dataType": "json", 10922 * "success": function (json) { 10923 * callback( json ); 10924 * } 10925 * } ); 10926 * } 10927 * } ); 10928 * } ); 10929 */ 10930 "fnStateLoadCallback": function ( settings ) { 10931 try { 10932 return JSON.parse( 10933 (settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem( 10934 'DataTables_'+settings.sInstance+'_'+location.pathname 10935 ) 10936 ); 10937 } catch (e) {} 10938 }, 10939 10940 10941 /** 10942 * Callback which allows modification of the saved state prior to loading that state. 10943 * This callback is called when the table is loading state from the stored data, but 10944 * prior to the settings object being modified by the saved state. Note that for 10945 * plug-in authors, you should use the `stateLoadParams` event to load parameters for 10946 * a plug-in. 10947 * @type function 10948 * @param {object} settings DataTables settings object 10949 * @param {object} data The state object that is to be loaded 10950 * 10951 * @dtopt Callbacks 10952 * @name DataTable.defaults.stateLoadParams 10953 * 10954 * @example 10955 * // Remove a saved filter, so filtering is never loaded 10956 * $(document).ready( function() { 10957 * $('#example').dataTable( { 10958 * "stateSave": true, 10959 * "stateLoadParams": function (settings, data) { 10960 * data.oSearch.sSearch = ""; 10961 * } 10962 * } ); 10963 * } ); 10964 * 10965 * @example 10966 * // Disallow state loading by returning false 10967 * $(document).ready( function() { 10968 * $('#example').dataTable( { 10969 * "stateSave": true, 10970 * "stateLoadParams": function (settings, data) { 10971 * return false; 10972 * } 10973 * } ); 10974 * } ); 10975 */ 10976 "fnStateLoadParams": null, 10977 10978 10979 /** 10980 * Callback that is called when the state has been loaded from the state saving method 10981 * and the DataTables settings object has been modified as a result of the loaded state. 10982 * @type function 10983 * @param {object} settings DataTables settings object 10984 * @param {object} data The state object that was loaded 10985 * 10986 * @dtopt Callbacks 10987 * @name DataTable.defaults.stateLoaded 10988 * 10989 * @example 10990 * // Show an alert with the filtering value that was saved 10991 * $(document).ready( function() { 10992 * $('#example').dataTable( { 10993 * "stateSave": true, 10994 * "stateLoaded": function (settings, data) { 10995 * alert( 'Saved filter was: '+data.oSearch.sSearch ); 10996 * } 10997 * } ); 10998 * } ); 10999 */ 11000 "fnStateLoaded": null, 11001 11002 11003 /** 11004 * Save the table state. This function allows you to define where and how the state 11005 * information for the table is stored By default DataTables will use `localStorage` 11006 * but you might wish to use a server-side database or cookies. 11007 * @type function 11008 * @member 11009 * @param {object} settings DataTables settings object 11010 * @param {object} data The state object to be saved 11011 * 11012 * @dtopt Callbacks 11013 * @name DataTable.defaults.stateSaveCallback 11014 * 11015 * @example 11016 * $(document).ready( function() { 11017 * $('#example').dataTable( { 11018 * "stateSave": true, 11019 * "stateSaveCallback": function (settings, data) { 11020 * // Send an Ajax request to the server with the state object 11021 * $.ajax( { 11022 * "url": "/state_save", 11023 * "data": data, 11024 * "dataType": "json", 11025 * "method": "POST" 11026 * "success": function () {} 11027 * } ); 11028 * } 11029 * } ); 11030 * } ); 11031 */ 11032 "fnStateSaveCallback": function ( settings, data ) { 11033 try { 11034 (settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem( 11035 'DataTables_'+settings.sInstance+'_'+location.pathname, 11036 JSON.stringify( data ) 11037 ); 11038 } catch (e) {} 11039 }, 11040 11041 11042 /** 11043 * Callback which allows modification of the state to be saved. Called when the table 11044 * has changed state a new state save is required. This method allows modification of 11045 * the state saving object prior to actually doing the save, including addition or 11046 * other state properties or modification. Note that for plug-in authors, you should 11047 * use the `stateSaveParams` event to save parameters for a plug-in. 11048 * @type function 11049 * @param {object} settings DataTables settings object 11050 * @param {object} data The state object to be saved 11051 * 11052 * @dtopt Callbacks 11053 * @name DataTable.defaults.stateSaveParams 11054 * 11055 * @example 11056 * // Remove a saved filter, so filtering is never saved 11057 * $(document).ready( function() { 11058 * $('#example').dataTable( { 11059 * "stateSave": true, 11060 * "stateSaveParams": function (settings, data) { 11061 * data.oSearch.sSearch = ""; 11062 * } 11063 * } ); 11064 * } ); 11065 */ 11066 "fnStateSaveParams": null, 11067 11068 11069 /** 11070 * Duration for which the saved state information is considered valid. After this period 11071 * has elapsed the state will be returned to the default. 11072 * Value is given in seconds. 11073 * @type int 11074 * @default 7200 <i>(2 hours)</i> 11075 * 11076 * @dtopt Options 11077 * @name DataTable.defaults.stateDuration 11078 * 11079 * @example 11080 * $(document).ready( function() { 11081 * $('#example').dataTable( { 11082 * "stateDuration": 60*60*24; // 1 day 11083 * } ); 11084 * } ) 11085 */ 11086 "iStateDuration": 7200, 11087 11088 11089 /** 11090 * When enabled DataTables will not make a request to the server for the first 11091 * page draw - rather it will use the data already on the page (no sorting etc 11092 * will be applied to it), thus saving on an XHR at load time. `deferLoading` 11093 * is used to indicate that deferred loading is required, but it is also used 11094 * to tell DataTables how many records there are in the full table (allowing 11095 * the information element and pagination to be displayed correctly). In the case 11096 * where a filtering is applied to the table on initial load, this can be 11097 * indicated by giving the parameter as an array, where the first element is 11098 * the number of records available after filtering and the second element is the 11099 * number of records without filtering (allowing the table information element 11100 * to be shown correctly). 11101 * @type int | array 11102 * @default null 11103 * 11104 * @dtopt Options 11105 * @name DataTable.defaults.deferLoading 11106 * 11107 * @example 11108 * // 57 records available in the table, no filtering applied 11109 * $(document).ready( function() { 11110 * $('#example').dataTable( { 11111 * "serverSide": true, 11112 * "ajax": "scripts/server_processing.php", 11113 * "deferLoading": 57 11114 * } ); 11115 * } ); 11116 * 11117 * @example 11118 * // 57 records after filtering, 100 without filtering (an initial filter applied) 11119 * $(document).ready( function() { 11120 * $('#example').dataTable( { 11121 * "serverSide": true, 11122 * "ajax": "scripts/server_processing.php", 11123 * "deferLoading": [ 57, 100 ], 11124 * "search": { 11125 * "search": "my_filter" 11126 * } 11127 * } ); 11128 * } ); 11129 */ 11130 "iDeferLoading": null, 11131 11132 11133 /** 11134 * Number of rows to display on a single page when using pagination. If 11135 * feature enabled (`lengthChange`) then the end user will be able to override 11136 * this to a custom setting using a pop-up menu. 11137 * @type int 11138 * @default 10 11139 * 11140 * @dtopt Options 11141 * @name DataTable.defaults.pageLength 11142 * 11143 * @example 11144 * $(document).ready( function() { 11145 * $('#example').dataTable( { 11146 * "pageLength": 50 11147 * } ); 11148 * } ) 11149 */ 11150 "iDisplayLength": 10, 11151 11152 11153 /** 11154 * Define the starting point for data display when using DataTables with 11155 * pagination. Note that this parameter is the number of records, rather than 11156 * the page number, so if you have 10 records per page and want to start on 11157 * the third page, it should be "20". 11158 * @type int 11159 * @default 0 11160 * 11161 * @dtopt Options 11162 * @name DataTable.defaults.displayStart 11163 * 11164 * @example 11165 * $(document).ready( function() { 11166 * $('#example').dataTable( { 11167 * "displayStart": 20 11168 * } ); 11169 * } ) 11170 */ 11171 "iDisplayStart": 0, 11172 11173 11174 /** 11175 * By default DataTables allows keyboard navigation of the table (sorting, paging, 11176 * and filtering) by adding a `tabindex` attribute to the required elements. This 11177 * allows you to tab through the controls and press the enter key to activate them. 11178 * The tabindex is default 0, meaning that the tab follows the flow of the document. 11179 * You can overrule this using this parameter if you wish. Use a value of -1 to 11180 * disable built-in keyboard navigation. 11181 * @type int 11182 * @default 0 11183 * 11184 * @dtopt Options 11185 * @name DataTable.defaults.tabIndex 11186 * 11187 * @example 11188 * $(document).ready( function() { 11189 * $('#example').dataTable( { 11190 * "tabIndex": 1 11191 * } ); 11192 * } ); 11193 */ 11194 "iTabIndex": 0, 11195 11196 11197 /** 11198 * Classes that DataTables assigns to the various components and features 11199 * that it adds to the HTML table. This allows classes to be configured 11200 * during initialisation in addition to through the static 11201 * {@link DataTable.ext.oStdClasses} object). 11202 * @namespace 11203 * @name DataTable.defaults.classes 11204 */ 11205 "oClasses": {}, 11206 11207 11208 /** 11209 * All strings that DataTables uses in the user interface that it creates 11210 * are defined in this object, allowing you to modified them individually or 11211 * completely replace them all as required. 11212 * @namespace 11213 * @name DataTable.defaults.language 11214 */ 11215 "oLanguage": { 11216 /** 11217 * Strings that are used for WAI-ARIA labels and controls only (these are not 11218 * actually visible on the page, but will be read by screenreaders, and thus 11219 * must be internationalised as well). 11220 * @namespace 11221 * @name DataTable.defaults.language.aria 11222 */ 11223 "oAria": { 11224 /** 11225 * ARIA label that is added to the table headers when the column may be 11226 * sorted ascending by activing the column (click or return when focused). 11227 * Note that the column header is prefixed to this string. 11228 * @type string 11229 * @default : activate to sort column ascending 11230 * 11231 * @dtopt Language 11232 * @name DataTable.defaults.language.aria.sortAscending 11233 * 11234 * @example 11235 * $(document).ready( function() { 11236 * $('#example').dataTable( { 11237 * "language": { 11238 * "aria": { 11239 * "sortAscending": " - click/return to sort ascending" 11240 * } 11241 * } 11242 * } ); 11243 * } ); 11244 */ 11245 "sSortAscending": ": activate to sort column ascending", 11246 11247 /** 11248 * ARIA label that is added to the table headers when the column may be 11249 * sorted descending by activing the column (click or return when focused). 11250 * Note that the column header is prefixed to this string. 11251 * @type string 11252 * @default : activate to sort column ascending 11253 * 11254 * @dtopt Language 11255 * @name DataTable.defaults.language.aria.sortDescending 11256 * 11257 * @example 11258 * $(document).ready( function() { 11259 * $('#example').dataTable( { 11260 * "language": { 11261 * "aria": { 11262 * "sortDescending": " - click/return to sort descending" 11263 * } 11264 * } 11265 * } ); 11266 * } ); 11267 */ 11268 "sSortDescending": ": activate to sort column descending" 11269 }, 11270 11271 /** 11272 * Pagination string used by DataTables for the built-in pagination 11273 * control types. 11274 * @namespace 11275 * @name DataTable.defaults.language.paginate 11276 */ 11277 "oPaginate": { 11278 /** 11279 * Text to use when using the 'full_numbers' type of pagination for the 11280 * button to take the user to the first page. 11281 * @type string 11282 * @default First 11283 * 11284 * @dtopt Language 11285 * @name DataTable.defaults.language.paginate.first 11286 * 11287 * @example 11288 * $(document).ready( function() { 11289 * $('#example').dataTable( { 11290 * "language": { 11291 * "paginate": { 11292 * "first": "First page" 11293 * } 11294 * } 11295 * } ); 11296 * } ); 11297 */ 11298 "sFirst": "First", 11299 11300 11301 /** 11302 * Text to use when using the 'full_numbers' type of pagination for the 11303 * button to take the user to the last page. 11304 * @type string 11305 * @default Last 11306 * 11307 * @dtopt Language 11308 * @name DataTable.defaults.language.paginate.last 11309 * 11310 * @example 11311 * $(document).ready( function() { 11312 * $('#example').dataTable( { 11313 * "language": { 11314 * "paginate": { 11315 * "last": "Last page" 11316 * } 11317 * } 11318 * } ); 11319 * } ); 11320 */ 11321 "sLast": "Last", 11322 11323 11324 /** 11325 * Text to use for the 'next' pagination button (to take the user to the 11326 * next page). 11327 * @type string 11328 * @default Next 11329 * 11330 * @dtopt Language 11331 * @name DataTable.defaults.language.paginate.next 11332 * 11333 * @example 11334 * $(document).ready( function() { 11335 * $('#example').dataTable( { 11336 * "language": { 11337 * "paginate": { 11338 * "next": "Next page" 11339 * } 11340 * } 11341 * } ); 11342 * } ); 11343 */ 11344 "sNext": "Next", 11345 11346 11347 /** 11348 * Text to use for the 'previous' pagination button (to take the user to 11349 * the previous page). 11350 * @type string 11351 * @default Previous 11352 * 11353 * @dtopt Language 11354 * @name DataTable.defaults.language.paginate.previous 11355 * 11356 * @example 11357 * $(document).ready( function() { 11358 * $('#example').dataTable( { 11359 * "language": { 11360 * "paginate": { 11361 * "previous": "Previous page" 11362 * } 11363 * } 11364 * } ); 11365 * } ); 11366 */ 11367 "sPrevious": "Previous" 11368 }, 11369 11370 /** 11371 * This string is shown in preference to `zeroRecords` when the table is 11372 * empty of data (regardless of filtering). Note that this is an optional 11373 * parameter - if it is not given, the value of `zeroRecords` will be used 11374 * instead (either the default or given value). 11375 * @type string 11376 * @default No data available in table 11377 * 11378 * @dtopt Language 11379 * @name DataTable.defaults.language.emptyTable 11380 * 11381 * @example 11382 * $(document).ready( function() { 11383 * $('#example').dataTable( { 11384 * "language": { 11385 * "emptyTable": "No data available in table" 11386 * } 11387 * } ); 11388 * } ); 11389 */ 11390 "sEmptyTable": "No data available in table", 11391 11392 11393 /** 11394 * This string gives information to the end user about the information 11395 * that is current on display on the page. The following tokens can be 11396 * used in the string and will be dynamically replaced as the table 11397 * display updates. This tokens can be placed anywhere in the string, or 11398 * removed as needed by the language requires: 11399 * 11400 * * `\_START\_` - Display index of the first record on the current page 11401 * * `\_END\_` - Display index of the last record on the current page 11402 * * `\_TOTAL\_` - Number of records in the table after filtering 11403 * * `\_MAX\_` - Number of records in the table without filtering 11404 * * `\_PAGE\_` - Current page number 11405 * * `\_PAGES\_` - Total number of pages of data in the table 11406 * 11407 * @type string 11408 * @default Showing _START_ to _END_ of _TOTAL_ entries 11409 * 11410 * @dtopt Language 11411 * @name DataTable.defaults.language.info 11412 * 11413 * @example 11414 * $(document).ready( function() { 11415 * $('#example').dataTable( { 11416 * "language": { 11417 * "info": "Showing page _PAGE_ of _PAGES_" 11418 * } 11419 * } ); 11420 * } ); 11421 */ 11422 "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries", 11423 11424 11425 /** 11426 * Display information string for when the table is empty. Typically the 11427 * format of this string should match `info`. 11428 * @type string 11429 * @default Showing 0 to 0 of 0 entries 11430 * 11431 * @dtopt Language 11432 * @name DataTable.defaults.language.infoEmpty 11433 * 11434 * @example 11435 * $(document).ready( function() { 11436 * $('#example').dataTable( { 11437 * "language": { 11438 * "infoEmpty": "No entries to show" 11439 * } 11440 * } ); 11441 * } ); 11442 */ 11443 "sInfoEmpty": "Showing 0 to 0 of 0 entries", 11444 11445 11446 /** 11447 * When a user filters the information in a table, this string is appended 11448 * to the information (`info`) to give an idea of how strong the filtering 11449 * is. The variable _MAX_ is dynamically updated. 11450 * @type string 11451 * @default (filtered from _MAX_ total entries) 11452 * 11453 * @dtopt Language 11454 * @name DataTable.defaults.language.infoFiltered 11455 * 11456 * @example 11457 * $(document).ready( function() { 11458 * $('#example').dataTable( { 11459 * "language": { 11460 * "infoFiltered": " - filtering from _MAX_ records" 11461 * } 11462 * } ); 11463 * } ); 11464 */ 11465 "sInfoFiltered": "(filtered from _MAX_ total entries)", 11466 11467 11468 /** 11469 * If can be useful to append extra information to the info string at times, 11470 * and this variable does exactly that. This information will be appended to 11471 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are 11472 * being used) at all times. 11473 * @type string 11474 * @default <i>Empty string</i> 11475 * 11476 * @dtopt Language 11477 * @name DataTable.defaults.language.infoPostFix 11478 * 11479 * @example 11480 * $(document).ready( function() { 11481 * $('#example').dataTable( { 11482 * "language": { 11483 * "infoPostFix": "All records shown are derived from real information." 11484 * } 11485 * } ); 11486 * } ); 11487 */ 11488 "sInfoPostFix": "", 11489 11490 11491 /** 11492 * This decimal place operator is a little different from the other 11493 * language options since DataTables doesn't output floating point 11494 * numbers, so it won't ever use this for display of a number. Rather, 11495 * what this parameter does is modify the sort methods of the table so 11496 * that numbers which are in a format which has a character other than 11497 * a period (`.`) as a decimal place will be sorted numerically. 11498 * 11499 * Note that numbers with different decimal places cannot be shown in 11500 * the same table and still be sortable, the table must be consistent. 11501 * However, multiple different tables on the page can use different 11502 * decimal place characters. 11503 * @type string 11504 * @default 11505 * 11506 * @dtopt Language 11507 * @name DataTable.defaults.language.decimal 11508 * 11509 * @example 11510 * $(document).ready( function() { 11511 * $('#example').dataTable( { 11512 * "language": { 11513 * "decimal": "," 11514 * "thousands": "." 11515 * } 11516 * } ); 11517 * } ); 11518 */ 11519 "sDecimal": "", 11520 11521 11522 /** 11523 * DataTables has a build in number formatter (`formatNumber`) which is 11524 * used to format large numbers that are used in the table information. 11525 * By default a comma is used, but this can be trivially changed to any 11526 * character you wish with this parameter. 11527 * @type string 11528 * @default , 11529 * 11530 * @dtopt Language 11531 * @name DataTable.defaults.language.thousands 11532 * 11533 * @example 11534 * $(document).ready( function() { 11535 * $('#example').dataTable( { 11536 * "language": { 11537 * "thousands": "'" 11538 * } 11539 * } ); 11540 * } ); 11541 */ 11542 "sThousands": ",", 11543 11544 11545 /** 11546 * Detail the action that will be taken when the drop down menu for the 11547 * pagination length option is changed. The '_MENU_' variable is replaced 11548 * with a default select list of 10, 25, 50 and 100, and can be replaced 11549 * with a custom select box if required. 11550 * @type string 11551 * @default Show _MENU_ entries 11552 * 11553 * @dtopt Language 11554 * @name DataTable.defaults.language.lengthMenu 11555 * 11556 * @example 11557 * // Language change only 11558 * $(document).ready( function() { 11559 * $('#example').dataTable( { 11560 * "language": { 11561 * "lengthMenu": "Display _MENU_ records" 11562 * } 11563 * } ); 11564 * } ); 11565 * 11566 * @example 11567 * // Language and options change 11568 * $(document).ready( function() { 11569 * $('#example').dataTable( { 11570 * "language": { 11571 * "lengthMenu": 'Display <select>'+ 11572 * '<option value="10">10</option>'+ 11573 * '<option value="20">20</option>'+ 11574 * '<option value="30">30</option>'+ 11575 * '<option value="40">40</option>'+ 11576 * '<option value="50">50</option>'+ 11577 * '<option value="-1">All</option>'+ 11578 * '</select> records' 11579 * } 11580 * } ); 11581 * } ); 11582 */ 11583 "sLengthMenu": "Show _MENU_ entries", 11584 11585 11586 /** 11587 * When using Ajax sourced data and during the first draw when DataTables is 11588 * gathering the data, this message is shown in an empty row in the table to 11589 * indicate to the end user the the data is being loaded. Note that this 11590 * parameter is not used when loading data by server-side processing, just 11591 * Ajax sourced data with client-side processing. 11592 * @type string 11593 * @default Loading... 11594 * 11595 * @dtopt Language 11596 * @name DataTable.defaults.language.loadingRecords 11597 * 11598 * @example 11599 * $(document).ready( function() { 11600 * $('#example').dataTable( { 11601 * "language": { 11602 * "loadingRecords": "Please wait - loading..." 11603 * } 11604 * } ); 11605 * } ); 11606 */ 11607 "sLoadingRecords": "Loading...", 11608 11609 11610 /** 11611 * Text which is displayed when the table is processing a user action 11612 * (usually a sort command or similar). 11613 * @type string 11614 *
11614 @default Processing... 11615 * 11616 * @dtopt Language 11617 * @name DataTable.defaults.language.processing 11618 * 11619 * @example 11620 * $(document).ready( function() { 11621 * $('#example').dataTable( { 11622 * "language": { 11623 * "processing": "DataTables is currently busy" 11624 * } 11625 * } ); 11626 * } ); 11627 */ 11628 "sProcessing": "Processing...
vendor: 24,082 bytes, lines 11628-12357
11628", 11629 11630 11631 /** 11632 * Details the actions that will be taken when the user types into the 11633 * filtering input text box. The variable "_INPUT_", if used in the string, 11634 * is replaced with the HTML text box for the filtering input allowing 11635 * control over where it appears in the string. If "_INPUT_" is not given 11636 * then the input box is appended to the string automatically. 11637 * @type string 11638 * @default Search: 11639 * 11640 * @dtopt Language 11641 * @name DataTable.defaults.language.search 11642 * 11643 * @example 11644 * // Input text box will be appended at the end automatically 11645 * $(document).ready( function() { 11646 * $('#example').dataTable( { 11647 * "language": { 11648 * "search": "Filter records:" 11649 * } 11650 * } ); 11651 * } ); 11652 * 11653 * @example 11654 * // Specify where the filter should appear 11655 * $(document).ready( function() { 11656 * $('#example').dataTable( { 11657 * "language": { 11658 * "search": "Apply filter _INPUT_ to table" 11659 * } 11660 * } ); 11661 * } ); 11662 */ 11663 "sSearch": "Search:", 11664 11665 11666 /** 11667 * Assign a `placeholder` attribute to the search `input` element 11668 * @type string 11669 * @default 11670 * 11671 * @dtopt Language 11672 * @name DataTable.defaults.language.searchPlaceholder 11673 */ 11674 "sSearchPlaceholder": "", 11675 11676 11677 /** 11678 * All of the language information can be stored in a file on the 11679 * server-side, which DataTables will look up if this parameter is passed. 11680 * It must store the URL of the language file, which is in a JSON format, 11681 * and the object has the same properties as the oLanguage object in the 11682 * initialiser object (i.e. the above parameters). Please refer to one of 11683 * the example language files to see how this works in action. 11684 * @type string 11685 * @default <i>Empty string - i.e. disabled</i> 11686 * 11687 * @dtopt Language 11688 * @name DataTable.defaults.language.url 11689 * 11690 * @example 11691 * $(document).ready( function() { 11692 * $('#example').dataTable( { 11693 * "language": { 11694 * "url": "http://www.sprymedia.co.uk/dataTables/lang.txt" 11695 * } 11696 * } ); 11697 * } ); 11698 */ 11699 "sUrl": "", 11700 11701 11702 /** 11703 * Text shown inside the table records when the is no information to be 11704 * displayed after filtering. `emptyTable` is shown when there is simply no 11705 * information in the table at all (regardless of filtering). 11706 * @type string 11707 * @default No matching records found 11708 * 11709 * @dtopt Language 11710 * @name DataTable.defaults.language.zeroRecords 11711 * 11712 * @example 11713 * $(document).ready( function() { 11714 * $('#example').dataTable( { 11715 * "language": { 11716 * "zeroRecords": "No records to display" 11717 * } 11718 * } ); 11719 * } ); 11720 */ 11721 "sZeroRecords": "No matching records found" 11722 }, 11723 11724 11725 /** 11726 * This parameter allows you to have define the global filtering state at 11727 * initialisation time. As an object the `search` parameter must be 11728 * defined, but all other parameters are optional. When `regex` is true, 11729 * the search string will be treated as a regular expression, when false 11730 * (default) it will be treated as a straight string. When `smart` 11731 * DataTables will use it's smart filtering methods (to word match at 11732 * any point in the data), when false this will not be done. 11733 * @namespace 11734 * @extends DataTable.models.oSearch 11735 * 11736 * @dtopt Options 11737 * @name DataTable.defaults.search 11738 * 11739 * @example 11740 * $(document).ready( function() { 11741 * $('#example').dataTable( { 11742 * "search": {"search": "Initial search"} 11743 * } ); 11744 * } ) 11745 */ 11746 "oSearch": $.extend( {}, DataTable.models.oSearch ), 11747 11748 11749 /** 11750 * __Deprecated__ The functionality provided by this parameter has now been 11751 * superseded by that provided through `ajax`, which should be used instead. 11752 * 11753 * By default DataTables will look for the property `data` (or `aaData` for 11754 * compatibility with DataTables 1.9-) when obtaining data from an Ajax 11755 * source or for server-side processing - this parameter allows that 11756 * property to be changed. You can use Javascript dotted object notation to 11757 * get a data source for multiple levels of nesting. 11758 * @type string 11759 * @default data 11760 * 11761 * @dtopt Options 11762 * @dtopt Server-side 11763 * @name DataTable.defaults.ajaxDataProp 11764 * 11765 * @deprecated 1.10. Please use `ajax` for this functionality now. 11766 */ 11767 "sAjaxDataProp": "data", 11768 11769 11770 /** 11771 * __Deprecated__ The functionality provided by this parameter has now been 11772 * superseded by that provided through `ajax`, which should be used instead. 11773 * 11774 * You can instruct DataTables to load data from an external 11775 * source using this parameter (use aData if you want to pass data in you 11776 * already have). Simply provide a url a JSON object can be obtained from. 11777 * @type string 11778 * @default null 11779 * 11780 * @dtopt Options 11781 * @dtopt Server-side 11782 * @name DataTable.defaults.ajaxSource 11783 * 11784 * @deprecated 1.10. Please use `ajax` for this functionality now. 11785 */ 11786 "sAjaxSource": null, 11787 11788 11789 /** 11790 * This initialisation variable allows you to specify exactly where in the 11791 * DOM you want DataTables to inject the various controls it adds to the page 11792 * (for example you might want the pagination controls at the top of the 11793 * table). DIV elements (with or without a custom class) can also be added to 11794 * aid styling. The follow syntax is used: 11795 * <ul> 11796 * <li>The following options are allowed: 11797 * <ul> 11798 * <li>'l' - Length changing</li> 11799 * <li>'f' - Filtering input</li> 11800 * <li>'t' - The table!</li> 11801 * <li>'i' - Information</li> 11802 * <li>'p' - Pagination</li> 11803 * <li>'r' - pRocessing</li> 11804 * </ul> 11805 * </li> 11806 * <li>The following constants are allowed: 11807 * <ul> 11808 * <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li> 11809 * <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li> 11810 * </ul> 11811 * </li> 11812 * <li>The following syntax is expected: 11813 * <ul> 11814 * <li>'<' and '>' - div elements</li> 11815 * <li>'<"class" and '>' - div with a class</li> 11816 * <li>'<"#id" and '>' - div with an ID</li> 11817 * </ul> 11818 * </li> 11819 * <li>Examples: 11820 * <ul> 11821 * <li>'<"wrapper"flipt>'</li> 11822 * <li>'<lf<t>ip>'</li> 11823 * </ul> 11824 * </li> 11825 * </ul> 11826 * @type string 11827 * @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b> 11828 * <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i> 11829 * 11830 * @dtopt Options 11831 * @name DataTable.defaults.dom 11832 * 11833 * @example 11834 * $(document).ready( function() { 11835 * $('#example').dataTable( { 11836 * "dom": '<"top"i>rt<"bottom"flp><"clear">' 11837 * } ); 11838 * } ); 11839 */ 11840 "sDom": "lfrtip", 11841 11842 11843 /** 11844 * Search delay option. This will throttle full table searches that use the 11845 * DataTables provided search input element (it does not effect calls to 11846 * `dt-api search()`, providing a delay before the search is made. 11847 * @type integer 11848 * @default 0 11849 * 11850 * @dtopt Options 11851 * @name DataTable.defaults.searchDelay 11852 * 11853 * @example 11854 * $(document).ready( function() { 11855 * $('#example').dataTable( { 11856 * "searchDelay": 200 11857 * } ); 11858 * } ) 11859 */ 11860 "searchDelay": null, 11861 11862 11863 /** 11864 * DataTables features six different built-in options for the buttons to 11865 * display for pagination control: 11866 * 11867 * * `numbers` - Page number buttons only 11868 * * `simple` - 'Previous' and 'Next' buttons only 11869 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers 11870 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons 11871 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers 11872 * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers 11873 * 11874 * Further methods can be added using {@link DataTable.ext.oPagination}. 11875 * @type string 11876 * @default simple_numbers 11877 * 11878 * @dtopt Options 11879 * @name DataTable.defaults.pagingType 11880 * 11881 * @example 11882 * $(document).ready( function() { 11883 * $('#example').dataTable( { 11884 * "pagingType": "full_numbers" 11885 * } ); 11886 * } ) 11887 */ 11888 "sPaginationType": "simple_numbers", 11889 11890 11891 /** 11892 * Enable horizontal scrolling. When a table is too wide to fit into a 11893 * certain layout, or you have a large number of columns in the table, you 11894 * can enable x-scrolling to show the table in a viewport, which can be 11895 * scrolled. This property can be `true` which will allow the table to 11896 * scroll horizontally when needed, or any CSS unit, or a number (in which 11897 * case it will be treated as a pixel measurement). Setting as simply `true` 11898 * is recommended. 11899 * @type boolean|string 11900 * @default <i>blank string - i.e. disabled</i> 11901 * 11902 * @dtopt Features 11903 * @name DataTable.defaults.scrollX 11904 * 11905 * @example 11906 * $(document).ready( function() { 11907 * $('#example').dataTable( { 11908 * "scrollX": true, 11909 * "scrollCollapse": true 11910 * } ); 11911 * } ); 11912 */ 11913 "sScrollX": "", 11914 11915 11916 /** 11917 * This property can be used to force a DataTable to use more width than it 11918 * might otherwise do when x-scrolling is enabled. For example if you have a 11919 * table which requires to be well spaced, this parameter is useful for 11920 * "over-sizing" the table, and thus forcing scrolling. This property can by 11921 * any CSS unit, or a number (in which case it will be treated as a pixel 11922 * measurement). 11923 * @type string 11924 * @default <i>blank string - i.e. disabled</i> 11925 * 11926 * @dtopt Options 11927 * @name DataTable.defaults.scrollXInner 11928 * 11929 * @example 11930 * $(document).ready( function() { 11931 * $('#example').dataTable( { 11932 * "scrollX": "100%", 11933 * "scrollXInner": "110%" 11934 * } ); 11935 * } ); 11936 */ 11937 "sScrollXInner": "", 11938 11939 11940 /** 11941 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable 11942 * to the given height, and enable scrolling for any data which overflows the 11943 * current viewport. This can be used as an alternative to paging to display 11944 * a lot of data in a small area (although paging and scrolling can both be 11945 * enabled at the same time). This property can be any CSS unit, or a number 11946 * (in which case it will be treated as a pixel measurement). 11947 * @type string 11948 * @default <i>blank string - i.e. disabled</i> 11949 * 11950 * @dtopt Features 11951 * @name DataTable.defaults.scrollY 11952 * 11953 * @example 11954 * $(document).ready( function() { 11955 * $('#example').dataTable( { 11956 * "scrollY": "200px", 11957 * "paginate": false 11958 * } ); 11959 * } ); 11960 */ 11961 "sScrollY": "", 11962 11963 11964 /** 11965 * __Deprecated__ The functionality provided by this parameter has now been 11966 * superseded by that provided through `ajax`, which should be used instead. 11967 * 11968 * Set the HTTP method that is used to make the Ajax call for server-side 11969 * processing or Ajax sourced data. 11970 * @type string 11971 * @default GET 11972 * 11973 * @dtopt Options 11974 * @dtopt Server-side 11975 * @name DataTable.defaults.serverMethod 11976 * 11977 * @deprecated 1.10. Please use `ajax` for this functionality now. 11978 */ 11979 "sServerMethod": "GET", 11980 11981 11982 /** 11983 * DataTables makes use of renderers when displaying HTML elements for 11984 * a table. These renderers can be added or modified by plug-ins to 11985 * generate suitable mark-up for a site. For example the Bootstrap 11986 * integration plug-in for DataTables uses a paging button renderer to 11987 * display pagination buttons in the mark-up required by Bootstrap. 11988 * 11989 * For further information about the renderers available see 11990 * DataTable.ext.renderer 11991 * @type string|object 11992 * @default null 11993 * 11994 * @name DataTable.defaults.renderer 11995 * 11996 */ 11997 "renderer": null, 11998 11999 12000 /** 12001 * Set the data property name that DataTables should use to get a row's id 12002 * to set as the `id` property in the node. 12003 * @type string 12004 * @default DT_RowId 12005 * 12006 * @name DataTable.defaults.rowId 12007 */ 12008 "rowId": "DT_RowId" 12009 }; 12010 12011 _fnHungarianMap( DataTable.defaults ); 12012 12013 12014 12015 /* 12016 * Developer note - See note in model.defaults.js about the use of Hungarian 12017 * notation and camel case. 12018 */ 12019 12020 /** 12021 * Column options that can be given to DataTables at initialisation time. 12022 * @namespace 12023 */ 12024 DataTable.defaults.column = { 12025 /** 12026 * Define which column(s) an order will occur on for this column. This 12027 * allows a column's ordering to take multiple columns into account when 12028 * doing a sort or use the data from a different column. For example first 12029 * name / last name columns make sense to do a multi-column sort over the 12030 * two columns. 12031 * @type array|int 12032 * @default null <i>Takes the value of the column index automatically</i> 12033 * 12034 * @name DataTable.defaults.column.orderData 12035 * @dtopt Columns 12036 * 12037 * @example 12038 * // Using `columnDefs` 12039 * $(document).ready( function() { 12040 * $('#example').dataTable( { 12041 * "columnDefs": [ 12042 * { "orderData": [ 0, 1 ], "targets": [ 0 ] }, 12043 * { "orderData": [ 1, 0 ], "targets": [ 1 ] }, 12044 * { "orderData": 2, "targets": [ 2 ] } 12045 * ] 12046 * } ); 12047 * } ); 12048 * 12049 * @example 12050 * // Using `columns` 12051 * $(document).ready( function() { 12052 * $('#example').dataTable( { 12053 * "columns": [ 12054 * { "orderData": [ 0, 1 ] }, 12055 * { "orderData": [ 1, 0 ] }, 12056 * { "orderData": 2 }, 12057 * null, 12058 * null 12059 * ] 12060 * } ); 12061 * } ); 12062 */ 12063 "aDataSort": null, 12064 "iDataSort": -1, 12065 12066 12067 /** 12068 * You can control the default ordering direction, and even alter the 12069 * behaviour of the sort handler (i.e. only allow ascending ordering etc) 12070 * using this parameter. 12071 * @type array 12072 * @default [ 'asc', 'desc' ] 12073 * 12074 * @name DataTable.defaults.column.orderSequence 12075 * @dtopt Columns 12076 * 12077 * @example 12078 * // Using `columnDefs` 12079 * $(document).ready( function() { 12080 * $('#example').dataTable( { 12081 * "columnDefs": [ 12082 * { "orderSequence": [ "asc" ], "targets": [ 1 ] }, 12083 * { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] }, 12084 * { "orderSequence": [ "desc" ], "targets": [ 3 ] } 12085 * ] 12086 * } ); 12087 * } ); 12088 * 12089 * @example 12090 * // Using `columns` 12091 * $(document).ready( function() { 12092 * $('#example').dataTable( { 12093 * "columns": [ 12094 * null, 12095 * { "orderSequence": [ "asc" ] }, 12096 * { "orderSequence": [ "desc", "asc", "asc" ] }, 12097 * { "orderSequence": [ "desc" ] }, 12098 * null 12099 * ] 12100 * } ); 12101 * } ); 12102 */ 12103 "asSorting": [ 'asc', 'desc' ], 12104 12105 12106 /** 12107 * Enable or disable filtering on the data in this column. 12108 * @type boolean 12109 * @default true 12110 * 12111 * @name DataTable.defaults.column.searchable 12112 * @dtopt Columns 12113 * 12114 * @example 12115 * // Using `columnDefs` 12116 * $(document).ready( function() { 12117 * $('#example').dataTable( { 12118 * "columnDefs": [ 12119 * { "searchable": false, "targets": [ 0 ] } 12120 * ] } ); 12121 * } ); 12122 * 12123 * @example 12124 * // Using `columns` 12125 * $(document).ready( function() { 12126 * $('#example').dataTable( { 12127 * "columns": [ 12128 * { "searchable": false }, 12129 * null, 12130 * null, 12131 * null, 12132 * null 12133 * ] } ); 12134 * } ); 12135 */ 12136 "bSearchable": true, 12137 12138 12139 /** 12140 * Enable or disable ordering on this column. 12141 * @type boolean 12142 * @default true 12143 * 12144 * @name DataTable.defaults.column.orderable 12145 * @dtopt Columns 12146 * 12147 * @example 12148 * // Using `columnDefs` 12149 * $(document).ready( function() { 12150 * $('#example').dataTable( { 12151 * "columnDefs": [ 12152 * { "orderable": false, "targets": [ 0 ] } 12153 * ] } ); 12154 * } ); 12155 * 12156 * @example 12157 * // Using `columns` 12158 * $(document).ready( function() { 12159 * $('#example').dataTable( { 12160 * "columns": [ 12161 * { "orderable": false }, 12162 * null, 12163 * null, 12164 * null, 12165 * null 12166 * ] } ); 12167 * } ); 12168 */ 12169 "bSortable": true, 12170 12171 12172 /** 12173 * Enable or disable the display of this column. 12174 * @type boolean 12175 * @default true 12176 * 12177 * @name DataTable.defaults.column.visible 12178 * @dtopt Columns 12179 * 12180 * @example 12181 * // Using `columnDefs` 12182 * $(document).ready( function() { 12183 * $('#example').dataTable( { 12184 * "columnDefs": [ 12185 * { "visible": false, "targets": [ 0 ] } 12186 * ] } ); 12187 * } ); 12188 * 12189 * @example 12190 * // Using `columns` 12191 * $(document).ready( function() { 12192 * $('#example').dataTable( { 12193 * "columns": [ 12194 * { "visible": false }, 12195 * null, 12196 * null, 12197 * null, 12198 * null 12199 * ] } ); 12200 * } ); 12201 */ 12202 "bVisible": true, 12203 12204 12205 /** 12206 * Developer definable function that is called whenever a cell is created (Ajax source, 12207 * etc) or processed for input (DOM source). This can be used as a compliment to mRender 12208 * allowing you to modify the DOM element (add background colour for example) when the 12209 * element is available. 12210 * @type function 12211 * @param {element} td The TD node that has been created 12212 * @param {*} cellData The Data for the cell 12213 * @param {array|object} rowData The data for the whole row 12214 * @param {int} row The row index for the aoData data store 12215 * @param {int} col The column index for aoColumns 12216 * 12217 * @name DataTable.defaults.column.createdCell 12218 * @dtopt Columns 12219 * 12220 * @example 12221 * $(document).ready( function() { 12222 * $('#example').dataTable( { 12223 * "columnDefs": [ { 12224 * "targets": [3], 12225 * "createdCell": function (td, cellData, rowData, row, col) { 12226 * if ( cellData == "1.7" ) { 12227 * $(td).css('color', 'blue') 12228 * } 12229 * } 12230 * } ] 12231 * }); 12232 * } ); 12233 */ 12234 "fnCreatedCell": null, 12235 12236 12237 /** 12238 * This parameter has been replaced by `data` in DataTables to ensure naming 12239 * consistency. `dataProp` can still be used, as there is backwards 12240 * compatibility in DataTables for this option, but it is strongly 12241 * recommended that you use `data` in preference to `dataProp`. 12242 * @name DataTable.defaults.column.dataProp 12243 */ 12244 12245 12246 /** 12247 * This property can be used to read data from any data source property, 12248 * including deeply nested objects / properties. `data` can be given in a 12249 * number of different ways which effect its behaviour: 12250 * 12251 * * `integer` - treated as an array index for the data source. This is the 12252 * default that DataTables uses (incrementally increased for each column). 12253 * * `string` - read an object property from the data source. There are 12254 * three 'special' options that can be used in the string to alter how 12255 * DataTables reads the data from the source object: 12256 * * `.` - Dotted Javascript notation. Just as you use a `.` in 12257 * Javascript to read from nested objects, so to can the options 12258 * specified in `data`. For example: `browser.version` or 12259 * `browser.name`. If your object parameter name contains a period, use 12260 * `\\` to escape it - i.e. `first\\.name`. 12261 * * `[]` - Array notation. DataTables can automatically combine data 12262 * from and array source, joining the data with the characters provided 12263 * between the two brackets. For example: `name[, ]` would provide a 12264 * comma-space separated list from the source array. If no characters 12265 * are provided between the brackets, the original array source is 12266 * returned. 12267 * * `()` - Function notation. Adding `()` to the end of a parameter will 12268 * execute a function of the name given. For example: `browser()` for a 12269 * simple function on the data source, `browser.version()` for a 12270 * function in a nested property or even `browser().version` to get an 12271 * object property if the function called returns an object. Note that 12272 * function notation is recommended for use in `render` rather than 12273 * `data` as it is much simpler to use as a renderer. 12274 * * `null` - use the original data source for the row rather than plucking 12275 * data directly from it. This action has effects on two other 12276 * initialisation options: 12277 * * `defaultContent` - When null is given as the `data` option and 12278 * `defaultContent` is specified for the column, the value defined by 12279 * `defaultContent` will be used for the cell. 12280 * * `render` - When null is used for the `data` option and the `render` 12281 * option is specified for the column, the whole data source for the 12282 * row is used for the renderer. 12283 * * `function` - the function given will be executed whenever DataTables 12284 * needs to set or get the data for a cell in the column. The function 12285 * takes three parameters: 12286 * * Parameters: 12287 * * `{array|object}` The data source for the row 12288 * * `{string}` The type call data requested - this will be 'set' when 12289 * setting data or 'filter', 'display', 'type', 'sort' or undefined 12290 * when gathering data. Note that when `undefined` is given for the 12291 * type DataTables expects to get the raw data for the object back< 12292 * * `{*}` Data to set when the second parameter is 'set'. 12293 * * Return: 12294 * * The return value from the function is not required when 'set' is 12295 * the type of call, but otherwise the return is what will be used 12296 * for the data requested. 12297 * 12298 * Note that `data` is a getter and setter option. If you just require 12299 * formatting of data for output, you will likely want to use `render` which 12300 * is simply a getter and thus simpler to use. 12301 * 12302 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The 12303 * name change reflects the flexibility of this property and is consistent 12304 * with the naming of mRender. If 'mDataProp' is given, then it will still 12305 * be used by DataTables, as it automatically maps the old name to the new 12306 * if required. 12307 * 12308 * @type string|int|function|null 12309 * @default null <i>Use automatically calculated column index</i> 12310 * 12311 * @name DataTable.defaults.column.data 12312 * @dtopt Columns 12313 * 12314 * @example 12315 * // Read table data from objects 12316 * // JSON structure for each row: 12317 * // { 12318 * // "engine": {value}, 12319 * // "browser": {value}, 12320 * // "platform": {value}, 12321 * // "version": {value}, 12322 * // "grade": {value} 12323 * // } 12324 * $(document).ready( function() { 12325 * $('#example').dataTable( { 12326 * "ajaxSource": "sources/objects.txt", 12327 * "columns": [ 12328 * { "data": "engine" }, 12329 * { "data": "browser" }, 12330 * { "data": "platform" }, 12331 * { "data": "version" }, 12332 * { "data": "grade" } 12333 * ] 12334 * } ); 12335 * } ); 12336 * 12337 * @example 12338 * // Read information from deeply nested objects 12339 * // JSON structure for each row: 12340 * // { 12341 * // "engine": {value}, 12342 * // "browser": {value}, 12343 * // "platform": { 12344 * // "inner": {value} 12345 * // }, 12346 * // "details": [ 12347 * // {value}, {value} 12348 * // ] 12349 * // } 12350 * $(document).ready( function() { 12351 * $('#example').dataTable( { 12352 * "ajaxSource": "sources/deep.txt", 12353 * "columns": [ 12354 * { "data": "engine" }, 12355 * { "data": "browser" }, 12356 * { "data": "platform.inner" }, 12357 * { "data": "
12357platform.details.0" }, 12358 * { "data": "platform.details.1" } 12359 * ] 12360 * } ); 12361 * } ); 12362 * 12363 * @example 12364 * // Using `data` as a function to provide different information for 12365 * // sorting, filtering and display. In this case, currency (price) 12366 * $(document).ready( function() { 12367 * $('#example').dataTable( { 12368 * "columnDefs": [ { 12369 * "targets": [ 0 ], 12370 * "data": function ( source, type, val ) { 12371 * if (type === 'set') { 12372 * source.price = val; 12373 * // Store the computed dis
vendor: 18,284 bytes, lines 12373-12922
12373lay and filter values for efficiency 12374 * source.price_display = val=="" ? "" : "$"+numberFormat(val); 12375 * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val; 12376 * return; 12377 * } 12378 * else if (type === 'display') { 12379 * return source.price_display; 12380 * } 12381 * else if (type === 'filter') { 12382 * return source.price_filter; 12383 * } 12384 * // 'sort', 'type' and undefined all just use the integer 12385 * return source.price; 12386 * } 12387 * } ] 12388 * } ); 12389 * } ); 12390 * 12391 * @example 12392 * // Using default content 12393 * $(document).ready( function() { 12394 * $('#example').dataTable( { 12395 * "columnDefs": [ { 12396 * "targets": [ 0 ], 12397 * "data": null, 12398 * "defaultContent": "Click to edit" 12399 * } ] 12400 * } ); 12401 * } ); 12402 * 12403 * @example 12404 * // Using array notation - outputting a list from an array 12405 * $(document).ready( function() { 12406 * $('#example').dataTable( { 12407 * "columnDefs": [ { 12408 * "targets": [ 0 ], 12409 * "data": "name[, ]" 12410 * } ] 12411 * } ); 12412 * } ); 12413 * 12414 */ 12415 "mData": null, 12416 12417 12418 /** 12419 * This property is the rendering partner to `data` and it is suggested that 12420 * when you want to manipulate data for display (including filtering, 12421 * sorting etc) without altering the underlying data for the table, use this 12422 * property. `render` can be considered to be the the read only companion to 12423 * `data` which is read / write (then as such more complex). Like `data` 12424 * this option can be given in a number of different ways to effect its 12425 * behaviour: 12426 * 12427 * * `integer` - treated as an array index for the data source. This is the 12428 * default that DataTables uses (incrementally increased for each column). 12429 * * `string` - read an object property from the data source. There are 12430 * three 'special' options that can be used in the string to alter how 12431 * DataTables reads the data from the source object: 12432 * * `.` - Dotted Javascript notation. Just as you use a `.` in 12433 * Javascript to read from nested objects, so to can the options 12434 * specified in `data`. For example: `browser.version` or 12435 * `browser.name`. If your object parameter name contains a period, use 12436 * `\\` to escape it - i.e. `first\\.name`. 12437 * * `[]` - Array notation. DataTables can automatically combine data 12438 * from and array source, joining the data with the characters provided 12439 * between the two brackets. For example: `name[, ]` would provide a 12440 * comma-space separated list from the source array. If no characters 12441 * are provided between the brackets, the original array source is 12442 * returned. 12443 * * `()` - Function notation. Adding `()` to the end of a parameter will 12444 * execute a function of the name given. For example: `browser()` for a 12445 * simple function on the data source, `browser.version()` for a 12446 * function in a nested property or even `browser().version` to get an 12447 * object property if the function called returns an object. 12448 * * `object` - use different data for the different data types requested by 12449 * DataTables ('filter', 'display', 'type' or 'sort'). The property names 12450 * of the object is the data type the property refers to and the value can 12451 * defined using an integer, string or function using the same rules as 12452 * `render` normally does. Note that an `_` option _must_ be specified. 12453 * This is the default value to use if you haven't specified a value for 12454 * the data type requested by DataTables. 12455 * * `function` - the function given will be executed whenever DataTables 12456 * needs to set or get the data for a cell in the column. The function 12457 * takes three parameters: 12458 * * Parameters: 12459 * * {array|object} The data source for the row (based on `data`) 12460 * * {string} The type call data requested - this will be 'filter', 12461 * 'display', 'type' or 'sort'. 12462 * * {array|object} The full data source for the row (not based on 12463 * `data`) 12464 * * Return: 12465 * * The return value from the function is what will be used for the 12466 * data requested. 12467 * 12468 * @type string|int|function|object|null 12469 * @default null Use the data source value. 12470 * 12471 * @name DataTable.defaults.column.render 12472 * @dtopt Columns 12473 * 12474 * @example 12475 * // Create a comma separated list from an array of objects 12476 * $(document).ready( function() { 12477 * $('#example').dataTable( { 12478 * "ajaxSource": "sources/deep.txt", 12479 * "columns": [ 12480 * { "data": "engine" }, 12481 * { "data": "browser" }, 12482 * { 12483 * "data": "platform", 12484 * "render": "[, ].name" 12485 * } 12486 * ] 12487 * } ); 12488 * } ); 12489 * 12490 * @example 12491 * // Execute a function to obtain data 12492 * $(document).ready( function() { 12493 * $('#example').dataTable( { 12494 * "columnDefs": [ { 12495 * "targets": [ 0 ], 12496 * "data": null, // Use the full data source object for the renderer's source 12497 * "render": "browserName()" 12498 * } ] 12499 * } ); 12500 * } ); 12501 * 12502 * @example 12503 * // As an object, extracting different data for the different types 12504 * // This would be used with a data source such as: 12505 * // { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" } 12506 * // Here the `phone` integer is used for sorting and type detection, while `phone_filter` 12507 * // (which has both forms) is used for filtering for if a user inputs either format, while 12508 * // the formatted phone number is the one that is shown in the table. 12509 * $(document).ready( function() { 12510 * $('#example').dataTable( { 12511 * "columnDefs": [ { 12512 * "targets": [ 0 ], 12513 * "data": null, // Use the full data source object for the renderer's source 12514 * "render": { 12515 * "_": "phone", 12516 * "filter": "phone_filter", 12517 * "display": "phone_display" 12518 * } 12519 * } ] 12520 * } ); 12521 * } ); 12522 * 12523 * @example 12524 * // Use as a function to create a link from the data source 12525 * $(document).ready( function() { 12526 * $('#example').dataTable( { 12527 * "columnDefs": [ { 12528 * "targets": [ 0 ], 12529 * "data": "download_link", 12530 * "render": function ( data, type, full ) { 12531 * return '<a href="'+data+'">Download</a>'; 12532 * } 12533 * } ] 12534 * } ); 12535 * } ); 12536 */ 12537 "mRender": null, 12538 12539 12540 /** 12541 * Change the cell type created for the column - either TD cells or TH cells. This 12542 * can be useful as TH cells have semantic meaning in the table body, allowing them 12543 * to act as a header for a row (you may wish to add scope='row' to the TH elements). 12544 * @type string 12545 * @default td 12546 * 12547 * @name DataTable.defaults.column.cellType 12548 * @dtopt Columns 12549 * 12550 * @example 12551 * // Make the first column use TH cells 12552 * $(document).ready( function() { 12553 * $('#example').dataTable( { 12554 * "columnDefs": [ { 12555 * "targets": [ 0 ], 12556 * "cellType": "th" 12557 * } ] 12558 * } ); 12559 * } ); 12560 */ 12561 "sCellType": "td", 12562 12563 12564 /** 12565 * Class to give to each cell in this column. 12566 * @type string 12567 * @default <i>Empty string</i> 12568 * 12569 * @name DataTable.defaults.column.class 12570 * @dtopt Columns 12571 * 12572 * @example 12573 * // Using `columnDefs` 12574 * $(document).ready( function() { 12575 * $('#example').dataTable( { 12576 * "columnDefs": [ 12577 * { "class": "my_class", "targets": [ 0 ] } 12578 * ] 12579 * } ); 12580 * } ); 12581 * 12582 * @example 12583 * // Using `columns` 12584 * $(document).ready( function() { 12585 * $('#example').dataTable( { 12586 * "columns": [ 12587 * { "class": "my_class" }, 12588 * null, 12589 * null, 12590 * null, 12591 * null 12592 * ] 12593 * } ); 12594 * } ); 12595 */ 12596 "sClass": "", 12597 12598 /** 12599 * When DataTables calculates the column widths to assign to each column, 12600 * it finds the longest string in each column and then constructs a 12601 * temporary table and reads the widths from that. The problem with this 12602 * is that "mmm" is much wider then "iiii", but the latter is a longer 12603 * string - thus the calculation can go wrong (doing it properly and putting 12604 * it into an DOM object and measuring that is horribly(!) slow). Thus as 12605 * a "work around" we provide this option. It will append its value to the 12606 * text that is found to be the longest string for the column - i.e. padding. 12607 * Generally you shouldn't need this! 12608 * @type string 12609 * @default <i>Empty string<i> 12610 * 12611 * @name DataTable.defaults.column.contentPadding 12612 * @dtopt Columns 12613 * 12614 * @example 12615 * // Using `columns` 12616 * $(document).ready( function() { 12617 * $('#example').dataTable( { 12618 * "columns": [ 12619 * null, 12620 * null, 12621 * null, 12622 * { 12623 * "contentPadding": "mmm" 12624 * } 12625 * ] 12626 * } ); 12627 * } ); 12628 */ 12629 "sContentPadding": "", 12630 12631 12632 /** 12633 * Allows a default value to be given for a column's data, and will be used 12634 * whenever a null data source is encountered (this can be because `data` 12635 * is set to null, or because the data source itself is null). 12636 * @type string 12637 * @default null 12638 * 12639 * @name DataTable.defaults.column.defaultContent 12640 * @dtopt Columns 12641 * 12642 * @example 12643 * // Using `columnDefs` 12644 * $(document).ready( function() { 12645 * $('#example').dataTable( { 12646 * "columnDefs": [ 12647 * { 12648 * "data": null, 12649 * "defaultContent": "Edit", 12650 * "targets": [ -1 ] 12651 * } 12652 * ] 12653 * } ); 12654 * } ); 12655 * 12656 * @example 12657 * // Using `columns` 12658 * $(document).ready( function() { 12659 * $('#example').dataTable( { 12660 * "columns": [ 12661 * null, 12662 * null, 12663 * null, 12664 * { 12665 * "data": null, 12666 * "defaultContent": "Edit" 12667 * } 12668 * ] 12669 * } ); 12670 * } ); 12671 */ 12672 "sDefaultContent": null, 12673 12674 12675 /** 12676 * This parameter is only used in DataTables' server-side processing. It can 12677 * be exceptionally useful to know what columns are being displayed on the 12678 * client side, and to map these to database fields. When defined, the names 12679 * also allow DataTables to reorder information from the server if it comes 12680 * back in an unexpected order (i.e. if you switch your columns around on the 12681 * client-side, your server-side code does not also need updating). 12682 * @type string 12683 * @default <i>Empty string</i> 12684 * 12685 * @name DataTable.defaults.column.name 12686 * @dtopt Columns 12687 * 12688 * @example 12689 * // Using `columnDefs` 12690 * $(document).ready( function() { 12691 * $('#example').dataTable( { 12692 * "columnDefs": [ 12693 * { "name": "engine", "targets": [ 0 ] }, 12694 * { "name": "browser", "targets": [ 1 ] }, 12695 * { "name": "platform", "targets": [ 2 ] }, 12696 * { "name": "version", "targets": [ 3 ] }, 12697 * { "name": "grade", "targets": [ 4 ] } 12698 * ] 12699 * } ); 12700 * } ); 12701 * 12702 * @example 12703 * // Using `columns` 12704 * $(document).ready( function() { 12705 * $('#example').dataTable( { 12706 * "columns": [ 12707 * { "name": "engine" }, 12708 * { "name": "browser" }, 12709 * { "name": "platform" }, 12710 * { "name": "version" }, 12711 * { "name": "grade" } 12712 * ] 12713 * } ); 12714 * } ); 12715 */ 12716 "sName": "", 12717 12718 12719 /** 12720 * Defines a data source type for the ordering which can be used to read 12721 * real-time information from the table (updating the internally cached 12722 * version) prior to ordering. This allows ordering to occur on user 12723 * editable elements such as form inputs. 12724 * @type string 12725 * @default std 12726 * 12727 * @name DataTable.defaults.column.orderDataType 12728 * @dtopt Columns 12729 * 12730 * @example 12731 * // Using `columnDefs` 12732 * $(document).ready( function() { 12733 * $('#example').dataTable( { 12734 * "columnDefs": [ 12735 * { "orderDataType": "dom-text", "targets": [ 2, 3 ] }, 12736 * { "type": "numeric", "targets": [ 3 ] }, 12737 * { "orderDataType": "dom-select", "targets": [ 4 ] }, 12738 * { "orderDataType": "dom-checkbox", "targets": [ 5 ] } 12739 * ] 12740 * } ); 12741 * } ); 12742 * 12743 * @example 12744 * // Using `columns` 12745 * $(document).ready( function() { 12746 * $('#example').dataTable( { 12747 * "columns": [ 12748 * null, 12749 * null, 12750 * { "orderDataType": "dom-text" }, 12751 * { "orderDataType": "dom-text", "type": "numeric" }, 12752 * { "orderDataType": "dom-select" }, 12753 * { "orderDataType": "dom-checkbox" } 12754 * ] 12755 * } ); 12756 * } ); 12757 */ 12758 "sSortDataType": "std", 12759 12760 12761 /** 12762 * The title of this column. 12763 * @type string 12764 * @default null <i>Derived from the 'TH' value for this column in the 12765 * original HTML table.</i> 12766 * 12767 * @name DataTable.defaults.column.title 12768 * @dtopt Columns 12769 * 12770 * @example 12771 * // Using `columnDefs` 12772 * $(document).ready( function() { 12773 * $('#example').dataTable( { 12774 * "columnDefs": [ 12775 * { "title": "My column title", "targets": [ 0 ] } 12776 * ] 12777 * } ); 12778 * } ); 12779 * 12780 * @example 12781 * // Using `columns` 12782 * $(document).ready( function() { 12783 * $('#example').dataTable( { 12784 * "columns": [ 12785 * { "title": "My column title" }, 12786 * null, 12787 * null, 12788 * null, 12789 * null 12790 * ] 12791 * } ); 12792 * } ); 12793 */ 12794 "sTitle": null, 12795 12796 12797 /** 12798 * The type allows you to specify how the data for this column will be 12799 * ordered. Four types (string, numeric, date and html (which will strip 12800 * HTML tags before ordering)) are currently available. Note that only date 12801 * formats understood by Javascript's Date() object will be accepted as type 12802 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string', 12803 * 'numeric', 'date' or 'html' (by default). Further types can be adding 12804 * through plug-ins. 12805 * @type string 12806 * @default null <i>Auto-detected from raw data</i> 12807 * 12808 * @name DataTable.defaults.column.type 12809 * @dtopt Columns 12810 * 12811 * @example 12812 * // Using `columnDefs` 12813 * $(document).ready( function() { 12814 * $('#example').dataTable( { 12815 * "columnDefs": [ 12816 * { "type": "html", "targets": [ 0 ] } 12817 * ] 12818 * } ); 12819 * } ); 12820 * 12821 * @example 12822 * // Using `columns` 12823 * $(document).ready( function() { 12824 * $('#example').dataTable( { 12825 * "columns": [ 12826 * { "type": "html" }, 12827 * null, 12828 * null, 12829 * null, 12830 * null 12831 * ] 12832 * } ); 12833 * } ); 12834 */ 12835 "sType": null, 12836 12837 12838 /** 12839 * Defining the width of the column, this parameter may take any CSS value 12840 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not 12841 * been given a specific width through this interface ensuring that the table 12842 * remains readable. 12843 * @type string 12844 * @default null <i>Automatic</i> 12845 * 12846 * @name DataTable.defaults.column.width 12847 * @dtopt Columns 12848 * 12849 * @example 12850 * // Using `columnDefs` 12851 * $(document).ready( function() { 12852 * $('#example').dataTable( { 12853 * "columnDefs": [ 12854 * { "width": "20%", "targets": [ 0 ] } 12855 * ] 12856 * } ); 12857 * } ); 12858 * 12859 * @example 12860 * // Using `columns` 12861 * $(document).ready( function() { 12862 * $('#example').dataTable( { 12863 * "columns": [ 12864 * { "width": "20%" }, 12865 * null, 12866 * null, 12867 * null, 12868 * null 12869 * ] 12870 * } ); 12871 * } ); 12872 */ 12873 "sWidth": null 12874 }; 12875 12876 _fnHungarianMap( DataTable.defaults.column ); 12877 12878 12879 12880 /** 12881 * DataTables settings object - this holds all the information needed for a 12882 * given table, including configuration, data and current application of the 12883 * table options. DataTables does not have a single instance for each DataTable 12884 * with the settings attached to that instance, but rather instances of the 12885 * DataTable "class" are created on-the-fly as needed (typically by a 12886 * $().dataTable() call) and the settings object is then applied to that 12887 * instance. 12888 * 12889 * Note that this object is related to {@link DataTable.defaults} but this 12890 * one is the internal data store for DataTables's cache of columns. It should 12891 * NOT be manipulated outside of DataTables. Any configuration should be done 12892 * through the initialisation options. 12893 * @namespace 12894 * @todo Really should attach the settings object to individual instances so we 12895 * don't need to create new instances on each $().dataTable() call (if the 12896 * table already exists). It would also save passing oSettings around and 12897 * into every single function. However, this is a very significant 12898 * architecture change for DataTables and will almost certainly break 12899 * backwards compatibility with older installations. This is something that 12900 * will be done in 2.0. 12901 */ 12902 DataTable.models.oSettings = { 12903 /** 12904 * Primary features of DataTables and their enablement state. 12905 * @namespace 12906 */ 12907 "oFeatures": { 12908 12909 /** 12910 * Flag to say if DataTables should automatically try to calculate the 12911 * optimum table and columns widths (true) or not (false). 12912 * Note that this parameter will be set by the initialisation routine. To 12913 * set a default use {@link DataTable.defaults}. 12914 * @type boolean 12915 */ 12916 "bAutoWidth": null, 12917 12918 /** 12919 * Delay the creation of TR and TD elements until they are actually 12920 * needed by a driven page draw. This can give a significant speed 12921 * increase for Ajax source and Javascript source data, but makes no 12922 * difference at all f
12922ro
vendor: 14,836 bytes, lines 12922-13499
12922 DOM and server-side processing tables. 12923 * Note that this parameter will be set by the initialisation routine. To 12924 * set a default use {@link DataTable.defaults}. 12925 * @type boolean 12926 */ 12927 "bDeferRender": null, 12928 12929 /** 12930 * Enable filtering on the table or not. Note that if this is disabled 12931 * then there is no filtering at all on the table, including fnFilter. 12932 * To just remove the filtering input use sDom and remove the 'f' option. 12933 * Note that this parameter will be set by the initialisation routine. To 12934 * set a default use {@link DataTable.defaults}. 12935 * @type boolean 12936 */ 12937 "bFilter": null, 12938 12939 /** 12940 * Table information element (the 'Showing x of y records' div) enable 12941 * flag. 12942 * Note that this parameter will be set by the initialisation routine. To 12943 * set a default use {@link DataTable.defaults}. 12944 * @type boolean 12945 */ 12946 "bInfo": null, 12947 12948 /** 12949 * Present a user control allowing the end user to change the page size 12950 * when pagination is enabled. 12951 * Note that this parameter will be set by the initialisation routine. To 12952 * set a default use {@link DataTable.defaults}. 12953 * @type boolean 12954 */ 12955 "bLengthChange": null, 12956 12957 /** 12958 * Pagination enabled or not. Note that if this is disabled then length 12959 * changing must also be disabled. 12960 * Note that this parameter will be set by the initialisation routine. To 12961 * set a default use {@link DataTable.defaults}. 12962 * @type boolean 12963 */ 12964 "bPaginate": null, 12965 12966 /** 12967 * Processing indicator enable flag whenever DataTables is enacting a 12968 * user request - typically an Ajax request for server-side processing. 12969 * Note that this parameter will be set by the initialisation routine. To 12970 * set a default use {@link DataTable.defaults}. 12971 * @type boolean 12972 */ 12973 "bProcessing": null, 12974 12975 /** 12976 * Server-side processing enabled flag - when enabled DataTables will 12977 * get all data from the server for every draw - there is no filtering, 12978 * sorting or paging done on the client-side. 12979 * Note that this parameter will be set by the initialisation routine. To 12980 * set a default use {@link DataTable.defaults}. 12981 * @type boolean 12982 */ 12983 "bServerSide": null, 12984 12985 /** 12986 * Sorting enablement flag. 12987 * Note that this parameter will be set by the initialisation routine. To 12988 * set a default use {@link DataTable.defaults}. 12989 * @type boolean 12990 */ 12991 "bSort": null, 12992 12993 /** 12994 * Multi-column sorting 12995 * Note that this parameter will be set by the initialisation routine. To 12996 * set a default use {@link DataTable.defaults}. 12997 * @type boolean 12998 */ 12999 "bSortMulti": null, 13000 13001 /** 13002 * Apply a class to the columns which are being sorted to provide a 13003 * visual highlight or not. This can slow things down when enabled since 13004 * there is a lot of DOM interaction. 13005 * Note that this parameter will be set by the initialisation routine. To 13006 * set a default use {@link DataTable.defaults}. 13007 * @type boolean 13008 */ 13009 "bSortClasses": null, 13010 13011 /** 13012 * State saving enablement flag. 13013 * Note that this parameter will be set by the initialisation routine. To 13014 * set a default use {@link DataTable.defaults}. 13015 * @type boolean 13016 */ 13017 "bStateSave": null 13018 }, 13019 13020 13021 /** 13022 * Scrolling settings for a table. 13023 * @namespace 13024 */ 13025 "oScroll": { 13026 /** 13027 * When the table is shorter in height than sScrollY, collapse the 13028 * table container down to the height of the table (when true). 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 "bCollapse": null, 13034 13035 /** 13036 * Width of the scrollbar for the web-browser's platform. Calculated 13037 * during table initialisation. 13038 * @type int 13039 * @default 0 13040 */ 13041 "iBarWidth": 0, 13042 13043 /** 13044 * Viewport width for horizontal scrolling. Horizontal scrolling is 13045 * disabled if an empty string. 13046 * Note that this parameter will be set by the initialisation routine. To 13047 * set a default use {@link DataTable.defaults}. 13048 * @type string 13049 */ 13050 "sX": null, 13051 13052 /** 13053 * Width to expand the table to when using x-scrolling. Typically you 13054 * should not need to use this. 13055 * Note that this parameter will be set by the initialisation routine. To 13056 * set a default use {@link DataTable.defaults}. 13057 * @type string 13058 * @deprecated 13059 */ 13060 "sXInner": null, 13061 13062 /** 13063 * Viewport height for vertical scrolling. Vertical scrolling is disabled 13064 * if an empty string. 13065 * Note that this parameter will be set by the initialisation routine. To 13066 * set a default use {@link DataTable.defaults}. 13067 * @type string 13068 */ 13069 "sY": null 13070 }, 13071 13072 /** 13073 * Language information for the table. 13074 * @namespace 13075 * @extends DataTable.defaults.oLanguage 13076 */ 13077 "oLanguage": { 13078 /** 13079 * Information callback function. See 13080 * {@link DataTable.defaults.fnInfoCallback} 13081 * @type function 13082 * @default null 13083 */ 13084 "fnInfoCallback": null 13085 }, 13086 13087 /** 13088 * Browser support parameters 13089 * @namespace 13090 */ 13091 "oBrowser": { 13092 /** 13093 * Indicate if the browser incorrectly calculates width:100% inside a 13094 * scrolling element (IE6/7) 13095 * @type boolean 13096 * @default false 13097 */ 13098 "bScrollOversize": false, 13099 13100 /** 13101 * Determine if the vertical scrollbar is on the right or left of the 13102 * scrolling container - needed for rtl language layout, although not 13103 * all browsers move the scrollbar (Safari). 13104 * @type boolean 13105 * @default false 13106 */ 13107 "bScrollbarLeft": false, 13108 13109 /** 13110 * Flag for if `getBoundingClientRect` is fully supported or not 13111 * @type boolean 13112 * @default false 13113 */ 13114 "bBounding": false, 13115 13116 /** 13117 * Browser scrollbar width 13118 * @type integer 13119 * @default 0 13120 */ 13121 "barWidth": 0 13122 }, 13123 13124 13125 "ajax": null, 13126 13127 13128 /** 13129 * Array referencing the nodes which are used for the features. The 13130 * parameters of this object match what is allowed by sDom - i.e. 13131 * <ul> 13132 * <li>'l' - Length changing</li> 13133 * <li>'f' - Filtering input</li> 13134 * <li>'t' - The table!</li> 13135 * <li>'i' - Information</li> 13136 * <li>'p' - Pagination</li> 13137 * <li>'r' - pRocessing</li> 13138 * </ul> 13139 * @type array 13140 * @default [] 13141 */ 13142 "aanFeatures": [], 13143 13144 /** 13145 * Store data information - see {@link DataTable.models.oRow} for detailed 13146 * information. 13147 * @type array 13148 * @default [] 13149 */ 13150 "aoData": [], 13151 13152 /** 13153 * Array of indexes which are in the current display (after filtering etc) 13154 * @type array 13155 * @default [] 13156 */ 13157 "aiDisplay": [], 13158 13159 /** 13160 * Array of indexes for display - no filtering 13161 * @type array 13162 * @default [] 13163 */ 13164 "aiDisplayMaster": [], 13165 13166 /** 13167 * Map of row ids to data indexes 13168 * @type object 13169 * @default {} 13170 */ 13171 "aIds": {}, 13172 13173 /** 13174 * Store information about each column that is in use 13175 * @type array 13176 * @default [] 13177 */ 13178 "aoColumns": [], 13179 13180 /** 13181 * Store information about the table's header 13182 * @type array 13183 * @default [] 13184 */ 13185 "aoHeader": [], 13186 13187 /** 13188 * Store information about the table's footer 13189 * @type array 13190 * @default [] 13191 */ 13192 "aoFooter": [], 13193 13194 /** 13195 * Store the applied global search information in case we want to force a 13196 * research or compare the old search to a new one. 13197 * Note that this parameter will be set by the initialisation routine. To 13198 * set a default use {@link DataTable.defaults}. 13199 * @namespace 13200 * @extends DataTable.models.oSearch 13201 */ 13202 "oPreviousSearch": {}, 13203 13204 /** 13205 * Store the applied search for each column - see 13206 * {@link DataTable.models.oSearch} for the format that is used for the 13207 * filtering information for each column. 13208 * @type array 13209 * @default [] 13210 */ 13211 "aoPreSearchCols": [], 13212 13213 /** 13214 * Sorting that is applied to the table. Note that the inner arrays are 13215 * used in the following manner: 13216 * <ul> 13217 * <li>Index 0 - column number</li> 13218 * <li>Index 1 - current sorting direction</li> 13219 * </ul> 13220 * Note that this parameter will be set by the initialisation routine. To 13221 * set a default use {@link DataTable.defaults}. 13222 * @type array 13223 * @todo These inner arrays should really be objects 13224 */ 13225 "aaSorting": null, 13226 13227 /** 13228 * Sorting that is always applied to the table (i.e. prefixed in front of 13229 * aaSorting). 13230 * Note that this parameter will be set by the initialisation routine. To 13231 * set a default use {@link DataTable.defaults}. 13232 * @type array 13233 * @default [] 13234 */ 13235 "aaSortingFixed": [], 13236 13237 /** 13238 * Classes to use for the striping of a table. 13239 * Note that this parameter will be set by the initialisation routine. To 13240 * set a default use {@link DataTable.defaults}. 13241 * @type array 13242 * @default [] 13243 */ 13244 "asStripeClasses": null, 13245 13246 /** 13247 * If restoring a table - we should restore its striping classes as well 13248 * @type array 13249 * @default [] 13250 */ 13251 "asDestroyStripes": [], 13252 13253 /** 13254 * If restoring a table - we should restore its width 13255 * @type int 13256 * @default 0 13257 */ 13258 "sDestroyWidth": 0, 13259 13260 /** 13261 * Callback functions array for every time a row is inserted (i.e. on a draw). 13262 * @type array 13263 * @default [] 13264 */ 13265 "aoRowCallback": [], 13266 13267 /** 13268 * Callback functions for the header on each draw. 13269 * @type array 13270 * @default [] 13271 */ 13272 "aoHeaderCallback": [], 13273 13274 /** 13275 * Callback function for the footer on each draw. 13276 * @type array 13277 * @default [] 13278 */ 13279 "aoFooterCallback": [], 13280 13281 /** 13282 * Array of callback functions for draw callback functions 13283 * @type array 13284 * @default [] 13285 */ 13286 "aoDrawCallback": [], 13287 13288 /** 13289 * Array of callback functions for row created function 13290 * @type array 13291 * @default [] 13292 */ 13293 "aoRowCreatedCallback": [], 13294 13295 /** 13296 * Callback functions for just before the table is redrawn. A return of 13297 * false will be used to cancel the draw. 13298 * @type array 13299 * @default [] 13300 */ 13301 "aoPreDrawCallback": [], 13302 13303 /** 13304 * Callback functions for when the table has been initialised. 13305 * @type array 13306 * @default [] 13307 */ 13308 "aoInitComplete": [], 13309 13310 13311 /** 13312 * Callbacks for modifying the settings to be stored for state saving, prior to 13313 * saving state. 13314 * @type array 13315 * @default [] 13316 */ 13317 "aoStateSaveParams": [], 13318 13319 /** 13320 * Callbacks for modifying the settings that have been stored for state saving 13321 * prior to using the stored values to restore the state. 13322 * @type array 13323 * @default [] 13324 */ 13325 "aoStateLoadParams": [], 13326 13327 /** 13328 * Callbacks for operating on the settings object once the saved state has been 13329 * loaded 13330 * @type array 13331 * @default [] 13332 */ 13333 "aoStateLoaded": [], 13334 13335 /** 13336 * Cache the table ID for quick access 13337 * @type string 13338 * @default <i>Empty string</i> 13339 */ 13340 "sTableId": "", 13341 13342 /** 13343 * The TABLE node for the main table 13344 * @type node 13345 * @default null 13346 */ 13347 "nTable": null, 13348 13349 /** 13350 * Permanent ref to the thead element 13351 * @type node 13352 * @default null 13353 */ 13354 "nTHead": null, 13355 13356 /** 13357 * Permanent ref to the tfoot element - if it exists 13358 * @type node 13359 * @default null 13360 */ 13361 "nTFoot": null, 13362 13363 /** 13364 * Permanent ref to the tbody element 13365 * @type node 13366 * @default null 13367 */ 13368 "nTBody": null, 13369 13370 /** 13371 * Cache the wrapper node (contains all DataTables controlled elements) 13372 * @type node 13373 * @default null 13374 */ 13375 "nTableWrapper": null, 13376 13377 /** 13378 * Indicate if when using server-side processing the loading of data 13379 * should be deferred until the second draw. 13380 * Note that this parameter will be set by the initialisation routine. To 13381 * set a default use {@link DataTable.defaults}. 13382 * @type boolean 13383 * @default false 13384 */ 13385 "bDeferLoading": false, 13386 13387 /** 13388 * Indicate if all required information has been read in 13389 * @type boolean 13390 * @default false 13391 */ 13392 "bInitialised": false, 13393 13394 /** 13395 * Information about open rows. Each object in the array has the parameters 13396 * 'nTr' and 'nParent' 13397 * @type array 13398 * @default [] 13399 */ 13400 "aoOpenRows": [], 13401 13402 /** 13403 * Dictate the positioning of DataTables' control elements - see 13404 * {@link DataTable.model.oInit.sDom}. 13405 * Note that this parameter will be set by the initialisation routine. To 13406 * set a default use {@link DataTable.defaults}. 13407 * @type string 13408 * @default null 13409 */ 13410 "sDom": null, 13411 13412 /** 13413 * Search delay (in mS) 13414 * @type integer 13415 * @default null 13416 */ 13417 "searchDelay": null, 13418 13419 /** 13420 * Which type of pagination should be used. 13421 * Note that this parameter will be set by the initialisation routine. To 13422 * set a default use {@link DataTable.defaults}. 13423 * @type string 13424 * @default two_button 13425 */ 13426 "sPaginationType": "two_button", 13427 13428 /** 13429 * The state duration (for `stateSave`) in seconds. 13430 * Note that this parameter will be set by the initialisation routine. To 13431 * set a default use {@link DataTable.defaults}. 13432 * @type int 13433 * @default 0 13434 */ 13435 "iStateDuration": 0, 13436 13437 /** 13438 * Array of callback functions for state saving. Each array element is an 13439 * object with the following parameters: 13440 * <ul> 13441 * <li>function:fn - function to call. Takes two parameters, oSettings 13442 * and the JSON string to save that has been thus far created. Returns 13443 * a JSON string to be inserted into a json object 13444 * (i.e. '"param": [ 0, 1, 2]')</li> 13445 * <li>string:sName - name of callback</li> 13446 * </ul> 13447 * @type array 13448 * @default [] 13449 */ 13450 "aoStateSave": [], 13451 13452 /** 13453 * Array of callback functions for state loading. Each array element is an 13454 * object with the following parameters: 13455 * <ul> 13456 * <li>function:fn - function to call. Takes two parameters, oSettings 13457 * and the object stored. May return false to cancel state loading</li> 13458 * <li>string:sName - name of callback</li> 13459 * </ul> 13460 * @type array 13461 * @default [] 13462 */ 13463 "aoStateLoad": [], 13464 13465 /** 13466 * State that was saved. Useful for back reference 13467 * @type object 13468 * @default null 13469 */ 13470 "oSavedState": null, 13471 13472 /** 13473 * State that was loaded. Useful for back reference 13474 * @type object 13475 * @default null 13476 */ 13477 "oLoadedState": null, 13478 13479 /** 13480 * Source url for AJAX data for the table. 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 null 13485 */ 13486 "sAjaxSource": null, 13487 13488 /** 13489 * Property from a given object from which to read the table data from. This 13490 * can be an empty string (when not server-side processing), in which case 13491 * it is assumed an an array is given directly. 13492 * Note that this parameter will be set by the initialisation routine. To 13493 * set a default use {@link DataTable.defaults}. 13494 * @type string 13495 */ 13496 "sAjaxDataProp": null, 13497 13498 /** 13499 *
13499Note if draw should be blocked while getting data 13500 * @type boolean 13501 * @default true 13502 */ 13503 "bAjaxDataGet": true, 13504 13505 /** 13506 * The last jQuery XHR object that was used for server-side data gathering. 13507 * This can be used for working with the XHR information in one of the 13508 * callbacks 13509 * @type object 13510 * @default null 13511 */ 13512 "jqXHR": null, 13513 13514 /** 13515 * JSON returned from the server in the last Ajax request 13516 * @type object 13517 * @default undefined 13518 */ 13519 "json": undefined, 13520 13521 /** 13522 * Data submitted as part of the last Ajax request 13523 * @type object 13524 * @default undefined 13525 */ 13526 "oAjaxData": undefined, 13527 13528 /** 13529 * Function to get the server-side data. 13530 * Note that this parameter will be set by the initialisation routine. To 13531 * set a default use {@link DataTable.defaults}. 13532 * @type function 13533 */ 13534 "fnServerData": null, 13535 13536 /** 13537 * Functions which are called prior to sending an Ajax request so extra 13538 * parameters can easily be sent to the server 13539 * @type array 13540 * @default [] 13541 */ 13542 "aoServerParams": [], 13543 13544 /** 13545 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if 13546 * required). 13547 * Note that this parameter will be set by the initialisation routine. To 13548 * set a default use {@link DataTable.defaults}. 13549 * @type string 13550 */ 13551 "sServerMethod": null, 13552 13553 /** 13554 * Format numbers for display. 13555 * Note that this parameter will be set by the initialisation routine. To 13556 * set a default use {@link DataTable.defaults}. 13557 * @type function 13558 */ 13559 "fnFormatNumber": null, 13560 13561 /** 13562 * List of options that can be used for the user selectable length menu. 13563 * Note that this parameter will be set by the initialisation routine. To 13564 * set a default use {@link DataTable.defaults}. 13565 * @type array 13566 * @default [] 13567 */ 13568 "aLengthMenu": null, 13569 13570 /** 13571 * Counter for the draws that the table does. Also used as a tracker for 13572 * server-side processing 13573 * @type int 13574 * @default 0 13575 */ 13576 "iDraw": 0, 13577 13578 /** 13579 * Indicate if a redraw is being done - useful for Ajax 13580 * @type boolean 13581 * @default false 13582 */ 13583 "bDrawing": false, 13584 13585 /** 13586 * Draw index (iDraw) of the last error when parsing the returned data 13587 * @type int 13588 * @default -1 13589 */ 13590 "iDrawError": -1, 13591 13592 /** 13593 * Paging display length 13594 * @type int 13595 * @default 10 13596 */ 13597 "_iDisplayLength": 10, 13598 13599 /** 13600 * Paging start point - aiDisplay index 13601 * @type int 13602 * @default 0 13603 */ 13604 "_iDisplayStart": 0, 13605 13606 /** 13607 * Server-side processing - number of records in the result set 13608 * (i.e. before filtering), Use fnRecordsTotal rather than 13609 * this property to get the value of the number of records, regardless of 13610 * the server-side processing setting. 13611 * @type int 13612 * @default 0 13613 * @private 13614 */ 13615 "_iRecordsTotal": 0, 13616 13617 /** 13618 * Server-side processing - number of records in the current display set 13619 * (i.e. after filtering). Use fnRecordsDisplay rather than 13620 * this property to get the value of the number of records, regardless of 13621 * the server-side processing setting. 13622 * @type boolean 13623 * @default 0 13624 * @private 13625 */ 13626 "_iRecordsDisplay": 0, 13627 13628 /** 13629 * Flag to indicate if jQuery UI marking and classes should be used. 13630 * Note that this parameter will be set by the initialisation routine. To 13631 * set a default use {@link DataTable.defaults}. 13632 * @type boolean 13633 */ 13634 "bJUI": null, 13635 13636 /** 13637 * The classes to use for the table 13638 * @type object 13639 * @default {} 13640 */
vendor: 3,548 bytes, lines 13641-13796
13641 "oClasses": {}, 13642 13643 /** 13644 * Flag attached to the settings object so you can check in the draw 13645 * callback if filtering has been done in the draw. Deprecated in favour of 13646 * events. 13647 * @type boolean 13648 * @default false 13649 * @deprecated 13650 */ 13651 "bFiltered": false, 13652 13653 /** 13654 * Flag attached to the settings object so you can check in the draw 13655 * callback if sorting has been done in the draw. Deprecated in favour of 13656 * events. 13657 * @type boolean 13658 * @default false 13659 * @deprecated 13660 */ 13661 "bSorted": false, 13662 13663 /** 13664 * Indicate that if multiple rows are in the header and there is more than 13665 * one unique cell per column, if the top one (true) or bottom one (false) 13666 * should be used for sorting / title by DataTables. 13667 * Note that this parameter will be set by the initialisation routine. To 13668 * set a default use {@link DataTable.defaults}. 13669 * @type boolean 13670 */ 13671 "bSortCellsTop": null, 13672 13673 /** 13674 * Initialisation object that is used for the table 13675 * @type object 13676 * @default null 13677 */ 13678 "oInit": null, 13679 13680 /** 13681 * Destroy callback functions - for plug-ins to attach themselves to the 13682 * destroy so they can clean up markup and events. 13683 * @type array 13684 * @default [] 13685 */ 13686 "aoDestroyCallback": [], 13687 13688 13689 /** 13690 * Get the number of records in the current record set, before filtering 13691 * @type function 13692 */ 13693 "fnRecordsTotal": function () 13694 { 13695 return _fnDataSource( this ) == 'ssp' ? 13696 this._iRecordsTotal * 1 : 13697 this.aiDisplayMaster.length; 13698 }, 13699 13700 /** 13701 * Get the number of records in the current record set, after filtering 13702 * @type function 13703 */ 13704 "fnRecordsDisplay": function () 13705 { 13706 return _fnDataSource( this ) == 'ssp' ? 13707 this._iRecordsDisplay * 1 : 13708 this.aiDisplay.length; 13709 }, 13710 13711 /** 13712 * Get the display end point - aiDisplay index 13713 * @type function 13714 */ 13715 "fnDisplayEnd": function () 13716 { 13717 var 13718 len = this._iDisplayLength, 13719 start = this._iDisplayStart, 13720 calc = start + len, 13721 records = this.aiDisplay.length, 13722 features = this.oFeatures, 13723 paginate = features.bPaginate; 13724 13725 if ( features.bServerSide ) { 13726 return paginate === false || len === -1 ? 13727 start + records : 13728 Math.min( start+len, this._iRecordsDisplay ); 13729 } 13730 else { 13731 return ! paginate || calc>records || len===-1 ? 13732 records : 13733 calc; 13734 } 13735 }, 13736 13737 /** 13738 * The DataTables object for this table 13739 * @type object 13740 * @default null 13741 */ 13742 "oInstance": null, 13743 13744 /** 13745 * Unique identifier for each instance of the DataTables object. If there 13746 * is an ID on the table node, then it takes that value, otherwise an 13747 * incrementing internal counter is used. 13748 * @type string 13749 * @default null 13750 */ 13751 "sInstance": null, 13752 13753 /** 13754 * tabindex attribute value that is added to DataTables control elements, allowing 13755 * keyboard navigation of the table and its controls. 13756 */ 13757 "iTabIndex": 0, 13758 13759 /** 13760 * DIV container for the footer scrolling table if scrolling 13761 */ 13762 "nScrollHead": null, 13763 13764 /** 13765 * DIV container for the footer scrolling table if scrolling 13766 */ 13767 "nScrollFoot": null, 13768 13769 /** 13770 * Last applied sort 13771 * @type array 13772 * @default [] 13773 */ 13774 "aLastSort": [], 13775 13776 /** 13777 * Stored plug-in instances 13778 * @type object 13779 * @default {} 13780 */ 13781 "oPlugins": {}, 13782 13783 /** 13784 * Function used to get a row's id from the row's data 13785 * @type function 13786 * @default null 13787 */ 13788 "rowIdFn": null, 13789 13790 /** 13791 * Data location where to store a row's id 13792 * @type string 13793 * @default null 13794 */ 13795 "rowId": null 13796 };
vendor: 11,984 bytes, lines 13797-14163
13797 13798 /** 13799 * Extension object for DataTables that is used to provide all extension 13800 * options. 13801 * 13802 * Note that the `DataTable.ext` object is available through 13803 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is 13804 * also aliased to `jQuery.fn.dataTableExt` for historic reasons. 13805 * @namespace 13806 * @extends DataTable.models.ext 13807 */ 13808 13809 13810 /** 13811 * DataTables extensions 13812 * 13813 * This namespace acts as a collection area for plug-ins that can be used to 13814 * extend DataTables capabilities. Indeed many of the build in methods 13815 * use this method to provide their own capabilities (sorting methods for 13816 * example). 13817 * 13818 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy 13819 * reasons 13820 * 13821 * @namespace 13822 */ 13823 DataTable.ext = _ext = { 13824 /** 13825 * Buttons. For use with the Buttons extension for DataTables. This is 13826 * defined here so other extensions can define buttons regardless of load 13827 * order. It is _not_ used by DataTables core. 13828 * 13829 * @type object 13830 * @default {} 13831 */ 13832 buttons: {}, 13833 13834 13835 /** 13836 * Element class names 13837 * 13838 * @type object 13839 * @default {} 13840 */ 13841 classes: {}, 13842 13843 13844 /** 13845 * DataTables build type (expanded by the download builder) 13846 * 13847 * @type string 13848 */ 13849 builder: "-source-", 13850 13851 13852 /** 13853 * Error reporting. 13854 * 13855 * How should DataTables report an error. Can take the value 'alert', 13856 * 'throw', 'none' or a function. 13857 * 13858 * @type string|function 13859 * @default alert 13860 */ 13861 errMode: "alert", 13862 13863 13864 /** 13865 * Feature plug-ins. 13866 * 13867 * This is an array of objects which describe the feature plug-ins that are 13868 * available to DataTables. These feature plug-ins are then available for 13869 * use through the `dom` initialisation option. 13870 * 13871 * Each feature plug-in is described by an object which must have the 13872 * following properties: 13873 * 13874 * * `fnInit` - function that is used to initialise the plug-in, 13875 * * `cFeature` - a character so the feature can be enabled by the `dom` 13876 * instillation option. This is case sensitive. 13877 * 13878 * The `fnInit` function has the following input parameters: 13879 * 13880 * 1. `{object}` DataTables settings object: see 13881 * {@link DataTable.models.oSettings} 13882 * 13883 * And the following return is expected: 13884 * 13885 * * {node|null} The element which contains your feature. Note that the 13886 * return may also be void if your plug-in does not require to inject any 13887 * DOM elements into DataTables control (`dom`) - for example this might 13888 * be useful when developing a plug-in which allows table control via 13889 * keyboard entry 13890 * 13891 * @type array 13892 * 13893 * @example 13894 * $.fn.dataTable.ext.features.push( { 13895 * "fnInit": function( oSettings ) { 13896 * return new TableTools( { "oDTSettings": oSettings } ); 13897 * }, 13898 * "cFeature": "T" 13899 * } ); 13900 */ 13901 feature: [], 13902 13903 13904 /** 13905 * Row searching. 13906 * 13907 * This method of searching is complimentary to the default type based 13908 * searching, and a lot more comprehensive as it allows you complete control 13909 * over the searching logic. Each element in this array is a function 13910 * (parameters described below) that is called for every row in the table, 13911 * and your logic decides if it should be included in the searching data set 13912 * or not. 13913 * 13914 * Searching functions have the following input parameters: 13915 * 13916 * 1. `{object}` DataTables settings object: see 13917 * {@link DataTable.models.oSettings} 13918 * 2. `{array|object}` Data for the row to be processed (same as the 13919 * original format that was passed in as the data source, or an array 13920 * from a DOM data source 13921 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which 13922 * can be useful to retrieve the `TR` element if you need DOM interaction. 13923 * 13924 * And the following return is expected: 13925 * 13926 * * {boolean} Include the row in the searched result set (true) or not 13927 * (false) 13928 * 13929 * Note that as with the main search ability in DataTables, technically this 13930 * is "filtering", since it is subtractive. However, for consistency in 13931 * naming we call it searching here. 13932 * 13933 * @type array 13934 * @default [] 13935 * 13936 * @example 13937 * // The following example shows custom search being applied to the 13938 * // fourth column (i.e. the data[3] index) based on two input values 13939 * // from the end-user, matching the data in a certain range. 13940 * $.fn.dataTable.ext.search.push( 13941 * function( settings, data, dataIndex ) { 13942 * var min = document.getElementById('min').value * 1; 13943 * var max = document.getElementById('max').value * 1; 13944 * var version = data[3] == "-" ? 0 : data[3]*1; 13945 * 13946 * if ( min == "" && max == "" ) { 13947 * return true; 13948 * } 13949 * else if ( min == "" && version < max ) { 13950 * return true; 13951 * } 13952 * else if ( min < version && "" == max ) { 13953 * return true; 13954 * } 13955 * else if ( min < version && version < max ) { 13956 * return true; 13957 * } 13958 * return false; 13959 * } 13960 * ); 13961 */ 13962 search: [], 13963 13964 13965 /** 13966 * Selector extensions 13967 * 13968 * The `selector` option can be used to extend the options available for the 13969 * selector modifier options (`selector-modifier` object data type) that 13970 * each of the three built in selector types offer (row, column and cell + 13971 * their plural counterparts). For example the Select extension uses this 13972 * mechanism to provide an option to select only rows, columns and cells 13973 * that have been marked as selected by the end user (`{selected: true}`), 13974 * which can be used in conjunction with the existing built in selector 13975 * options. 13976 * 13977 * Each property is an array to which functions can be pushed. The functions 13978 * take three attributes: 13979 * 13980 * * Settings object for the host table 13981 * * Options object (`selector-modifier` object type) 13982 * * Array of selected item indexes 13983 * 13984 * The return is an array of the resulting item indexes after the custom 13985 * selector has been applied. 13986 * 13987 * @type object 13988 */ 13989 selector: { 13990 cell: [], 13991 column: [], 13992 row: [] 13993 }, 13994 13995 13996 /** 13997 * Internal functions, exposed for used in plug-ins. 13998 * 13999 * Please note that you should not need to use the internal methods for 14000 * anything other than a plug-in (and even then, try to avoid if possible). 14001 * The internal function may change between releases. 14002 * 14003 * @type object 14004 * @default {} 14005 */ 14006 internal: {}, 14007 14008 14009 /** 14010 * Legacy configuration options. Enable and disable legacy options that 14011 * are available in DataTables. 14012 * 14013 * @type object 14014 */ 14015 legacy: { 14016 /** 14017 * Enable / disable DataTables 1.9 compatible server-side processing 14018 * requests 14019 * 14020 * @type boolean 14021 * @default null 14022 */ 14023 ajax: null 14024 }, 14025 14026 14027 /** 14028 * Pagination plug-in methods. 14029 * 14030 * Each entry in this object is a function and defines which buttons should 14031 * be shown by the pagination rendering method that is used for the table: 14032 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the 14033 * buttons are displayed in the document, while the functions here tell it 14034 * what buttons to display. This is done by returning an array of button 14035 * descriptions (what each button will do). 14036 * 14037 * Pagination types (the four built in options and any additional plug-in 14038 * options defined here) can be used through the `paginationType` 14039 * initialisation parameter. 14040 * 14041 * The functions defined take two parameters: 14042 * 14043 * 1. `{int} page` The current page index 14044 * 2. `{int} pages` The number of pages in the table 14045 * 14046 * Each function is expected to return an array where each element of the 14047 * array can be one of: 14048 * 14049 * * `first` - Jump to first page when activated 14050 * * `last` - Jump to last page when activated 14051 * * `previous` - Show previous page when activated 14052 * * `next` - Show next page when activated 14053 * * `{int}` - Show page of the index given 14054 * * `{array}` - A nested array containing the above elements to add a 14055 * containing 'DIV' element (might be useful for styling). 14056 * 14057 * Note that DataTables v1.9- used this object slightly differently whereby 14058 * an object with two functions would be defined for each plug-in. That 14059 * ability is still supported by DataTables 1.10+ to provide backwards 14060 * compatibility, but this option of use is now decremented and no longer 14061 * documented in DataTables 1.10+. 14062 * 14063 * @type object 14064 * @default {} 14065 * 14066 * @example 14067 * // Show previous, next and current page buttons only 14068 * $.fn.dataTableExt.oPagination.current = function ( page, pages ) { 14069 * return [ 'previous', page, 'next' ]; 14070 * }; 14071 */ 14072 pager: {}, 14073 14074 14075 renderer: { 14076 pageButton: {}, 14077 header: {} 14078 }, 14079 14080 14081 /** 14082 * Ordering plug-ins - custom data source 14083 * 14084 * The extension options for ordering of data available here is complimentary 14085 * to the default type based ordering that DataTables typically uses. It 14086 * allows much greater control over the the data that is being used to 14087 * order a column, but is necessarily therefore more complex. 14088 * 14089 * This type of ordering is useful if you want to do ordering based on data 14090 * live from the DOM (for example the contents of an 'input' element) rather 14091 * than just the static string that DataTables knows of. 14092 * 14093 * The way these plug-ins work is that you create an array of the values you 14094 * wish to be ordering for the column in question and then return that 14095 * array. The data in the array much be in the index order of the rows in 14096 * the table (not the currently ordering order!). Which order data gathering 14097 * function is run here depends on the `dt-init columns.orderDataType` 14098 * parameter that is used for the column (if any). 14099 * 14100 * The functions defined take two parameters: 14101 * 14102 * 1. `{object}` DataTables settings object: see 14103 * {@link DataTable.models.oSettings} 14104 * 2. `{int}` Target column index 14105 * 14106 * Each function is expected to return an array: 14107 * 14108 * * `{array}` Data for the column to be ordering upon 14109 * 14110 * @type array 14111 * 14112 * @example 14113 * // Ordering using `input` node values 14114 * $.fn.dataTable.ext.order['dom-text'] = function ( settings, col ) 14115 * { 14116 * return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) { 14117 * return $('input', td).val(); 14118 * } ); 14119 * } 14120 */ 14121 order: {}, 14122 14123 14124 /** 14125 * Type based plug-ins. 14126 * 14127 * Each column in DataTables has a type assigned to it, either by automatic 14128 * detection or by direct assignment using the `type` option for the column. 14129 * The type of a column will effect how it is ordering and search (plug-ins 14130 * can also make use of the column type if required). 14131 * 14132 * @namespace 14133 */ 14134 type: { 14135 /** 14136 * Type detection functions. 14137 * 14138 * The functions defined in this object are used to automatically detect 14139 * a column's type, making initialisation of DataTables super easy, even 14140 * when complex data is in the table. 14141 * 14142 * The functions defined take two parameters: 14143 * 14144 * 1. `{*}` Data from the column cell to be analysed 14145 * 2. `{settings}` DataTables settings object. This can be used to 14146 * perform context specific type detection - for example detection 14147 * based on language settings such as using a comma for a decimal 14148 * place. Generally speaking the options from the settings will not 14149 * be required 14150 * 14151 * Each function is expected to return: 14152 * 14153 * * `{string|null}` Data type detected, or null if unknown (and thus 14154 * pass it on to the other type detection functions. 14155 * 14156 * @type array 14157 * 14158 * @example 14159 * // Currency type detection plug-in: 14160 * $.fn.dataTable.ext.type.detect.push( 14161 * function ( data, settings ) { 14162 * // Check the numeric part 14163 * if ( !
14163$.isNumeric( data.substring(1) ) ) { 14164 * return null; 14165 * } 14166 * 14167 * // Check prefixed by currency 14168 * if ( data.charAt(0) == '$' || data.charAt(0) == '£' ) { 14169 * return 'currency'; 14170 * } 14171 * return null; 14172 * } 14173 * ); 14174 */ 14175 detect: [], 14176 14177 14178 /** 14179 * Type based search formatting. 14180 * 14181 * The type based searching functions can be used to pre-format the 14182 * data to be search on. For example, it can be used to strip HTML 14183 * tags or to de-format telephone numbers for numeric only searching. 14184 * 14185 * Note that is a search is not defined for a column of a given type, 14186 * no search formatting will be performed. 14187 * 14188 * Pre-processing of searching data plug-ins - When you assign the sType 14189 * for a column (or have it automatically detected for you by DataTables 14190 * or a type detection plug-in), you will typically be using this for 14191 * custom sorting, but it can also be used to provide custom searching 14192 * by allowing you to pre-processing the data and returning the data in 14193 * the format that should be searched upon. This is done by adding 14194 * functions this object with a parameter name which matches the sType 14195 * for that target column. This is the corollary of <i>afnSortData</i> 14196 * for searching data. 14197 * 14198 * The functions defined take a single parameter: 14199 * 14200 * 1. `{*}` Data from the column cell to be prepared for searching 14201 * 14202 * Each function is expected to return: 14203 * 14204 * * `{string|null}` Formatted string that will be used for the searching. 14205 * 14206 * @type object 14207 * @default {} 14208 * 14209 * @example 14210 * $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) { 14211 * return d.replace(/\n/g," ").replace( /<.*?>/g, "" ); 14212 * } 14213 */ 14214 search: {}, 14215 14216 14217 /** 14218 * Type based ordering. 14219 * 14220 * The column type tells DataTables what ordering to apply to the table 14221 * when a column is sorted upon. The order for each type that is defined, 14222 * is defined by the functions available in this object. 14223 * 14224 * Each ordering option can be described by three properties added to 14225 * this object: 14226 * 14227 * * `{type}-pre` - Pre-formatting function 14228 * * `{type}-asc` - Ascending order function 14229 * * `{type}-desc` - Descending order function 14230 * 14231 * All three can be used together, only `{type}-pre` or only 14232 * `{type}-asc` and `{type}-desc` together. It is generally recommended 14233 * that only `{type}-pre` is used, as this provides the optimal 14234 * implementation in terms of speed, although the others are provided 14235 * for compatibility with existing Javascript sort functions. 14236 * 14237 * `{type}-pre`: Functions defined take a single parameter: 14238 * 14239 * 1. `{*}` Data from the column cell to be prepared for ordering 14240 * 14241 * And return: 14242 * 14243 * * `{*}` Data to be sorted upon 14244 * 14245 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort 14246 * functions, taking two parameters: 14247 * 14248 * 1. `{*}` Data to compare to the second parameter 14249 * 2. `{*}` Data to compare to the first parameter 14250 * 14251 * And returning: 14252 * 14253 * * `{*}` Ordering match: <0 if first parameter should be sorted lower 14254 * than the second parameter, ===0 if the two parameters are equal and 14255 * >0 if the first parameter should be sorted height than the second 14256 * parameter. 14257 * 14258 * @type object 14259 * @default {} 14260 * 14261 * @example 14262 * // Numeric ordering of formatted numbers with a pre-formatter 14263 * $.extend( $.fn.dataTable.ext.type.order, { 14264 * "string-pre": function(x) { 14265 * a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" ); 14266 * return parseFloat( a ); 14267 * } 14268 * } ); 14269 * 14270 * @example 14271 * // Case-sensitive string ordering, with no pre-formatting method 14272 * $.extend( $.fn.dataTable.ext.order, { 14273 * "string-case-asc": function(x,y) { 14274 * return ((x < y) ? -1 : ((x > y) ? 1 : 0)); 14275 * }, 14276 * "string-case-desc": function(x,y) { 14277 * return ((x < y) ? 1 : ((x > y) ? -1 : 0)); 14278 * } 14279 * } ); 14280 */ 14281 order: {} 14282 }, 14283 14284 /** 14285 * Unique DataTables instance counter 14286 * 14287 * @type int 14288 * @private 14289 */ 14290 _unique: 0, 14291 14292 14293 // 14294 // Depreciated 14295 // The following properties are retained for backwards compatiblity only. 14296 // The should not be used in new projects and will be removed in a future 14297 // version 14298 // 14299 14300 /** 14301 * Version check function. 14302 * @type function 14303 * @depreciated Since 1.10 14304 */ 14305 fnVersionCheck: DataTable.fnVersionCheck, 14306 14307 14308 /** 14309 * Index for what 'this' index API functions should use 14310 * @type int 14311 * @deprecated Since v1.10 14312 */ 14313 iApiIndex: 0, 14314 14315 14316 /** 14317 * jQuery UI class container 14318 * @type object 14319 * @deprecated Since v1.10 14320 */ 14321 oJUIClasses: {}, 14322 14323 14324 /** 14325 * Software version 14326 * @type string 14327 * @deprecated Since v1.10 14328 */
14329 sVersion: DataTable.version 14330 }; 14331 14332 14333 // 14334 // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts 14335 // 14336 $.extend( _ext, { 14337 afnFiltering: _ext.search, 14338 aTypes: _ext.type.detect, 14339 ofnSearch: _ext.type.search, 14340 oSort: _ext.type.order, 14341 afnSortData: _ext.order, 14342 aoFeatures: _ext.feature, 14343 oApi: _ext.internal, 14344 oStdClasses: _ext.classes, 14345 oPagination: _ext.pager 14346 } ); 14347 14348 14349 $.extend( DataTable.ext.classes, { 14350 "sTable": "dataTable", 14351 "sNoFooter": "no-footer", 14352 14353 /* Paging buttons */ 14354 "sPageButton": "paginate_button", 14355 "sPageButtonActive": "current", 14356 "sPageButtonDisabled": "disabled", 14357 14358 /* Striping classes */ 14359 "sStripeOdd": "odd", 14360 "sStripeEven": "even", 14361 14362 /* Empty row */ 14363 "sRowEmpty": "dataTables_empty", 14364 14365 /* Features */ 14366 "sWrapper": "dataTables_wrapper", 14367 "sFilter": "dataTables_filter", 14368 "sInfo": "dataTables_info", 14369 "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */ 14370 "sLength": "dataTables_length", 14371 "sProcessing": "dataTables_processing", 14372 14373 /* Sorting */ 14374 "sSortAsc": "sorting_asc", 14375 "sSortDesc": "sorting_desc", 14376 "sSortable": "sorting", /* Sortable in both directions */ 14377 "sSortableAsc": "sorting_asc_disabled", 14378 "sSortableDesc": "sorting_desc_disabled", 14379 "sSortableNone": "sorting_disabled", 14380 "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */ 14381 14382 /* Filtering */ 14383 "sFilterInput": "", 14384 14385 /* Page length */ 14386 "sLengthSelect": "", 14387 14388 /* Scrolling */ 14389 "sScrollWrapper": "dataTables_scroll", 14390 "sScrollHead": "dataTables_scrollHead", 14391 "sScrollHeadInner": "dataTables_scrollHeadInner", 14392 "sScrollBody": "dataTables_scrollBody", 14393 "sScrollFoot": "dataTables_scrollFoot", 14394 "sScrollFootInner": "dataTables_scrollFootInner", 14395 14396 /* Misc */ 14397 "sHeaderTH": "", 14398 "sFooterTH": "", 14399 14400 // Deprecated 14401 "sSortJUIAsc": "", 14402 "sSortJUIDesc": "", 14403 "sSortJUI": "", 14404 "sSortJUIAscAllowed": "", 14405 "sSortJUIDescAllowed": "", 14406 "sSortJUIWrapper": "", 14407 "sSortIcon": "", 14408 "sJUIHeader": "", 14409 "sJUIFooter": "" 14410 } ); 14411 14412 14413 (function() { 14414 14415 // Reused strings for better compression. Closure compiler appears to have a
vendor: 24,949 bytes, lines 14416-15242
14416 // weird edge case where it is trying to expand strings rather than use the 14417 // variable version. This results in about 200 bytes being added, for very 14418 // little preference benefit since it this run on script load only. 14419 var _empty = ''; 14420 _empty = ''; 14421 14422 var _stateDefault = _empty + 'ui-state-default'; 14423 var _sortIcon = _empty + 'css_right ui-icon ui-icon-'; 14424 var _headerFooter = _empty + 'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix'; 14425 14426 $.extend( DataTable.ext.oJUIClasses, DataTable.ext.classes, { 14427 /* Full numbers paging buttons */ 14428 "sPageButton": "fg-button ui-button "+_stateDefault, 14429 "sPageButtonActive": "ui-state-disabled", 14430 "sPageButtonDisabled": "ui-state-disabled", 14431 14432 /* Features */ 14433 "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+ 14434 "ui-buttonset-multi paging_", /* Note that the type is postfixed */ 14435 14436 /* Sorting */ 14437 "sSortAsc": _stateDefault+" sorting_asc", 14438 "sSortDesc": _stateDefault+" sorting_desc", 14439 "sSortable": _stateDefault+" sorting", 14440 "sSortableAsc": _stateDefault+" sorting_asc_disabled", 14441 "sSortableDesc": _stateDefault+" sorting_desc_disabled", 14442 "sSortableNone": _stateDefault+" sorting_disabled", 14443 "sSortJUIAsc": _sortIcon+"triangle-1-n", 14444 "sSortJUIDesc": _sortIcon+"triangle-1-s", 14445 "sSortJUI": _sortIcon+"carat-2-n-s", 14446 "sSortJUIAscAllowed": _sortIcon+"carat-1-n", 14447 "sSortJUIDescAllowed": _sortIcon+"carat-1-s", 14448 "sSortJUIWrapper": "DataTables_sort_wrapper", 14449 "sSortIcon": "DataTables_sort_icon", 14450 14451 /* Scrolling */ 14452 "sScrollHead": "dataTables_scrollHead "+_stateDefault, 14453 "sScrollFoot": "dataTables_scrollFoot "+_stateDefault, 14454 14455 /* Misc */ 14456 "sHeaderTH": _stateDefault, 14457 "sFooterTH": _stateDefault, 14458 "sJUIHeader": _headerFooter+" ui-corner-tl ui-corner-tr", 14459 "sJUIFooter": _headerFooter+" ui-corner-bl ui-corner-br" 14460 } ); 14461 14462 }()); 14463 14464 14465 14466 var extPagination = DataTable.ext.pager; 14467 14468 function _numbers ( page, pages ) { 14469 var 14470 numbers = [], 14471 buttons = extPagination.numbers_length, 14472 half = Math.floor( buttons / 2 ), 14473 i = 1; 14474 14475 if ( pages <= buttons ) { 14476 numbers = _range( 0, pages ); 14477 } 14478 else if ( page <= half ) { 14479 numbers = _range( 0, buttons-2 ); 14480 numbers.push( 'ellipsis' ); 14481 numbers.push( pages-1 ); 14482 } 14483 else if ( page >= pages - 1 - half ) { 14484 numbers = _range( pages-(buttons-2), pages ); 14485 numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6 14486 numbers.splice( 0, 0, 0 ); 14487 } 14488 else { 14489 numbers = _range( page-half+2, page+half-1 ); 14490 numbers.push( 'ellipsis' ); 14491 numbers.push( pages-1 ); 14492 numbers.splice( 0, 0, 'ellipsis' ); 14493 numbers.splice( 0, 0, 0 ); 14494 } 14495 14496 numbers.DT_el = 'span'; 14497 return numbers; 14498 } 14499 14500 14501 $.extend( extPagination, { 14502 simple: function ( page, pages ) { 14503 return [ 'previous', 'next' ]; 14504 }, 14505 14506 full: function ( page, pages ) { 14507 return [ 'first', 'previous', 'next', 'last' ]; 14508 }, 14509 14510 numbers: function ( page, pages ) { 14511 return [ _numbers(page, pages) ]; 14512 }, 14513 14514 simple_numbers: function ( page, pages ) { 14515 return [ 'previous', _numbers(page, pages), 'next' ]; 14516 }, 14517 14518 full_numbers: function ( page, pages ) { 14519 return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ]; 14520 }, 14521 14522 first_last_numbers: function (page, pages) { 14523 return ['first', _numbers(page, pages), 'last']; 14524 }, 14525 14526 // For testing and plug-ins to use 14527 _numbers: _numbers, 14528 14529 // Number of number buttons (including ellipsis) to show. _Must be odd!_ 14530 numbers_length: 7 14531 } ); 14532 14533 14534 $.extend( true, DataTable.ext.renderer, { 14535 pageButton: { 14536 _: function ( settings, host, idx, buttons, page, pages ) { 14537 var classes = settings.oClasses; 14538 var lang = settings.oLanguage.oPaginate; 14539 var aria = settings.oLanguage.oAria.paginate || {}; 14540 var btnDisplay, btnClass, counter=0; 14541 14542 var attach = function( container, buttons ) { 14543 var i, ien, node, button; 14544 var clickHandler = function ( e ) { 14545 _fnPageChange( settings, e.data.action, true ); 14546 }; 14547 14548 for ( i=0, ien=buttons.length ; i<ien ; i++ ) { 14549 button = buttons[i]; 14550 14551 if ( $.isArray( button ) ) { 14552 var inner = $( '<'+(button.DT_el || 'div')+'/>' ) 14553 .appendTo( container ); 14554 attach( inner, button ); 14555 } 14556 else { 14557 btnDisplay = null; 14558 btnClass = ''; 14559 14560 switch ( button ) { 14561 case 'ellipsis': 14562 container.append('<span class="ellipsis">…</span>'); 14563 break; 14564 14565 case 'first': 14566 btnDisplay = lang.sFirst; 14567 btnClass = button + (page > 0 ? 14568 '' : ' '+classes.sPageButtonDisabled); 14569 break; 14570 14571 case 'previous': 14572 btnDisplay = lang.sPrevious; 14573 btnClass = button + (page > 0 ? 14574 '' : ' '+classes.sPageButtonDisabled); 14575 break; 14576 14577 case 'next': 14578 btnDisplay = lang.sNext; 14579 btnClass = button + (page < pages-1 ? 14580 '' : ' '+classes.sPageButtonDisabled); 14581 break; 14582 14583 case 'last': 14584 btnDisplay = lang.sLast; 14585 btnClass = button + (page < pages-1 ? 14586 '' : ' '+classes.sPageButtonDisabled); 14587 break; 14588 14589 default: 14590 btnDisplay = button + 1; 14591 btnClass = page === button ? 14592 classes.sPageButtonActive : ''; 14593 break; 14594 } 14595 14596 if ( btnDisplay !== null ) { 14597 node = $('<a>', { 14598 'class': classes.sPageButton+' '+btnClass, 14599 'aria-controls': settings.sTableId, 14600 'aria-label': aria[ button ], 14601 'data-dt-idx': counter, 14602 'tabindex': settings.iTabIndex, 14603 'id': idx === 0 && typeof button === 'string' ? 14604 settings.sTableId +'_'+ button : 14605 null 14606 } ) 14607 .html( btnDisplay ) 14608 .appendTo( container ); 14609 14610 _fnBindAction( 14611 node, {action: button}, clickHandler 14612 ); 14613 14614 counter++; 14615 } 14616 } 14617 } 14618 }; 14619 14620 // IE9 throws an 'unknown error' if document.activeElement is used 14621 // inside an iframe or frame. Try / catch the error. Not good for 14622 // accessibility, but neither are frames. 14623 var activeEl; 14624 14625 try { 14626 // Because this approach is destroying and recreating the paging 14627 // elements, focus is lost on the select button which is bad for 14628 // accessibility. So we want to restore focus once the draw has 14629 // completed 14630 activeEl = $(host).find(document.activeElement).data('dt-idx'); 14631 } 14632 catch (e) {} 14633 14634 attach( $(host).empty(), buttons ); 14635 14636 if ( activeEl !== undefined ) { 14637 $(host).find( '[data-dt-idx='+activeEl+']' ).focus(); 14638 } 14639 } 14640 } 14641 } ); 14642 14643 14644 14645 // Built in type detection. See model.ext.aTypes for information about 14646 // what is required from this methods. 14647 $.extend( DataTable.ext.type.detect, [ 14648 // Plain numbers - first since V8 detects some plain numbers as dates 14649 // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...). 14650 function ( d, settings ) 14651 { 14652 var decimal = settings.oLanguage.sDecimal; 14653 return _isNumber( d, decimal ) ? 'num'+decimal : null; 14654 }, 14655 14656 // Dates (only those recognised by the browser's Date.parse) 14657 function ( d, settings ) 14658 { 14659 // V8 tries _very_ hard to make a string passed into `Date.parse()` 14660 // valid, so we need to use a regex to restrict date formats. Use a 14661 // plug-in for anything other than ISO8601 style strings 14662 if ( d && !(d instanceof Date) && ! _re_date.test(d) ) { 14663 return null; 14664 } 14665 var parsed = Date.parse(d); 14666 return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null; 14667 }, 14668 14669 // Formatted numbers 14670 function ( d, settings ) 14671 { 14672 var decimal = settings.oLanguage.sDecimal; 14673 return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null; 14674 }, 14675 14676 // HTML numeric 14677 function ( d, settings ) 14678 { 14679 var decimal = settings.oLanguage.sDecimal; 14680 return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null; 14681 }, 14682 14683 // HTML numeric, formatted 14684 function ( d, settings ) 14685 { 14686 var decimal = settings.oLanguage.sDecimal; 14687 return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null; 14688 }, 14689 14690 // HTML (this is strict checking - there must be html) 14691 function ( d, settings ) 14692 { 14693 return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ? 14694 'html' : null; 14695 } 14696 ] ); 14697 14698 14699 14700 // Filter formatting functions. See model.ext.ofnSearch for information about 14701 // what is required from these methods. 14702 // 14703 // Note that additional search methods are added for the html numbers and 14704 // html formatted numbers by `_addNumericSort()` when we know what the decimal 14705 // place is 14706 14707 14708 $.extend( DataTable.ext.type.search, { 14709 html: function ( data ) { 14710 return _empty(data) ? 14711 data : 14712 typeof data === 'string' ? 14713 data 14714 .replace( _re_new_lines, " " ) 14715 .replace( _re_html, "" ) : 14716 ''; 14717 }, 14718 14719 string: function ( data ) { 14720 return _empty(data) ? 14721 data : 14722 typeof data === 'string' ? 14723 data.replace( _re_new_lines, " " ) : 14724 data; 14725 } 14726 } ); 14727 14728 14729 14730 var __numericReplace = function ( d, decimalPlace, re1, re2 ) { 14731 if ( d !== 0 && (!d || d === '-') ) { 14732 return -Infinity; 14733 } 14734 14735 // If a decimal place other than `.` is used, it needs to be given to the 14736 // function so we can detect it and replace with a `.` which is the only 14737 // decimal place Javascript recognises - it is not locale aware. 14738 if ( decimalPlace ) { 14739 d = _numToDecimal( d, decimalPlace ); 14740 } 14741 14742 if ( d.replace ) { 14743 if ( re1 ) { 14744 d = d.replace( re1, '' ); 14745 } 14746 14747 if ( re2 ) { 14748 d = d.replace( re2, '' ); 14749 } 14750 } 14751 14752 return d * 1; 14753 }; 14754 14755 14756 // Add the numeric 'deformatting' functions for sorting and search. This is done 14757 // in a function to provide an easy ability for the language options to add 14758 // additional methods if a non-period decimal place is used. 14759 function _addNumericSort ( decimalPlace ) { 14760 $.each( 14761 { 14762 // Plain numbers 14763 "num": function ( d ) { 14764 return __numericReplace( d, decimalPlace ); 14765 }, 14766 14767 // Formatted numbers 14768 "num-fmt": function ( d ) { 14769 return __numericReplace( d, decimalPlace, _re_formatted_numeric ); 14770 }, 14771 14772 // HTML numeric 14773 "html-num": function ( d ) { 14774 return __numericReplace( d, decimalPlace, _re_html ); 14775 }, 14776 14777 // HTML numeric, formatted 14778 "html-num-fmt": function ( d ) { 14779 return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric ); 14780 } 14781 }, 14782 function ( key, fn ) { 14783 // Add the ordering method 14784 _ext.type.order[ key+decimalPlace+'-pre' ] = fn; 14785 14786 // For HTML types add a search formatter that will strip the HTML 14787 if ( key.match(/^html\-/) ) { 14788 _ext.type.search[ key+decimalPlace ] = _ext.type.search.html; 14789 } 14790 } 14791 ); 14792 } 14793 14794 14795 // Default sort methods 14796 $.extend( _ext.type.order, { 14797 // Dates 14798 "date-pre": function ( d ) { 14799 return Date.parse( d ) || -Infinity; 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 14856 .removeClass( 14857 column.sSortingClass +' '+ 14858 classes.sSortAsc +' '+ 14859 classes.sSortDesc 14860 ) 14861 .addClass( columns[ colIdx ] == 'asc' ? 14862 classes.sSortAsc : columns[ colIdx ] == 'desc' ? 14863 classes.sSortDesc : 14864 column.sSortingClass 14865 ); 14866 } ); 14867 }, 14868 14869 jqueryui: function ( settings, cell, column, classes ) { 14870 $('<div/>') 14871 .addClass( classes.sSortJUIWrapper ) 14872 .append( cell.contents() ) 14873 .append( $('<span/>') 14874 .addClass( classes.sSortIcon+' '+column.sSortingClassJUI ) 14875 ) 14876 .appendTo( cell ); 14877 14878 // Attach a sort listener to update on sort 14879 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) { 14880 if ( settings !== ctx ) { 14881 return; 14882 } 14883 14884 var colIdx = column.idx; 14885 14886 cell 14887 .removeClass( classes.sSortAsc +" "+classes.sSortDesc ) 14888 .addClass( columns[ colIdx ] == 'asc' ? 14889 classes.sSortAsc : columns[ colIdx ] == 'desc' ? 14890 classes.sSortDesc : 14891 column.sSortingClass 14892 ); 14893 14894 cell 14895 .find( 'span.'+classes.sSortIcon ) 14896 .removeClass( 14897 classes.sSortJUIAsc +" "+ 14898 classes.sSortJUIDesc +" "+ 14899 classes.sSortJUI +" "+ 14900 classes.sSortJUIAscAllowed +" "+ 14901 classes.sSortJUIDescAllowed 14902 ) 14903 .addClass( columns[ colIdx ] == 'asc' ? 14904 classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ? 14905 classes.sSortJUIDesc : 14906 column.sSortingClassJUI 14907 ); 14908 } ); 14909 } 14910 } 14911 } ); 14912 14913 /* 14914 * Public helper functions. These aren't used internally by DataTables, or 14915 * called by any of the options passed into DataTables, but they can be used 14916 * externally by developers working with DataTables. They are helper functions 14917 * to make working with DataTables a little bit easier. 14918 */ 14919 14920 var __htmlEscapeEntities = function ( d ) { 14921 return typeof d === 'string' ? 14922 d.replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"') : 14923 d; 14924 }; 14925 14926 /** 14927 * Helpers for `columns.render`. 14928 * 14929 * The options defined here can be used with the `columns.render` initialisation 14930 * option to provide a display renderer. The following functions are defined: 14931 * 14932 * * `number` - Will format numeric data (defined by `columns.data`) for 14933 * display, retaining the original unformatted data for sorting and filtering. 14934 * It takes 5 parameters: 14935 * * `string` - Thousands grouping separator 14936 * * `string` - Decimal point indicator 14937 * * `integer` - Number of decimal points to show 14938 * * `string` (optional) - Prefix. 14939 * * `string` (optional) - Postfix (/suffix). 14940 * * `text` - Escape HTML to help prevent XSS attacks. It has no optional 14941 * parameters. 14942 * 14943 * @example 14944 * // Column definition using the number renderer 14945 * { 14946 * data: "salary", 14947 * render: $.fn.dataTable.render.number( '\'', '.', 0, '$' ) 14948 * } 14949 * 14950 * @namespace 14951 */ 14952 DataTable.render = { 14953 number: function ( thousands, decimal, precision, prefix, postfix ) { 14954 return { 14955 display: function ( d ) { 14956 if ( typeof d !== 'number' && typeof d !== 'string' ) { 14957 return d; 14958 } 14959 14960 var negative = d < 0 ? '-' : ''; 14961 var flo = parseFloat( d ); 14962 14963 // If NaN then there isn't much formatting that we can do - just 14964 // return immediately, escaping any HTML (this was supposed to 14965 // be a number after all) 14966 if ( isNaN( flo ) ) { 14967 return __htmlEscapeEntities( d ); 14968 } 14969 14970 flo = flo.toFixed( precision ); 14971 d = Math.abs( flo ); 14972 14973 var intPart = parseInt( d, 10 ); 14974 var floatPart = precision ? 14975 decimal+(d - intPart).toFixed( precision ).substring( 2 ): 14976 ''; 14977 14978 return negative + (prefix||'') + 14979 intPart.toString().replace( 14980 /\B(?=(\d{3})+(?!\d))/g, thousands 14981 ) + 14982 floatPart + 14983 (postfix||''); 14984 } 14985 }; 14986 }, 14987 14988 text: function () { 14989 return { 14990 display: __htmlEscapeEntities 14991 }; 14992 } 14993 }; 14994 14995 14996 /* 14997 * This is really a good bit rubbish this method of exposing the internal methods 14998 * publicly... - To be fixed in 2.0 using methods on the prototype 14999 */ 15000 15001 15002 /** 15003 * Create a wrapper function for exporting an internal functions to an external API. 15004 * @param {string} fn API function name 15005 * @returns {function} wrapped function 15006 * @memberof DataTable#internal 15007 */ 15008 function _fnExternApiFunc (fn) 15009 { 15010 return function() { 15011 var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat( 15012 Array.prototype.slice.call(arguments) 15013 ); 15014 return DataTable.ext.internal[fn].apply( this, args ); 15015 }; 15016 } 15017 15018 15019 /** 15020 * Reference to internal functions for use by plug-in developers. Note that 15021 * these methods are references to internal functions and are considered to be 15022 * private. If you use these methods, be aware that they are liable to change 15023 * between versions. 15024 * @namespace 15025 */ 15026 $.extend( DataTable.ext.internal, { 15027 _fnExternApiFunc: _fnExternApiFunc, 15028 _fnBuildAjax: _fnBuildAjax, 15029 _fnAjaxUpdate: _fnAjaxUpdate, 15030 _fnAjaxParameters: _fnAjaxParameters, 15031 _fnAjaxUpdateDraw: _fnAjaxUpdateDraw, 15032 _fnAjaxDataSrc: _fnAjaxDataSrc, 15033 _fnAddColumn: _fnAddColumn, 15034 _fnColumnOptions: _fnColumnOptions, 15035 _fnAdjustColumnSizing: _fnAdjustColumnSizing, 15036 _fnVisibleToColumnIndex: _fnVisibleToColumnIndex, 15037 _fnColumnIndexToVisible: _fnColumnIndexToVisible, 15038 _fnVisbleColumns: _fnVisbleColumns, 15039 _fnGetColumns: _fnGetColumns, 15040 _fnColumnTypes: _fnColumnTypes, 15041 _fnApplyColumnDefs: _fnApplyColumnDefs, 15042 _fnHungarianMap: _fnHungarianMap, 15043 _fnCamelToHungarian: _fnCamelToHungarian, 15044 _fnLanguageCompat: _fnLanguageCompat, 15045 _fnBrowserDetect: _fnBrowserDetect, 15046 _fnAddData: _fnAddData, 15047 _fnAddTr: _fnAddTr, 15048 _fnNodeToDataIndex: _fnNodeToDataIndex, 15049 _fnNodeToColumnIndex: _fnNodeToColumnIndex, 15050 _fnGetCellData: _fnGetCellData, 15051 _fnSetCellData: _fnSetCellData, 15052 _fnSplitObjNotation: _fnSplitObjNotation, 15053 _fnGetObjectDataFn: _fnGetObjectDataFn, 15054 _fnSetObjectDataFn: _fnSetObjectDataFn, 15055 _fnGetDataMaster: _fnGetDataMaster, 15056 _fnClearTable: _fnClearTable, 15057 _fnDeleteIndex: _fnDeleteIndex, 15058 _fnInvalidate: _fnInvalidate, 15059 _fnGetRowElements: _fnGetRowElements, 15060 _fnCreateTr: _fnCreateTr, 15061 _fnBuildHead: _fnBuildHead, 15062 _fnDrawHead: _fnDrawHead, 15063 _fnDraw: _fnDraw, 15064 _fnReDraw: _fnReDraw, 15065 _fnAddOptionsHtml: _fnAddOptionsHtml, 15066 _fnDetectHeader: _fnDetectHeader, 15067 _fnGetUniqueThs: _fnGetUniqueThs, 15068 _fnFeatureHtmlFilter: _fnFeatureHtmlFilter, 15069 _fnFilterComplete: _fnFilterComplete, 15070 _fnFilterCustom: _fnFilterCustom, 15071 _fnFilterColumn: _fnFilterColumn, 15072 _fnFilter: _fnFilter, 15073 _fnFilterCreateSearch: _fnFilterCreateSearch, 15074 _fnEscapeRegex: _fnEscapeRegex, 15075 _fnFilterData: _fnFilterData, 15076 _fnFeatureHtmlInfo: _fnFeatureHtmlInfo, 15077 _fnUpdateInfo: _fnUpdateInfo, 15078 _fnInfoMacros: _fnInfoMacros, 15079 _fnInitialise: _fnInitialise, 15080 _fnInitComplete: _fnInitComplete, 15081 _fnLengthChange: _fnLengthChange, 15082 _fnFeatureHtmlLength: _fnFeatureHtmlLength, 15083 _fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate, 15084 _fnPageChange: _fnPageChange, 15085 _fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing, 15086 _fnProcessingDisplay: _fnProcessingDisplay, 15087 _fnFeatureHtmlTable: _fnFeatureHtmlTable, 15088 _fnScrollDraw: _fnScrollDraw, 15089 _fnApplyToChildren: _fnApplyToChildren, 15090 _fnCalculateColumnWidths: _fnCalculateColumnWidths, 15091 _fnThrottle: _fnThrottle, 15092 _fnConvertToWidth: _fnConvertToWidth, 15093 _fnGetWidestNode: _fnGetWidestNode, 15094 _fnGetMaxLenString: _fnGetMaxLenString, 15095 _fnStringToCss: _fnStringToCss, 15096 _fnSortFlatten: _fnSortFlatten, 15097 _fnSort: _fnSort, 15098 _fnSortAria: _fnSortAria, 15099 _fnSortListener: _fnSortListener, 15100 _fnSortAttachListener: _fnSortAttachListener, 15101 _fnSortingClasses: _fnSortingClasses, 15102 _fnSortData: _fnSortData, 15103 _fnSaveState: _fnSaveState, 15104 _fnLoadState: _fnLoadState, 15105 _fnSettingsFromNode: _fnSettingsFromNode, 15106 _fnLog: _fnLog, 15107 _fnMap: _fnMap, 15108 _fnBindAction: _fnBindAction, 15109 _fnCallbackReg: _fnCallbackReg, 15110 _fnCallbackFire: _fnCallbackFire, 15111 _fnLengthOverflow: _fnLengthOverflow, 15112 _fnRenderer: _fnRenderer, 15113 _fnDataSource: _fnDataSource, 15114 _fnRowAttributes: _fnRowAttributes, 15115 _fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant 15116 // in 1.10, so this dead-end function is 15117 // added to prevent errors 15118 } ); 15119 15120 15121 // jQuery access 15122 $.fn.dataTable = DataTable; 15123 15124 // Provide access to the host jQuery object (circular reference) 15125 DataTable.$ = $; 15126 15127 // Legacy aliases 15128 $.fn.dataTableSettings = DataTable.settings; 15129 $.fn.dataTableExt = DataTable.ext; 15130 15131 // With a capital `D` we return a DataTables API instance rather than a 15132 // jQuery object 15133 $.fn.DataTable = function ( opts ) { 15134 return $(this).dataTable( opts ).api(); 15135 }; 15136 15137 // All properties that are available to $.fn.dataTable should also be 15138 // available on $.fn.DataTable 15139 $.each( DataTable, function ( prop, val ) { 15140 $.fn.DataTable[ prop ] = val; 15141 } ); 15142 15143 15144 // Information about events fired by DataTables - for documentation. 15145 /** 15146 * Draw event, fired whenever the table is redrawn on the page, at the same 15147 * point as fnDrawCallback. This may be useful for binding events or 15148 * performing calculations when the table is altered at all. 15149 * @name DataTable#draw.dt 15150 * @event 15151 * @param {event} e jQuery event object 15152 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15153 */ 15154 15155 /** 15156 * Search event, fired when the searching applied to the table (using the 15157 * built-in global search, or column filters) is altered. 15158 * @name DataTable#search.dt 15159 * @event 15160 * @param {event} e jQuery event object 15161 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15162 */ 15163 15164 /** 15165 * Page change event, fired when the paging of the table is altered. 15166 * @name DataTable#page.dt 15167 * @event 15168 * @param {event} e jQuery event object 15169 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15170 */ 15171 15172 /** 15173 * Order event, fired when the ordering applied to the table is altered. 15174 * @name DataTable#order.dt 15175 * @event 15176 * @param {event} e jQuery event object 15177 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15178 */ 15179 15180 /** 15181 * DataTables initialisation complete event, fired when the table is fully 15182 * drawn, including Ajax data loaded, if Ajax data is required. 15183 * @name DataTable#init.dt 15184 * @event 15185 * @param {event} e jQuery event object 15186 * @param {object} oSettings DataTables settings object 15187 * @param {object} json The JSON object request from the server - only 15188 * present if client-side Ajax sourced data is used</li></ol> 15189 */ 15190 15191 /** 15192 * State save event, fired when the table has changed state a new state save 15193 * is required. This event allows modification of the state saving object 15194 * prior to actually doing the save, including addition or other state 15195 * properties (for plug-ins) or modification of a DataTables core property. 15196 * @name DataTable#stateSaveParams.dt 15197 * @event 15198 * @param {event} e jQuery event object 15199 * @param {object} oSettings DataTables settings object 15200 * @param {object} json The state information to be saved 15201 */ 15202 15203 /** 15204 * State load event, fired when the table is loading state from the stored 15205 * data, but prior to the settings object being modified by the saved state 15206 * - allowing modification of the saved state is required or loading of 15207 * state for a plug-in. 15208 * @name DataTable#stateLoadParams.dt 15209 * @event 15210 * @param {event} e jQuery event object 15211 * @param {object} oSettings DataTables settings object 15212 * @param {object} json The saved state information 15213 */ 15214 15215 /** 15216 * State loaded event, fired when state has been loaded from stored data and 15217 * the settings object has been modified by the loaded data. 15218 * @name DataTable#stateLoaded.dt 15219 * @event 15220 * @param {event} e jQuery event object 15221 * @param {object} oSettings DataTables settings object 15222 * @param {object} json The saved state information 15223 */ 15224 15225 /** 15226 * Processing event, fired when DataTables is doing some kind of processing 15227 * (be it, order, searcg or anything else). It can be used to indicate to 15228 * the end user that there is something happening, or that something has 15229 * finished. 15230 * @name DataTable#processing.dt 15231 * @event 15232 * @param {event} e jQuery event object 15233 * @param {object} oSettings DataTables settings object 15234 * @param {boolean} bShow Flag for if DataTables is doing processing or not 15235 */ 15236 15237 /** 15238 * Ajax (XHR) event, fired whenever an Ajax request is completed from a 15239 * request to made to the server for new data. This event is called before 15240 * DataTables processed the returned data, so it can also be used to pre- 15241 * process the data returned from the server, if needed. 15242 *
15243 * Note that this trigger is called in `fnServerData`, if you override 15244 * `fnServerData` and which to use this event, you need to trigger it in you 15245 * success function. 15246 * @name DataTable#xhr.dt 15247 * @event 15248 * @param {event} e jQuery event object 15249 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15250 * @param {object} json JSON returned from the server 15251 * 15252 * @example 15253 * // Use a custom property returned from the server in another DOM element 15254 * $('#table').dataTable().on('xhr.dt', function (e, settings, json) { 15255 * $('#status').html( json.status ); 15256 * } ); 15257 * 15258 * @example 15259 * // Pre-process the data returned from the server 15260 * $('#table').dataTable().on('xhr.dt', function (e, settings, json) { 15261 * for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) { 15262 * json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two; 15263 * } 15264 * // Note no return - manipulate the data directly in the JSON object. 15265 * } ); 15266 */ 15267 15268 /** 15269 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy 15270 * or passing the bDestroy:true parameter in the initialisation object. This 15271 * can be used to remove bound events, added DOM nodes, etc. 15272 * @name DataTable#destroy.dt 15273 * @event 15274 * @param {event} e jQuery event object 15275 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15276 */ 15277 15278 /** 15279 * Page length change event, fired when number of records to show on each 15280 * page (the length) is changed. 15281 * @name DataTable#length.dt 15282 * @event 15283 * @param {event} e jQuery event object 15284 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15285 * @param {integer} len New length 15286 */ 15287 15288 /** 15289 * Column sizing has changed. 15290 * @name DataTable#column-sizing.dt 15291 * @event 15292 * @param {event} e jQuery event object 15293 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15294 */ 15295 15296 /** 15297 * Column visibility has changed. 15298 * @name DataTable#column-visibility.dt 15299 * @event 15300 * @param {event} e jQuery event object 15301 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 15302 * @param {int} column Column index 15303 * @param {bool} vis `false` if column now hidden, or `true` if visible 15304 */ 15305 15306 return $.fn.dataTable; 15307}));
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.