Add datatables-1.9.4 and jquery-1.10.2 libraries
[proteocache.git] / webapp / resources / datatables-1.9.4 / media / src / api / api.methods.js
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;
1294