1 |
/** |
2 |
* Perform a jQuery selector action on the table's TR elements (from the tbody) and |
3 |
* return the resulting jQuery object. |
4 |
* @param {string|node|jQuery} sSelector jQuery selector or node collection to act on |
5 |
* @param {object} [oOpts] Optional parameters for modifying the rows to be included |
6 |
* @param {string} [oOpts.filter=none] Select TR elements that meet the current filter |
7 |
* criterion ("applied") or all TR elements (i.e. no filter). |
8 |
* @param {string} [oOpts.order=current] Order of the TR elements in the processed array. |
9 |
* Can be either 'current', whereby the current sorting of the table is used, or |
10 |
* 'original' whereby the original order the data was read into the table is used. |
11 |
* @param {string} [oOpts.page=all] Limit the selection to the currently displayed page |
12 |
* ("current") or not ("all"). If 'current' is given, then order is assumed to be |
13 |
* 'current' and filter is 'applied', regardless of what they might be given as. |
14 |
* @returns {object} jQuery object, filtered by the given selector. |
15 |
* @dtopt API |
16 |
* |
17 |
* @example |
18 |
* $(document).ready(function() { |
19 |
* var oTable = $('#example').dataTable(); |
20 |
* |
21 |
* // Highlight every second row |
22 |
* oTable.$('tr:odd').css('backgroundColor', 'blue'); |
23 |
* } ); |
24 |
* |
25 |
* @example |
26 |
* $(document).ready(function() { |
27 |
* var oTable = $('#example').dataTable(); |
28 |
* |
29 |
* // Filter to rows with 'Webkit' in them, add a background colour and then |
30 |
* // remove the filter, thus highlighting the 'Webkit' rows only. |
31 |
* oTable.fnFilter('Webkit'); |
32 |
* oTable.$('tr', {"filter": "applied"}).css('backgroundColor', 'blue'); |
33 |
* oTable.fnFilter(''); |
34 |
* } ); |
35 |
*/ |
36 |
this.$ = function ( sSelector, oOpts ) |
37 |
{ |
38 |
var i, iLen, a = [], tr; |
39 |
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); |
40 |
var aoData = oSettings.aoData; |
41 |
var aiDisplay = oSettings.aiDisplay; |
42 |
var aiDisplayMaster = oSettings.aiDisplayMaster; |
43 |
|
44 |
if ( !oOpts ) |
45 |
{ |
46 |
oOpts = {}; |
47 |
} |
48 |
|
49 |
oOpts = $.extend( {}, { |
50 |
"filter": "none", // applied |
51 |
"order": "current", // "original" |
52 |
"page": "all" // current |
53 |
}, oOpts ); |
54 |
|
55 |
// Current page implies that order=current and fitler=applied, since it is fairly |
56 |
// senseless otherwise |
57 |
if ( oOpts.page == 'current' ) |
58 |
{ |
59 |
for ( i=oSettings._iDisplayStart, iLen=oSettings.fnDisplayEnd() ; i<iLen ; i++ ) |
60 |
{ |
61 |
tr = aoData[ aiDisplay[i] ].nTr; |
62 |
if ( tr ) |
63 |
{ |
64 |
a.push( tr ); |
65 |
} |
66 |
} |
67 |
} |
68 |
else if ( oOpts.order == "current" && oOpts.filter == "none" ) |
69 |
{ |
70 |
for ( i=0, iLen=aiDisplayMaster.length ; i<iLen ; i++ ) |
71 |
{ |
72 |
tr = aoData[ aiDisplayMaster[i] ].nTr; |
73 |
if ( tr ) |
74 |
{ |
75 |
a.push( tr ); |
76 |
} |
77 |
} |
78 |
} |
79 |
else if ( oOpts.order == "current" && oOpts.filter == "applied" ) |
80 |
{ |
81 |
for ( i=0, iLen=aiDisplay.length ; i<iLen ; i++ ) |
82 |
{ |
83 |
tr = aoData[ aiDisplay[i] ].nTr; |
84 |
if ( tr ) |
85 |
{ |
86 |
a.push( tr ); |
87 |
} |
88 |
} |
89 |
} |
90 |
else if ( oOpts.order == "original" && oOpts.filter == "none" ) |
91 |
{ |
92 |
for ( i=0, iLen=aoData.length ; i<iLen ; i++ ) |
93 |
{ |
94 |
tr = aoData[ i ].nTr ; |
95 |
if ( tr ) |
96 |
{ |
97 |
a.push( tr ); |
98 |
} |
99 |
} |
100 |
} |
101 |
else if ( oOpts.order == "original" && oOpts.filter == "applied" ) |
102 |
{ |
103 |
for ( i=0, iLen=aoData.length ; i<iLen ; i++ ) |
104 |
{ |
105 |
tr = aoData[ i ].nTr; |
106 |
if ( $.inArray( i, aiDisplay ) !== -1 && tr ) |
107 |
{ |
108 |
a.push( tr ); |
109 |
} |
110 |
} |
111 |
} |
112 |
else |
113 |
{ |
114 |
_fnLog( oSettings, 1, "Unknown selection options" ); |
115 |
} |
116 |
|
117 |
/* We need to filter on the TR elements and also 'find' in their descendants |
118 |
* to make the selector act like it would in a full table - so we need |
119 |
* to build both results and then combine them together |
120 |
*/ |
121 |
var jqA = $(a); |
122 |
var jqTRs = jqA.filter( sSelector ); |
123 |
var jqDescendants = jqA.find( sSelector ); |
124 |
|
125 |
return $( [].concat($.makeArray(jqTRs), $.makeArray(jqDescendants)) ); |
126 |
}; |
127 |
|
128 |
|
129 |
/** |
130 |
* Almost identical to $ in operation, but in this case returns the data for the matched |
131 |
* rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes |
132 |
* rather than any descendants, so the data can be obtained for the row/cell. If matching |
133 |
* rows are found, the data returned is the original data array/object that was used to |
134 |
* create the row (or a generated array if from a DOM source). |
135 |
* |
136 |
* This method is often useful in-combination with $ where both functions are given the |
137 |
* same parameters and the array indexes will match identically. |
138 |
* @param {string|node|jQuery} sSelector jQuery selector or node collection to act on |
139 |
* @param {object} [oOpts] Optional parameters for modifying the rows to be included |
140 |
* @param {string} [oOpts.filter=none] Select elements that meet the current filter |
141 |
* criterion ("applied") or all elements (i.e. no filter). |
142 |
* @param {string} [oOpts.order=current] Order of the data in the processed array. |
143 |
* Can be either 'current', whereby the current sorting of the table is used, or |
144 |
* 'original' whereby the original order the data was read into the table is used. |
145 |
* @param {string} [oOpts.page=all] Limit the selection to the currently displayed page |
146 |
* ("current") or not ("all"). If 'current' is given, then order is assumed to be |
147 |
* 'current' and filter is 'applied', regardless of what they might be given as. |
148 |
* @returns {array} Data for the matched elements. If any elements, as a result of the |
149 |
* selector, were not TR, TD or TH elements in the DataTable, they will have a null |
150 |
* entry in the array. |
151 |
* @dtopt API |
152 |
* |
153 |
* @example |
154 |
* $(document).ready(function() { |
155 |
* var oTable = $('#example').dataTable(); |
156 |
* |
157 |
* // Get the data from the first row in the table |
158 |
* var data = oTable._('tr:first'); |
159 |
* |
160 |
* // Do something useful with the data |
161 |
* alert( "First cell is: "+data[0] ); |
162 |
* } ); |
163 |
* |
164 |
* @example |
165 |
* $(document).ready(function() { |
166 |
* var oTable = $('#example').dataTable(); |
167 |
* |
168 |
* // Filter to 'Webkit' and get all data for |
169 |
* oTable.fnFilter('Webkit'); |
170 |
* var data = oTable._('tr', {"filter": "applied"}); |
171 |
* |
172 |
* // Do something with the data |
173 |
* alert( data.length+" rows matched the filter" ); |
174 |
* } ); |
175 |
*/ |
176 |
this._ = function ( sSelector, oOpts ) |
177 |
{ |
178 |
var aOut = []; |
179 |
var i, iLen, iIndex; |
180 |
var aTrs = this.$( sSelector, oOpts ); |
181 |
|
182 |
for ( i=0, iLen=aTrs.length ; i<iLen ; i++ ) |
183 |
{ |
184 |
aOut.push( this.fnGetData(aTrs[i]) ); |
185 |
} |
186 |
|
187 |
return aOut; |
188 |
}; |
189 |
|
190 |
|
191 |
/** |
192 |
* Add a single new row or multiple rows of data to the table. Please note |
193 |
* that this is suitable for client-side processing only - if you are using |
194 |
* server-side processing (i.e. "bServerSide": true), then to add data, you |
195 |
* must add it to the data source, i.e. the server-side, through an Ajax call. |
196 |
* @param {array|object} mData The data to be added to the table. This can be: |
197 |
* <ul> |
198 |
* <li>1D array of data - add a single row with the data provided</li> |
199 |
* <li>2D array of arrays - add multiple rows in a single call</li> |
200 |
* <li>object - data object when using <i>mData</i></li> |
201 |
* <li>array of objects - multiple data objects when using <i>mData</i></li> |
202 |
* </ul> |
203 |
* @param {bool} [bRedraw=true] redraw the table or not |
204 |
* @returns {array} An array of integers, representing the list of indexes in |
205 |
* <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to |
206 |
* the table. |
207 |
* @dtopt API |
208 |
* |
209 |
* @example |
210 |
* // Global var for counter |
211 |
* var giCount = 2; |
212 |
* |
213 |
* $(document).ready(function() { |
214 |
* $('#example').dataTable(); |
215 |
* } ); |
216 |
* |
217 |
* function fnClickAddRow() { |
218 |
* $('#example').dataTable().fnAddData( [ |
219 |
* giCount+".1", |
220 |
* giCount+".2", |
221 |
* giCount+".3", |
222 |
* giCount+".4" ] |
223 |
* ); |
224 |
* |
225 |
* giCount++; |
226 |
* } |
227 |
*/ |
228 |
this.fnAddData = function( mData, bRedraw ) |
229 |
{ |
230 |
if ( mData.length === 0 ) |
231 |
{ |
232 |
return []; |
233 |
} |
234 |
|
235 |
var aiReturn = []; |
236 |
var iTest; |
237 |
|
238 |
/* Find settings from table node */ |
239 |
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); |
240 |
|
241 |
/* Check if we want to add multiple rows or not */ |
242 |
if ( typeof mData[0] === "object" && mData[0] !== null ) |
243 |
{ |
244 |
for ( var i=0 ; i<mData.length ; i++ ) |
245 |
{ |
246 |
iTest = _fnAddData( oSettings, mData[i] ); |
247 |
if ( iTest == -1 ) |
248 |
{ |
249 |
return aiReturn; |
250 |
} |
251 |
aiReturn.push( iTest ); |
252 |
} |
253 |
} |
254 |
else |
255 |
{ |
256 |
iTest = _fnAddData( oSettings, mData ); |
257 |
if ( iTest == -1 ) |
258 |
{ |
259 |
return aiReturn; |
260 |
} |
261 |
aiReturn.push( iTest ); |
262 |
} |
263 |
|
264 |
oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); |
265 |
|
266 |
if ( bRedraw === undefined || bRedraw ) |
267 |
{ |
268 |
_fnReDraw( oSettings ); |
269 |
} |
270 |
return aiReturn; |
271 |
}; |
272 |
|
273 |
|
274 |
/** |
275 |
* This function will make DataTables recalculate the column sizes, based on the data |
276 |
* contained in the table and the sizes applied to the columns (in the DOM, CSS or |
277 |
* through the sWidth parameter). This can be useful when the width of the table's |
278 |
* parent element changes (for example a window resize). |
279 |
* @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to |
280 |
* @dtopt API |
281 |
* |
282 |
* @example |
283 |
* $(document).ready(function() { |
284 |
* var oTable = $('#example').dataTable( { |
285 |
* "sScrollY": "200px", |
286 |
* "bPaginate": false |
287 |
* } ); |
288 |
* |
289 |
* $(window).bind('resize', function () { |
290 |
* oTable.fnAdjustColumnSizing(); |
291 |
* } ); |
292 |
* } ); |
293 |
*/ |
294 |
this.fnAdjustColumnSizing = function ( bRedraw ) |
295 |
{ |
296 |
var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]); |
297 |
_fnAdjustColumnSizing( oSettings ); |
298 |
|
299 |
if ( bRedraw === undefined || bRedraw ) |
300 |
{ |
301 |
this.fnDraw( false ); |
302 |
} |
303 |
else if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" ) |
304 |
{ |
305 |
/* If not redrawing, but scrolling, we want to apply the new column sizes anyway */ |
306 |
this.oApi._fnScrollDraw(oSettings); |
307 |
} |
308 |
}; |
309 |
|
310 |
|
311 |
/** |
312 |
* Quickly and simply clear a table |
313 |
* @param {bool} [bRedraw=true] redraw the table or not |
314 |
* @dtopt API |
315 |
* |
316 |
* @example |
317 |
* $(document).ready(function() { |
318 |
* var oTable = $('#example').dataTable(); |
319 |
* |
320 |
* // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...) |
321 |
* oTable.fnClearTable(); |
322 |
* } ); |
323 |
*/ |
324 |
this.fnClearTable = function( bRedraw ) |
325 |
{ |
326 |
/* Find settings from table node */ |
327 |
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); |
328 |
_fnClearTable( oSettings ); |
329 |
|
330 |
if ( bRedraw === undefined || bRedraw ) |
331 |
{ |
332 |
_fnDraw( oSettings ); |
333 |
} |
334 |
}; |
335 |
|
336 |
|
337 |
/** |
338 |
* The exact opposite of 'opening' a row, this function will close any rows which |
339 |
* are currently 'open'. |
340 |
* @param {node} nTr the table row to 'close' |
341 |
* @returns {int} 0 on success, or 1 if failed (can't find the row) |
342 |
* @dtopt API |
343 |
* |
344 |
* @example |
345 |
* $(document).ready(function() { |
346 |
* var oTable; |
347 |
* |
348 |
* // 'open' an information row when a row is clicked on |
349 |
* $('#example tbody tr').click( function () { |
350 |
* if ( oTable.fnIsOpen(this) ) { |
351 |
* oTable.fnClose( this ); |
352 |
* } else { |
353 |
* oTable.fnOpen( this, "Temporary row opened", "info_row" ); |
354 |
* } |
355 |
* } ); |
356 |
* |
357 |
* oTable = $('#example').dataTable(); |
358 |
* } ); |
359 |
*/ |
360 |
this.fnClose = function( nTr ) |
361 |
{ |
362 |
/* Find settings from table node */ |
363 |
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); |
364 |
|
365 |
for ( var i=0 ; i<oSettings.aoOpenRows.length ; i++ ) |
366 |
{ |
367 |
if ( oSettings.aoOpenRows[i].nParent == nTr ) |
368 |
{ |
369 |
var nTrParent = oSettings.aoOpenRows[i].nTr.parentNode; |
370 |
if ( nTrParent ) |
371 |
{ |
372 |
/* Remove it if it is currently on display */ |
373 |
nTrParent.removeChild( oSettings.aoOpenRows[i].nTr ); |
374 |
} |
375 |
oSettings.aoOpenRows.splice( i, 1 ); |
376 |
return 0; |
377 |
} |
378 |
} |
379 |
return 1; |
380 |
}; |
381 |
|
382 |
|
383 |
/** |
384 |
* Remove a row for the table |
385 |
* @param {mixed} mTarget The index of the row from aoData to be deleted, or |
386 |
* the TR element you want to delete |
387 |
* @param {function|null} [fnCallBack] Callback function |
388 |
* @param {bool} [bRedraw=true] Redraw the table or not |
389 |
* @returns {array} The row that was deleted |
390 |
* @dtopt API |
391 |
* |
392 |
* @example |
393 |
* $(document).ready(function() { |
394 |
* var oTable = $('#example').dataTable(); |
395 |
* |
396 |
* // Immediately remove the first row |
397 |
* oTable.fnDeleteRow( 0 ); |
398 |
* } ); |
399 |
*/ |
400 |
this.fnDeleteRow = function( mTarget, fnCallBack, bRedraw ) |
401 |
{ |
402 |
/* Find settings from table node */ |
403 |
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); |
404 |
var i, iLen, iAODataIndex; |
405 |
|
406 |
iAODataIndex = (typeof mTarget === 'object') ? |
407 |
_fnNodeToDataIndex(oSettings, mTarget) : mTarget; |
408 |
|
409 |
/* Return the data array from this row */ |
410 |
var oData = oSettings.aoData.splice( iAODataIndex, 1 ); |
411 |
|
412 |
/* Update the _DT_RowIndex parameter */ |
413 |
for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ ) |
414 |
{ |
415 |
if ( oSettings.aoData[i].nTr !== null ) |
416 |
{ |
417 |
oSettings.aoData[i].nTr._DT_RowIndex = i; |
418 |
} |
419 |
} |
420 |
|
421 |
/* Remove the target row from the search array */ |
422 |
var iDisplayIndex = $.inArray( iAODataIndex, oSettings.aiDisplay ); |
423 |
oSettings.asDataSearch.splice( iDisplayIndex, 1 ); |
424 |
|
425 |
/* Delete from the display arrays */ |
426 |
_fnDeleteIndex( oSettings.aiDisplayMaster, iAODataIndex ); |
427 |
_fnDeleteIndex( oSettings.aiDisplay, iAODataIndex ); |
428 |
|
429 |
/* If there is a user callback function - call it */ |
430 |
if ( typeof fnCallBack === "function" ) |
431 |
{ |
432 |
fnCallBack.call( this, oSettings, oData ); |
433 |
} |
434 |
|
435 |
/* Check for an 'overflow' they case for displaying the table */ |
436 |
if ( oSettings._iDisplayStart >= oSettings.fnRecordsDisplay() ) |
437 |
{ |
438 |
oSettings._iDisplayStart -= oSettings._iDisplayLength; |
439 |
if ( oSettings._iDisplayStart < 0 ) |
440 |
{ |
441 |
oSettings._iDisplayStart = 0; |
442 |
} |
443 |
} |
444 |
|
445 |
if ( bRedraw === undefined || bRedraw ) |
446 |
{ |
447 |
_fnCalculateEnd( oSettings ); |
448 |
_fnDraw( oSettings ); |
449 |
} |
450 |
|
451 |
return oData; |
452 |
}; |
453 |
|
454 |
|
455 |
/** |
456 |
* Restore the table to it's original state in the DOM by removing all of DataTables |
457 |
* enhancements, alterations to the DOM structure of the table and event listeners. |
458 |
* @param {boolean} [bRemove=false] Completely remove the table from the DOM |
459 |
* @dtopt API |
460 |
* |
461 |
* @example |
462 |
* $(document).ready(function() { |
463 |
* // This example is fairly pointless in reality, but shows how fnDestroy can be used |
464 |
* var oTable = $('#example').dataTable(); |
465 |
* oTable.fnDestroy(); |
466 |
* } ); |
467 |
*/ |
468 |
this.fnDestroy = function ( bRemove ) |
469 |
{ |
470 |
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); |
471 |
var nOrig = oSettings.nTableWrapper.parentNode; |
472 |
var nBody = oSettings.nTBody; |
473 |
var i, iLen; |
474 |
|
475 |
bRemove = (bRemove===undefined) ? false : bRemove; |
476 |
|
477 |
/* Flag to note that the table is currently being destroyed - no action should be taken */ |
478 |
oSettings.bDestroying = true; |
479 |
|
480 |
/* Fire off the destroy callbacks for plug-ins etc */ |
481 |
_fnCallbackFire( oSettings, "aoDestroyCallback", "destroy", [oSettings] ); |
482 |
|
483 |
/* If the table is not being removed, restore the hidden columns */ |
484 |
if ( !bRemove ) |
485 |
{ |
486 |
for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) |
487 |
{ |
488 |
if ( oSettings.aoColumns[i].bVisible === false ) |
489 |
{ |
490 |
this.fnSetColumnVis( i, true ); |
491 |
} |
492 |
} |
493 |
} |
494 |
|
495 |
/* Blitz all DT events */ |
496 |
$(oSettings.nTableWrapper).find('*').andSelf().unbind('.DT'); |
497 |
|
498 |
/* If there is an 'empty' indicator row, remove it */ |
499 |
$('tbody>tr>td.'+oSettings.oClasses.sRowEmpty, oSettings.nTable).parent().remove(); |
500 |
|
501 |
/* When scrolling we had to break the table up - restore it */ |
502 |
if ( oSettings.nTable != oSettings.nTHead.parentNode ) |
503 |
{ |
504 |
$(oSettings.nTable).children('thead').remove(); |
505 |
oSettings.nTable.appendChild( oSettings.nTHead ); |
506 |
} |
507 |
|
508 |
if ( oSettings.nTFoot && oSettings.nTable != oSettings.nTFoot.parentNode ) |
509 |
{ |
510 |
$(oSettings.nTable).children('tfoot').remove(); |
511 |
oSettings.nTable.appendChild( oSettings.nTFoot ); |
512 |
} |
513 |
|
514 |
/* Remove the DataTables generated nodes, events and classes */ |
515 |
oSettings.nTable.parentNode.removeChild( oSettings.nTable ); |
516 |
$(oSettings.nTableWrapper).remove(); |
517 |
|
518 |
oSettings.aaSorting = []; |
519 |
oSettings.aaSortingFixed = []; |
520 |
_fnSortingClasses( oSettings ); |
521 |
|
522 |
$(_fnGetTrNodes( oSettings )).removeClass( oSettings.asStripeClasses.join(' ') ); |
523 |
|
524 |
$('th, td', oSettings.nTHead).removeClass( [ |
525 |
oSettings.oClasses.sSortable, |
526 |
oSettings.oClasses.sSortableAsc, |
527 |
oSettings.oClasses.sSortableDesc, |
528 |
oSettings.oClasses.sSortableNone ].join(' ') |
529 |
); |
530 |
if ( oSettings.bJUI ) |
531 |
{ |
532 |
$('th span.'+oSettings.oClasses.sSortIcon |
533 |
+ ', td span.'+oSettings.oClasses.sSortIcon, oSettings.nTHead).remove(); |
534 |
|
535 |
$('th, td', oSettings.nTHead).each( function () { |
536 |
var jqWrapper = $('div.'+oSettings.oClasses.sSortJUIWrapper, this); |
537 |
var kids = jqWrapper.contents(); |
538 |
$(this).append( kids ); |
539 |
jqWrapper.remove(); |
540 |
} ); |
541 |
} |
542 |
|
543 |
/* Add the TR elements back into the table in their original order */ |
544 |
if ( !bRemove && oSettings.nTableReinsertBefore ) |
545 |
{ |
546 |
nOrig.insertBefore( oSettings.nTable, oSettings.nTableReinsertBefore ); |
547 |
} |
548 |
else if ( !bRemove ) |
549 |
{ |
550 |
nOrig.appendChild( oSettings.nTable ); |
551 |
} |
552 |
|
553 |
for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ ) |
554 |
{ |
555 |
if ( oSettings.aoData[i].nTr !== null ) |
556 |
{ |
557 |
nBody.appendChild( oSettings.aoData[i].nTr ); |
558 |
} |
559 |
} |
560 |
|
561 |
/* Restore the width of the original table */ |
562 |
if ( oSettings.oFeatures.bAutoWidth === true ) |
563 |
{ |
564 |
oSettings.nTable.style.width = _fnStringToCss(oSettings.sDestroyWidth); |
565 |
} |
566 |
|
567 |
/* If the were originally stripe classes - then we add them back here. Note |
568 |
* this is not fool proof (for example if not all rows had stripe classes - but |
569 |
* it's a good effort without getting carried away |
570 |
*/ |
571 |
iLen = oSettings.asDestroyStripes.length; |
572 |
if (iLen) |
573 |
{ |
574 |
var anRows = $(nBody).children('tr'); |
575 |
for ( i=0 ; i<iLen ; i++ ) |
576 |
{ |
577 |
anRows.filter(':nth-child(' + iLen + 'n + ' + i + ')').addClass( oSettings.asDestroyStripes[i] ); |
578 |
} |
579 |
} |
580 |
|
581 |
/* Remove the settings object from the settings array */ |
582 |
for ( i=0, iLen=DataTable.settings.length ; i<iLen ; i++ ) |
583 |
{ |
584 |
if ( DataTable.settings[i] == oSettings ) |
585 |
{ |
586 |
DataTable.settings.splice( i, 1 ); |
587 |
} |
588 |
} |
589 |
|
590 |
/* End it all */ |
591 |
oSettings = null; |
592 |
oInit = null; |
593 |
}; |
594 |
|
595 |
|
596 |
/** |
597 |
* Redraw the table |
598 |
* @param {bool} [bComplete=true] Re-filter and resort (if enabled) the table before the draw. |
599 |
* @dtopt API |
600 |
* |
601 |
* @example |
602 |
* $(document).ready(function() { |
603 |
* var oTable = $('#example').dataTable(); |
604 |
* |
605 |
* // Re-draw the table - you wouldn't want to do it here, but it's an example :-) |
606 |
* oTable.fnDraw(); |
607 |
* } ); |
608 |
*/ |
609 |
this.fnDraw = function( bComplete ) |
610 |
{ |
611 |
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); |
612 |
if ( bComplete === false ) |
613 |
{ |
614 |
_fnCalculateEnd( oSettings ); |
615 |
_fnDraw( oSettings ); |
616 |
} |
617 |
else |
618 |
{ |
619 |
_fnReDraw( oSettings ); |
620 |
} |
621 |
}; |
622 |
|
623 |
|
624 |
/** |
625 |
* Filter the input based on data |
626 |
* @param {string} sInput String to filter the table on |
627 |
* @param {int|null} [iColumn] Column to limit filtering to |
628 |
* @param {bool} [bRegex=false] Treat as regular expression or not |
629 |
* @param {bool} [bSmart=true] Perform smart filtering or not |
630 |
* @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es) |
631 |
* @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false) |
632 |
* @dtopt API |
633 |
* |
634 |
* @example |
635 |
* $(document).ready(function() { |
636 |
* var oTable = $('#example').dataTable(); |
637 |
* |
638 |
* // Sometime later - filter... |
639 |
* oTable.fnFilter( 'test string' ); |
640 |
* } ); |
641 |
*/ |
642 |
this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive ) |
643 |
{ |
644 |
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); |
645 |
|
646 |
if ( !oSettings.oFeatures.bFilter ) |
647 |
{ |
648 |
return; |
649 |
} |
650 |
|
651 |
if ( bRegex === undefined || bRegex === null ) |
652 |
{ |
653 |
bRegex = false; |
654 |
} |
655 |
|
656 |
if ( bSmart === undefined || bSmart === null ) |
657 |
{ |
658 |
bSmart = true; |
659 |
} |
660 |
|
661 |
if ( bShowGlobal === undefined || bShowGlobal === null ) |
662 |
{ |
663 |
bShowGlobal = true; |
664 |
} |
665 |
|
666 |
if ( bCaseInsensitive === undefined || bCaseInsensitive === null ) |
667 |
{ |
668 |
bCaseInsensitive = true; |
669 |
} |
670 |
|
671 |
if ( iColumn === undefined || iColumn === null ) |
672 |
{ |
673 |
/* Global filter */ |
674 |
_fnFilterComplete( oSettings, { |
675 |
"sSearch":sInput+"", |
676 |
"bRegex": bRegex, |
677 |
"bSmart": bSmart, |
678 |
"bCaseInsensitive": bCaseInsensitive |
679 |
}, 1 ); |
680 |
|
681 |
if ( bShowGlobal && oSettings.aanFeatures.f ) |
682 |
{ |
683 |
var n = oSettings.aanFeatures.f; |
684 |
for ( var i=0, iLen=n.length ; i<iLen ; i++ ) |
685 |
{ |
686 |
// IE9 throws an 'unknown error' if document.activeElement is used |
687 |
// inside an iframe or frame... |
688 |
try { |
689 |
if ( n[i]._DT_Input != document.activeElement ) |
690 |
{ |
691 |
$(n[i]._DT_Input).val( sInput ); |
692 |
} |
693 |
} |
694 |
catch ( e ) { |
695 |
$(n[i]._DT_Input).val( sInput ); |
696 |
} |
697 |
} |
698 |
} |
699 |
} |
700 |
else |
701 |
{ |
702 |
/* Single column filter */ |
703 |
$.extend( oSettings.aoPreSearchCols[ iColumn ], { |
704 |
"sSearch": sInput+"", |
705 |
"bRegex": bRegex, |
706 |
"bSmart": bSmart, |
707 |
"bCaseInsensitive": bCaseInsensitive |
708 |
} ); |
709 |
_fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 ); |
710 |
} |
711 |
}; |
712 |
|
713 |
|
714 |
/** |
715 |
* Get the data for the whole table, an individual row or an individual cell based on the |
716 |
* provided parameters. |
717 |
* @param {int|node} [mRow] A TR row node, TD/TH cell node or an integer. If given as |
718 |
* a TR node then the data source for the whole row will be returned. If given as a |
719 |
* TD/TH cell node then iCol will be automatically calculated and the data for the |
720 |
* cell returned. If given as an integer, then this is treated as the aoData internal |
721 |
* data index for the row (see fnGetPosition) and the data for that row used. |
722 |
* @param {int} [iCol] Optional column index that you want the data of. |
723 |
* @returns {array|object|string} If mRow is undefined, then the data for all rows is |
724 |
* returned. If mRow is defined, just data for that row, and is iCol is |
725 |
* defined, only data for the designated cell is returned. |
726 |
* @dtopt API |
727 |
* |
728 |
* @example |
729 |
* // Row data |
730 |
* $(document).ready(function() { |
731 |
* oTable = $('#example').dataTable(); |
732 |
* |
733 |
* oTable.$('tr').click( function () { |
734 |
* var data = oTable.fnGetData( this ); |
735 |
* // ... do something with the array / object of data for the row |
736 |
* } ); |
737 |
* } ); |
738 |
* |
739 |
* @example |
740 |
* // Individual cell data |
741 |
* $(document).ready(function() { |
742 |
* oTable = $('#example').dataTable(); |
743 |
* |
744 |
* oTable.$('td').click( function () { |
745 |
* var sData = oTable.fnGetData( this ); |
746 |
* alert( 'The cell clicked on had the value of '+sData ); |
747 |
* } ); |
748 |
* } ); |
749 |
*/ |
750 |
this.fnGetData = function( mRow, iCol ) |
751 |
{ |
752 |
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); |
753 |
|
754 |
if ( mRow !== undefined ) |
755 |
{ |
756 |
var iRow = mRow; |
757 |
if ( typeof mRow === 'object' ) |
758 |
{ |
759 |
var sNode = mRow.nodeName.toLowerCase(); |
760 |
if (sNode === "tr" ) |
761 |
{ |
762 |
iRow = _fnNodeToDataIndex(oSettings, mRow); |
763 |
} |
764 |
else if ( sNode === "td" ) |
765 |
{ |
766 |
iRow = _fnNodeToDataIndex(oSettings, mRow.parentNode); |
767 |
iCol = _fnNodeToColumnIndex( oSettings, iRow, mRow ); |
768 |
} |
769 |
} |
770 |
|
771 |
if ( iCol !== undefined ) |
772 |
{ |
773 |
return _fnGetCellData( oSettings, iRow, iCol, '' ); |
774 |
} |
775 |
return (oSettings.aoData[iRow]!==undefined) ? |
776 |
oSettings.aoData[iRow]._aData : null; |
777 |
} |
778 |
return _fnGetDataMaster( oSettings ); |
779 |
}; |
780 |
|
781 |
|
782 |
/** |
783 |
* Get an array of the TR nodes that are used in the table's body. Note that you will |
784 |
* typically want to use the '$' API method in preference to this as it is more |
785 |
* flexible. |
786 |
* @param {int} [iRow] Optional row index for the TR element you want |
787 |
* @returns {array|node} If iRow is undefined, returns an array of all TR elements |
788 |
* in the table's body, or iRow is defined, just the TR element requested. |
789 |
* @dtopt API |
790 |
* |
791 |
* @example |
792 |
* $(document).ready(function() { |
793 |
* var oTable = $('#example').dataTable(); |
794 |
* |
795 |
* // Get the nodes from the table |
796 |
* var nNodes = oTable.fnGetNodes( ); |
797 |
* } ); |
798 |
*/ |
799 |
this.fnGetNodes = function( iRow ) |
800 |
{ |
801 |
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); |
802 |
|
803 |
if ( iRow !== undefined ) { |
804 |
return (oSettings.aoData[iRow]!==undefined) ? |
805 |
oSettings.aoData[iRow].nTr : null; |
806 |
} |
807 |
return _fnGetTrNodes( oSettings ); |
808 |
}; |
809 |
|
810 |
|
811 |
/** |
812 |
* Get the array indexes of a particular cell from it's DOM element |
813 |
* and column index including hidden columns |
814 |
* @param {node} nNode this can either be a TR, TD or TH in the table's body |
815 |
* @returns {int} If nNode is given as a TR, then a single index is returned, or |
816 |
* if given as a cell, an array of [row index, column index (visible), |
817 |
* column index (all)] is given. |
818 |
* @dtopt API |
819 |
* |
820 |
* @example |
821 |
* $(document).ready(function() { |
822 |
* $('#example tbody td').click( function () { |
823 |
* // Get the position of the current data from the node |
824 |
* var aPos = oTable.fnGetPosition( this ); |
825 |
* |
826 |
* // Get the data array for this row |
827 |
* var aData = oTable.fnGetData( aPos[0] ); |
828 |
* |
829 |
* // Update the data array and return the value |
830 |
* aData[ aPos[1] ] = 'clicked'; |
831 |
* this.innerHTML = 'clicked'; |
832 |
* } ); |
833 |
* |
834 |
* // Init DataTables |
835 |
* oTable = $('#example').dataTable(); |
836 |
* } ); |
837 |
*/ |
838 |
this.fnGetPosition = function( nNode ) |
839 |
{ |
840 |
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); |
841 |
var sNodeName = nNode.nodeName.toUpperCase(); |
842 |
|
843 |
if ( sNodeName == "TR" ) |
844 |
{ |
845 |
return _fnNodeToDataIndex(oSettings, nNode); |
846 |
} |
847 |
else if ( sNodeName == "TD" || sNodeName == "TH" ) |
848 |
{ |
849 |
var iDataIndex = _fnNodeToDataIndex( oSettings, nNode.parentNode ); |
850 |
var iColumnIndex = _fnNodeToColumnIndex( oSettings, iDataIndex, nNode ); |
851 |
return [ iDataIndex, _fnColumnIndexToVisible(oSettings, iColumnIndex ), iColumnIndex ]; |
852 |
} |
853 |
return null; |
854 |
}; |
855 |
|
856 |
|
857 |
/** |
858 |
* Check to see if a row is 'open' or not. |
859 |
* @param {node} nTr the table row to check |
860 |
* @returns {boolean} true if the row is currently open, false otherwise |
861 |
* @dtopt API |
862 |
* |
863 |
* @example |
864 |
* $(document).ready(function() { |
865 |
* var oTable; |
866 |
* |
867 |
* // 'open' an information row when a row is clicked on |
868 |
* $('#example tbody tr').click( function () { |
869 |
* if ( oTable.fnIsOpen(this) ) { |
870 |
* oTable.fnClose( this ); |
871 |
* } else { |
872 |
* oTable.fnOpen( this, "Temporary row opened", "info_row" ); |
873 |
* } |
874 |
* } ); |
875 |
* |
876 |
* oTable = $('#example').dataTable(); |
877 |
* } ); |
878 |
*/ |
879 |
this.fnIsOpen = function( nTr ) |
880 |
{ |
881 |
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); |
882 |
var aoOpenRows = oSettings.aoOpenRows; |
883 |
|
884 |
for ( var i=0 ; i<oSettings.aoOpenRows.length ; i++ ) |
885 |
{ |
886 |
if ( oSettings.aoOpenRows[i].nParent == nTr ) |
887 |
{ |
888 |
return true; |
889 |
} |
890 |
} |
891 |
return false; |
892 |
}; |
893 |
|
894 |
|
895 |
/** |
896 |
* This function will place a new row directly after a row which is currently |
897 |
* on display on the page, with the HTML contents that is passed into the |
898 |
* function. This can be used, for example, to ask for confirmation that a |
899 |
* particular record should be deleted. |
900 |
* @param {node} nTr The table row to 'open' |
901 |
* @param {string|node|jQuery} mHtml The HTML to put into the row |
902 |
* @param {string} sClass Class to give the new TD cell |
903 |
* @returns {node} The row opened. Note that if the table row passed in as the |
904 |
* first parameter, is not found in the table, this method will silently |
905 |
* return. |
906 |
* @dtopt API |
907 |
* |
908 |
* @example |
909 |
* $(document).ready(function() { |
910 |
* var oTable; |
911 |
* |
912 |
* // 'open' an information row when a row is clicked on |
913 |
* $('#example tbody tr').click( function () { |
914 |
* if ( oTable.fnIsOpen(this) ) { |
915 |
* oTable.fnClose( this ); |
916 |
* } else { |
917 |
* oTable.fnOpen( this, "Temporary row opened", "info_row" ); |
918 |
* } |
919 |
* } ); |
920 |
* |
921 |
* oTable = $('#example').dataTable(); |
922 |
* } ); |
923 |
*/ |
924 |
this.fnOpen = function( nTr, mHtml, sClass ) |
925 |
{ |
926 |
/* Find settings from table node */ |
927 |
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); |
928 |
|
929 |
/* Check that the row given is in the table */ |
930 |
var nTableRows = _fnGetTrNodes( oSettings ); |
931 |
if ( $.inArray(nTr, nTableRows) === -1 ) |
932 |
{ |
933 |
return; |
934 |
} |
935 |
|
936 |
/* the old open one if there is one */ |
937 |
this.fnClose( nTr ); |
938 |
|
939 |
var nNewRow = document.createElement("tr"); |
940 |
var nNewCell = document.createElement("td"); |
941 |
nNewRow.appendChild( nNewCell ); |
942 |
nNewCell.className = sClass; |
943 |
nNewCell.colSpan = _fnVisbleColumns( oSettings ); |
944 |
|
945 |
if (typeof mHtml === "string") |
946 |
{ |
947 |
nNewCell.innerHTML = mHtml; |
948 |
} |
949 |
else |
950 |
{ |
951 |
$(nNewCell).html( mHtml ); |
952 |
} |
953 |
|
954 |
/* If the nTr isn't on the page at the moment - then we don't insert at the moment */ |
955 |
var nTrs = $('tr', oSettings.nTBody); |
956 |
if ( $.inArray(nTr, nTrs) != -1 ) |
957 |
{ |
958 |
$(nNewRow).insertAfter(nTr); |
959 |
} |
960 |
|
961 |
oSettings.aoOpenRows.push( { |
962 |
"nTr": nNewRow, |
963 |
"nParent": nTr |
964 |
} ); |
965 |
|
966 |
return nNewRow; |
967 |
}; |
968 |
|
969 |
|
970 |
/** |
971 |
* Change the pagination - provides the internal logic for pagination in a simple API |
972 |
* function. With this function you can have a DataTables table go to the next, |
973 |
* previous, first or last pages. |
974 |
* @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last" |
975 |
* or page number to jump to (integer), note that page 0 is the first page. |
976 |
* @param {bool} [bRedraw=true] Redraw the table or not |
977 |
* @dtopt API |
978 |
* |
979 |
* @example |
980 |
* $(document).ready(function() { |
981 |
* var oTable = $('#example').dataTable(); |
982 |
* oTable.fnPageChange( 'next' ); |
983 |
* } ); |
984 |
*/ |
985 |
this.fnPageChange = function ( mAction, bRedraw ) |
986 |
{ |
987 |
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); |
988 |
_fnPageChange( oSettings, mAction ); |
989 |
_fnCalculateEnd( oSettings ); |
990 |
|
991 |
if ( bRedraw === undefined || bRedraw ) |
992 |
{ |
993 |
_fnDraw( oSettings ); |
994 |
} |
995 |
}; |
996 |
|
997 |
|
998 |
/** |
999 |
* Show a particular column |
1000 |
* @param {int} iCol The column whose display should be changed |
1001 |
* @param {bool} bShow Show (true) or hide (false) the column |
1002 |
* @param {bool} [bRedraw=true] Redraw the table or not |
1003 |
* @dtopt API |
1004 |
* |
1005 |
* @example |
1006 |
* $(document).ready(function() { |
1007 |
* var oTable = $('#example').dataTable(); |
1008 |
* |
1009 |
* // Hide the second column after initialisation |
1010 |
* oTable.fnSetColumnVis( 1, false ); |
1011 |
* } ); |
1012 |
*/ |
1013 |
this.fnSetColumnVis = function ( iCol, bShow, bRedraw ) |
1014 |
{ |
1015 |
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); |
1016 |
var i, iLen; |
1017 |
var aoColumns = oSettings.aoColumns; |
1018 |
var aoData = oSettings.aoData; |
1019 |
var nTd, bAppend, iBefore; |
1020 |
|
1021 |
/* No point in doing anything if we are requesting what is already true */ |
1022 |
if ( aoColumns[iCol].bVisible == bShow ) |
1023 |
{ |
1024 |
return; |
1025 |
} |
1026 |
|
1027 |
/* Show the column */ |
1028 |
if ( bShow ) |
1029 |
{ |
1030 |
var iInsert = 0; |
1031 |
for ( i=0 ; i<iCol ; i++ ) |
1032 |
{ |
1033 |
if ( aoColumns[i].bVisible ) |
1034 |
{ |
1035 |
iInsert++; |
1036 |
} |
1037 |
} |
1038 |
|
1039 |
/* Need to decide if we should use appendChild or insertBefore */ |
1040 |
bAppend = (iInsert >= _fnVisbleColumns( oSettings )); |
1041 |
|
1042 |
/* Which coloumn should we be inserting before? */ |
1043 |
if ( !bAppend ) |
1044 |
{ |
1045 |
for ( i=iCol ; i<aoColumns.length ; i++ ) |
1046 |
{ |
1047 |
if ( aoColumns[i].bVisible ) |
1048 |
{ |
1049 |
iBefore = i; |
1050 |
break; |
1051 |
} |
1052 |
} |
1053 |
} |
1054 |
|
1055 |
for ( i=0, iLen=aoData.length ; i<iLen ; i++ ) |
1056 |
{ |
1057 |
if ( aoData[i].nTr !== null ) |
1058 |
{ |
1059 |
if ( bAppend ) |
1060 |
{ |
1061 |
aoData[i].nTr.appendChild( |
1062 |
aoData[i]._anHidden[iCol] |
1063 |
); |
1064 |
} |
1065 |
else |
1066 |
{ |
1067 |
aoData[i].nTr.insertBefore( |
1068 |
aoData[i]._anHidden[iCol], |
1069 |
_fnGetTdNodes( oSettings, i )[iBefore] ); |
1070 |
} |
1071 |
} |
1072 |
} |
1073 |
} |
1074 |
else |
1075 |
{ |
1076 |
/* Remove a column from display */ |
1077 |
for ( i=0, iLen=aoData.length ; i<iLen ; i++ ) |
1078 |
{ |
1079 |
if ( aoData[i].nTr !== null ) |
1080 |
{ |
1081 |
nTd = _fnGetTdNodes( oSettings, i )[iCol]; |
1082 |
aoData[i]._anHidden[iCol] = nTd; |
1083 |
nTd.parentNode.removeChild( nTd ); |
1084 |
} |
1085 |
} |
1086 |
} |
1087 |
|
1088 |
/* Clear to set the visible flag */ |
1089 |
aoColumns[iCol].bVisible = bShow; |
1090 |
|
1091 |
/* Redraw the header and footer based on the new column visibility */ |
1092 |
_fnDrawHead( oSettings, oSettings.aoHeader ); |
1093 |
if ( oSettings.nTFoot ) |
1094 |
{ |
1095 |
_fnDrawHead( oSettings, oSettings.aoFooter ); |
1096 |
} |
1097 |
|
1098 |
/* If there are any 'open' rows, then we need to alter the colspan for this col change */ |
1099 |
for ( i=0, iLen=oSettings.aoOpenRows.length ; i<iLen ; i++ ) |
1100 |
{ |
1101 |
oSettings.aoOpenRows[i].nTr.colSpan = _fnVisbleColumns( oSettings ); |
1102 |
} |
1103 |
|
1104 |
/* Do a redraw incase anything depending on the table columns needs it |
1105 |
* (built-in: scrolling) |
1106 |
*/ |
1107 |
if ( bRedraw === undefined || bRedraw ) |
1108 |
{ |
1109 |
_fnAdjustColumnSizing( oSettings ); |
1110 |
_fnDraw( oSettings ); |
1111 |
} |
1112 |
|
1113 |
_fnSaveState( oSettings ); |
1114 |
}; |
1115 |
|
1116 |
|
1117 |
/** |
1118 |
* Get the settings for a particular table for external manipulation |
1119 |
* @returns {object} DataTables settings object. See |
1120 |
* {@link DataTable.models.oSettings} |
1121 |
* @dtopt API |
1122 |
* |
1123 |
* @example |
1124 |
* $(document).ready(function() { |
1125 |
* var oTable = $('#example').dataTable(); |
1126 |
* var oSettings = oTable.fnSettings(); |
1127 |
* |
1128 |
* // Show an example parameter from the settings |
1129 |
* alert( oSettings._iDisplayStart ); |
1130 |
* } ); |
1131 |
*/ |
1132 |
this.fnSettings = function() |
1133 |
{ |
1134 |
return _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); |
1135 |
}; |
1136 |
|
1137 |
|
1138 |
/** |
1139 |
* Sort the table by a particular column |
1140 |
* @param {int} iCol the data index to sort on. Note that this will not match the |
1141 |
* 'display index' if you have hidden data entries |
1142 |
* @dtopt API |
1143 |
* |
1144 |
* @example |
1145 |
* $(document).ready(function() { |
1146 |
* var oTable = $('#example').dataTable(); |
1147 |
* |
1148 |
* // Sort immediately with columns 0 and 1 |
1149 |
* oTable.fnSort( [ [0,'asc'], [1,'asc'] ] ); |
1150 |
* } ); |
1151 |
*/ |
1152 |
this.fnSort = function( aaSort ) |
1153 |
{ |
1154 |
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); |
1155 |
oSettings.aaSorting = aaSort; |
1156 |
_fnSort( oSettings ); |
1157 |
}; |
1158 |
|
1159 |
|
1160 |
/** |
1161 |
* Attach a sort listener to an element for a given column |
1162 |
* @param {node} nNode the element to attach the sort listener to |
1163 |
* @param {int} iColumn the column that a click on this node will sort on |
1164 |
* @param {function} [fnCallback] callback function when sort is run |
1165 |
* @dtopt API |
1166 |
* |
1167 |
* @example |
1168 |
* $(document).ready(function() { |
1169 |
* var oTable = $('#example').dataTable(); |
1170 |
* |
1171 |
* // Sort on column 1, when 'sorter' is clicked on |
1172 |
* oTable.fnSortListener( document.getElementById('sorter'), 1 ); |
1173 |
* } ); |
1174 |
*/ |
1175 |
this.fnSortListener = function( nNode, iColumn, fnCallback ) |
1176 |
{ |
1177 |
_fnSortAttachListener( _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ), nNode, iColumn, |
1178 |
fnCallback ); |
1179 |
}; |
1180 |
|
1181 |
|
1182 |
/** |
1183 |
* Update a table cell or row - this method will accept either a single value to |
1184 |
* update the cell with, an array of values with one element for each column or |
1185 |
* an object in the same format as the original data source. The function is |
1186 |
* self-referencing in order to make the multi column updates easier. |
1187 |
* @param {object|array|string} mData Data to update the cell/row with |
1188 |
* @param {node|int} mRow TR element you want to update or the aoData index |
1189 |
* @param {int} [iColumn] The column to update (not used of mData is an array or object) |
1190 |
* @param {bool} [bRedraw=true] Redraw the table or not |
1191 |
* @param {bool} [bAction=true] Perform pre-draw actions or not |
1192 |
* @returns {int} 0 on success, 1 on error |
1193 |
* @dtopt API |
1194 |
* |
1195 |
* @example |
1196 |
* $(document).ready(function() { |
1197 |
* var oTable = $('#example').dataTable(); |
1198 |
* oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell |
1199 |
* oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], 1, 0 ); // Row |
1200 |
* } ); |
1201 |
*/ |
1202 |
this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction ) |
1203 |
{ |
1204 |
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); |
1205 |
var i, iLen, sDisplay; |
1206 |
var iRow = (typeof mRow === 'object') ? |
1207 |
_fnNodeToDataIndex(oSettings, mRow) : mRow; |
1208 |
|
1209 |
if ( $.isArray(mData) && iColumn === undefined ) |
1210 |
{ |
1211 |
/* Array update - update the whole row */ |
1212 |
oSettings.aoData[iRow]._aData = mData.slice(); |
1213 |
|
1214 |
/* Flag to the function that we are recursing */ |
1215 |
for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) |
1216 |
{ |
1217 |
this.fnUpdate( _fnGetCellData( oSettings, iRow, i ), iRow, i, false, false ); |
1218 |
} |
1219 |
} |
1220 |
else if ( $.isPlainObject(mData) && iColumn === undefined ) |
1221 |
{ |
1222 |
/* Object update - update the whole row - assume the developer gets the object right */ |
1223 |
oSettings.aoData[iRow]._aData = $.extend( true, {}, mData ); |
1224 |
|
1225 |
for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) |
1226 |
{ |
1227 |
this.fnUpdate( _fnGetCellData( oSettings, iRow, i ), iRow, i, false, false ); |
1228 |
} |
1229 |
} |
1230 |
else |
1231 |
{ |
1232 |
/* Individual cell update */ |
1233 |
_fnSetCellData( oSettings, iRow, iColumn, mData ); |
1234 |
sDisplay = _fnGetCellData( oSettings, iRow, iColumn, 'display' ); |
1235 |
|
1236 |
var oCol = oSettings.aoColumns[iColumn]; |
1237 |
if ( oCol.fnRender !== null ) |
1238 |
{ |
1239 |
sDisplay = _fnRender( oSettings, iRow, iColumn ); |
1240 |
if ( oCol.bUseRendered ) |
1241 |
{ |
1242 |
_fnSetCellData( oSettings, iRow, iColumn, sDisplay ); |
1243 |
} |
1244 |
} |
1245 |
|
1246 |
if ( oSettings.aoData[iRow].nTr !== null ) |
1247 |
{ |
1248 |
/* Do the actual HTML update */ |
1249 |
_fnGetTdNodes( oSettings, iRow )[iColumn].innerHTML = sDisplay; |
1250 |
} |
1251 |
} |
1252 |
|
1253 |
/* Modify the search index for this row (strictly this is likely not needed, since fnReDraw |
1254 |
* will rebuild the search array - however, the redraw might be disabled by the user) |
1255 |
*/ |
1256 |
var iDisplayIndex = $.inArray( iRow, oSettings.aiDisplay ); |
1257 |
oSettings.asDataSearch[iDisplayIndex] = _fnBuildSearchRow( |
1258 |
oSettings, |
1259 |
_fnGetRowData( oSettings, iRow, 'filter', _fnGetColumns( oSettings, 'bSearchable' ) ) |
1260 |
); |
1261 |
|
1262 |
/* Perform pre-draw actions */ |
1263 |
if ( bAction === undefined || bAction ) |
1264 |
{ |
1265 |
_fnAdjustColumnSizing( oSettings ); |
1266 |
} |
1267 |
|
1268 |
/* Redraw the table */ |
1269 |
if ( bRedraw === undefined || bRedraw ) |
1270 |
{ |
1271 |
_fnReDraw( oSettings ); |
1272 |
} |
1273 |
return 0; |
1274 |
}; |
1275 |
|
1276 |
|
1277 |
/** |
1278 |
* Provide a common method for plug-ins to check the version of DataTables being used, in order |
1279 |
* to ensure compatibility. |
1280 |
* @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the |
1281 |
* formats "X" and "X.Y" are also acceptable. |
1282 |
* @returns {boolean} true if this version of DataTables is greater or equal to the required |
1283 |
* version, or false if this version of DataTales is not suitable |
1284 |
* @method |
1285 |
* @dtopt API |
1286 |
* |
1287 |
* @example |
1288 |
* $(document).ready(function() { |
1289 |
* var oTable = $('#example').dataTable(); |
1290 |
* alert( oTable.fnVersionCheck( '1.9.0' ) ); |
1291 |
* } ); |
1292 |
*/ |
1293 |
this.fnVersionCheck = DataTable.ext.fnVersionCheck; |