Statistiques
| Révision :

root / tei / js / jquery.dataTables.js @ 2

Historique | Voir | Annoter | Télécharger (205,46 ko)

1 2 mingarao
/*
2 2 mingarao
 * File:        jquery.dataTables.js
3 2 mingarao
 * Version:     1.7.4
4 2 mingarao
 * Description: Paginate, search and sort HTML tables
5 2 mingarao
 * Author:      Allan Jardine (www.sprymedia.co.uk)
6 2 mingarao
 * Created:     28/3/2008
7 2 mingarao
 * Language:    Javascript
8 2 mingarao
 * License:     GPL v2 or BSD 3 point style
9 2 mingarao
 * Project:     Mtaala
10 2 mingarao
 * Contact:     allan.jardine@sprymedia.co.uk
11 2 mingarao
 *
12 2 mingarao
 * Copyright 2008-2010 Allan Jardine, all rights reserved.
13 2 mingarao
 *
14 2 mingarao
 * This source file is free software, under either the GPL v2 license or a
15 2 mingarao
 * BSD style license, as supplied with this software.
16 2 mingarao
 *
17 2 mingarao
 * This source file is distributed in the hope that it will be useful, but
18 2 mingarao
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 2 mingarao
 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
20 2 mingarao
 *
21 2 mingarao
 * For details please refer to: http://www.datatables.net
22 2 mingarao
 */
23 2 mingarao
24 2 mingarao
/*
25 2 mingarao
 * When considering jsLint, we need to allow eval() as it it is used for reading cookies and
26 2 mingarao
 * building the dynamic multi-column sort functions.
27 2 mingarao
 */
28 2 mingarao
/*jslint evil: true, undef: true, browser: true */
29 2 mingarao
/*globals $, jQuery,_fnExternApiFunc,_fnInitalise,_fnLanguageProcess,_fnAddColumn,_fnColumnOptions,_fnAddData,_fnGatherData,_fnDrawHead,_fnDraw,_fnReDraw,_fnAjaxUpdate,_fnAjaxUpdateDraw,_fnAddOptionsHtml,_fnFeatureHtmlTable,_fnScrollDraw,_fnAjustColumnSizing,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnBuildSearchArray,_fnBuildSearchRow,_fnFilterCreateSearch,_fnDataToSearch,_fnSort,_fnSortAttachListener,_fnSortingClasses,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnFeatureHtmlLength,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnNodeToDataIndex,_fnVisbleColumns,_fnCalculateEnd,_fnConvertToWidth,_fnCalculateColumnWidths,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnArrayCmp,_fnDetectType,_fnSettingsFromNode,_fnGetDataMaster,_fnGetTrNodes,_fnGetTdNodes,_fnEscapeRegex,_fnDeleteIndex,_fnReOrderIndex,_fnColumnOrdering,_fnLog,_fnClearTable,_fnSaveState,_fnLoadState,_fnCreateCookie,_fnReadCookie,_fnGetUniqueThs,_fnScrollBarWidth,_fnApplyToChildren,_fnMap*/
30 2 mingarao
31 2 mingarao
(function($, window, document) {
32 2 mingarao
        /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
33 2 mingarao
         * Section - DataTables variables
34 2 mingarao
         * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
35 2 mingarao
36 2 mingarao
        /*
37 2 mingarao
         * Variable: dataTableSettings
38 2 mingarao
         * Purpose:  Store the settings for each dataTables instance
39 2 mingarao
         * Scope:    jQuery.fn
40 2 mingarao
         */
41 2 mingarao
        $.fn.dataTableSettings = [];
42 2 mingarao
        var _aoSettings = $.fn.dataTableSettings; /* Short reference for fast internal lookup */
43 2 mingarao
44 2 mingarao
        /*
45 2 mingarao
         * Variable: dataTableExt
46 2 mingarao
         * Purpose:  Container for customisable parts of DataTables
47 2 mingarao
         * Scope:    jQuery.fn
48 2 mingarao
         */
49 2 mingarao
        $.fn.dataTableExt = {};
50 2 mingarao
        var _oExt = $.fn.dataTableExt;
51 2 mingarao
52 2 mingarao
53 2 mingarao
        /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
54 2 mingarao
         * Section - DataTables extensible objects
55 2 mingarao
         *
56 2 mingarao
         * The _oExt object is used to provide an area where user dfined plugins can be
57 2 mingarao
         * added to DataTables. The following properties of the object are used:
58 2 mingarao
         *   oApi - Plug-in API functions
59 2 mingarao
         *   aTypes - Auto-detection of types
60 2 mingarao
         *   oSort - Sorting functions used by DataTables (based on the type)
61 2 mingarao
         *   oPagination - Pagination functions for different input styles
62 2 mingarao
         * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
63 2 mingarao
64 2 mingarao
        /*
65 2 mingarao
         * Variable: sVersion
66 2 mingarao
         * Purpose:  Version string for plug-ins to check compatibility
67 2 mingarao
         * Scope:    jQuery.fn.dataTableExt
68 2 mingarao
         * Notes:    Allowed format is a.b.c.d.e where:
69 2 mingarao
         *   a:int, b:int, c:int, d:string(dev|beta), e:int. d and e are optional
70 2 mingarao
         */
71 2 mingarao
        _oExt.sVersion = "1.7.4";
72 2 mingarao
73 2 mingarao
        /*
74 2 mingarao
         * Variable: sErrMode
75 2 mingarao
         * Purpose:  How should DataTables report an error. Can take the value 'alert' or 'throw'
76 2 mingarao
         * Scope:    jQuery.fn.dataTableExt
77 2 mingarao
         */
78 2 mingarao
        _oExt.sErrMode = "alert";
79 2 mingarao
80 2 mingarao
        /*
81 2 mingarao
         * Variable: iApiIndex
82 2 mingarao
         * Purpose:  Index for what 'this' index API functions should use
83 2 mingarao
         * Scope:    jQuery.fn.dataTableExt
84 2 mingarao
         */
85 2 mingarao
        _oExt.iApiIndex = 0;
86 2 mingarao
87 2 mingarao
        /*
88 2 mingarao
         * Variable: oApi
89 2 mingarao
         * Purpose:  Container for plugin API functions
90 2 mingarao
         * Scope:    jQuery.fn.dataTableExt
91 2 mingarao
         */
92 2 mingarao
        _oExt.oApi = { };
93 2 mingarao
94 2 mingarao
        /*
95 2 mingarao
         * Variable: aFiltering
96 2 mingarao
         * Purpose:  Container for plugin filtering functions
97 2 mingarao
         * Scope:    jQuery.fn.dataTableExt
98 2 mingarao
         */
99 2 mingarao
        _oExt.afnFiltering = [ ];
100 2 mingarao
101 2 mingarao
        /*
102 2 mingarao
         * Variable: aoFeatures
103 2 mingarao
         * Purpose:  Container for plugin function functions
104 2 mingarao
         * Scope:    jQuery.fn.dataTableExt
105 2 mingarao
         * Notes:    Array of objects with the following parameters:
106 2 mingarao
         *   fnInit: Function for initialisation of Feature. Takes oSettings and returns node
107 2 mingarao
         *   cFeature: Character that will be matched in sDom - case sensitive
108 2 mingarao
         *   sFeature: Feature name - just for completeness :-)
109 2 mingarao
         */
110 2 mingarao
        _oExt.aoFeatures = [ ];
111 2 mingarao
112 2 mingarao
        /*
113 2 mingarao
         * Variable: ofnSearch
114 2 mingarao
         * Purpose:  Container for custom filtering functions
115 2 mingarao
         * Scope:    jQuery.fn.dataTableExt
116 2 mingarao
         * Notes:    This is an object (the name should match the type) for custom filtering function,
117 2 mingarao
         *   which can be used for live DOM checking or formatted text filtering
118 2 mingarao
         */
119 2 mingarao
        _oExt.ofnSearch = { };
120 2 mingarao
121 2 mingarao
        /*
122 2 mingarao
         * Variable: afnSortData
123 2 mingarao
         * Purpose:  Container for custom sorting data source functions
124 2 mingarao
         * Scope:    jQuery.fn.dataTableExt
125 2 mingarao
         * Notes:    Array (associative) of functions which is run prior to a column of this
126 2 mingarao
         *   'SortDataType' being sorted upon.
127 2 mingarao
         *   Function input parameters:
128 2 mingarao
         *     object:oSettings-  DataTables settings object
129 2 mingarao
         *     int:iColumn - Target column number
130 2 mingarao
         *   Return value: Array of data which exactly matched the full data set size for the column to
131 2 mingarao
         *     be sorted upon
132 2 mingarao
         */
133 2 mingarao
        _oExt.afnSortData = [ ];
134 2 mingarao
135 2 mingarao
        /*
136 2 mingarao
         * Variable: oStdClasses
137 2 mingarao
         * Purpose:  Storage for the various classes that DataTables uses
138 2 mingarao
         * Scope:    jQuery.fn.dataTableExt
139 2 mingarao
         */
140 2 mingarao
        _oExt.oStdClasses = {
141 2 mingarao
                /* Two buttons buttons */
142 2 mingarao
                "sPagePrevEnabled": "paginate_enabled_previous",
143 2 mingarao
                "sPagePrevDisabled": "paginate_disabled_previous",
144 2 mingarao
                "sPageNextEnabled": "paginate_enabled_next",
145 2 mingarao
                "sPageNextDisabled": "paginate_disabled_next",
146 2 mingarao
                "sPageJUINext": "",
147 2 mingarao
                "sPageJUIPrev": "",
148 2 mingarao
149 2 mingarao
                /* Full numbers paging buttons */
150 2 mingarao
                "sPageButton": "paginate_button",
151 2 mingarao
                "sPageButtonActive": "paginate_active",
152 2 mingarao
                "sPageButtonStaticDisabled": "paginate_button",
153 2 mingarao
                "sPageFirst": "first",
154 2 mingarao
                "sPagePrevious": "previous",
155 2 mingarao
                "sPageNext": "next",
156 2 mingarao
                "sPageLast": "last",
157 2 mingarao
158 2 mingarao
                /* Stripping classes */
159 2 mingarao
                "sStripOdd": "odd",
160 2 mingarao
                "sStripEven": "even",
161 2 mingarao
162 2 mingarao
                /* Empty row */
163 2 mingarao
                "sRowEmpty": "dataTables_empty",
164 2 mingarao
165 2 mingarao
                /* Features */
166 2 mingarao
                "sWrapper": "dataTables_wrapper",
167 2 mingarao
                "sFilter": "dataTables_filter",
168 2 mingarao
                "sInfo": "dataTables_info",
169 2 mingarao
                "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
170 2 mingarao
                "sLength": "dataTables_length",
171 2 mingarao
                "sProcessing": "dataTables_processing",
172 2 mingarao
173 2 mingarao
                /* Sorting */
174 2 mingarao
                "sSortAsc": "sorting_asc",
175 2 mingarao
                "sSortDesc": "sorting_desc",
176 2 mingarao
                "sSortable": "sorting", /* Sortable in both directions */
177 2 mingarao
                "sSortableAsc": "sorting_asc_disabled",
178 2 mingarao
                "sSortableDesc": "sorting_desc_disabled",
179 2 mingarao
                "sSortableNone": "sorting_disabled",
180 2 mingarao
                "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
181 2 mingarao
                "sSortJUIAsc": "",
182 2 mingarao
                "sSortJUIDesc": "",
183 2 mingarao
                "sSortJUI": "",
184 2 mingarao
                "sSortJUIAscAllowed": "",
185 2 mingarao
                "sSortJUIDescAllowed": "",
186 2 mingarao
                "sSortJUIWrapper": "",
187 2 mingarao
188 2 mingarao
                /* Scrolling */
189 2 mingarao
                "sScrollWrapper": "dataTables_scroll",
190 2 mingarao
                "sScrollHead": "dataTables_scrollHead",
191 2 mingarao
                "sScrollHeadInner": "dataTables_scrollHeadInner",
192 2 mingarao
                "sScrollBody": "dataTables_scrollBody",
193 2 mingarao
                "sScrollFoot": "dataTables_scrollFoot",
194 2 mingarao
                "sScrollFootInner": "dataTables_scrollFootInner",
195 2 mingarao
196 2 mingarao
                /* Misc */
197 2 mingarao
                "sFooterTH": ""
198 2 mingarao
        };
199 2 mingarao
200 2 mingarao
        /*
201 2 mingarao
         * Variable: oJUIClasses
202 2 mingarao
         * Purpose:  Storage for the various classes that DataTables uses - jQuery UI suitable
203 2 mingarao
         * Scope:    jQuery.fn.dataTableExt
204 2 mingarao
         */
205 2 mingarao
        _oExt.oJUIClasses = {
206 2 mingarao
                /* Two buttons buttons */
207 2 mingarao
                "sPagePrevEnabled": "fg-button ui-button ui-state-default ui-corner-left",
208 2 mingarao
                "sPagePrevDisabled": "fg-button ui-button ui-state-default ui-corner-left ui-state-disabled",
209 2 mingarao
                "sPageNextEnabled": "fg-button ui-button ui-state-default ui-corner-right",
210 2 mingarao
                "sPageNextDisabled": "fg-button ui-button ui-state-default ui-corner-right ui-state-disabled",
211 2 mingarao
                "sPageJUINext": "ui-icon ui-icon-circle-arrow-e",
212 2 mingarao
                "sPageJUIPrev": "ui-icon ui-icon-circle-arrow-w",
213 2 mingarao
214 2 mingarao
                /* Full numbers paging buttons */
215 2 mingarao
                "sPageButton": "fg-button ui-button ui-state-default",
216 2 mingarao
                "sPageButtonActive": "fg-button ui-button ui-state-default ui-state-disabled",
217 2 mingarao
                "sPageButtonStaticDisabled": "fg-button ui-button ui-state-default ui-state-disabled",
218 2 mingarao
                "sPageFirst": "first ui-corner-tl ui-corner-bl",
219 2 mingarao
                "sPagePrevious": "previous",
220 2 mingarao
                "sPageNext": "next",
221 2 mingarao
                "sPageLast": "last ui-corner-tr ui-corner-br",
222 2 mingarao
223 2 mingarao
                /* Stripping classes */
224 2 mingarao
                "sStripOdd": "odd",
225 2 mingarao
                "sStripEven": "even",
226 2 mingarao
227 2 mingarao
                /* Empty row */
228 2 mingarao
                "sRowEmpty": "dataTables_empty",
229 2 mingarao
230 2 mingarao
                /* Features */
231 2 mingarao
                "sWrapper": "dataTables_wrapper",
232 2 mingarao
                "sFilter": "dataTables_filter",
233 2 mingarao
                "sInfo": "dataTables_info",
234 2 mingarao
                "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
235 2 mingarao
                        "ui-buttonset-multi paging_", /* Note that the type is postfixed */
236 2 mingarao
                "sLength": "dataTables_length",
237 2 mingarao
                "sProcessing": "dataTables_processing",
238 2 mingarao
239 2 mingarao
                /* Sorting */
240 2 mingarao
                "sSortAsc": "ui-state-default",
241 2 mingarao
                "sSortDesc": "ui-state-default",
242 2 mingarao
                "sSortable": "ui-state-default",
243 2 mingarao
                "sSortableAsc": "ui-state-default",
244 2 mingarao
                "sSortableDesc": "ui-state-default",
245 2 mingarao
                "sSortableNone": "ui-state-default",
246 2 mingarao
                "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
247 2 mingarao
                "sSortJUIAsc": "css_right ui-icon ui-icon-triangle-1-n",
248 2 mingarao
                "sSortJUIDesc": "css_right ui-icon ui-icon-triangle-1-s",
249 2 mingarao
                "sSortJUI": "css_right ui-icon ui-icon-carat-2-n-s",
250 2 mingarao
                "sSortJUIAscAllowed": "css_right ui-icon ui-icon-carat-1-n",
251 2 mingarao
                "sSortJUIDescAllowed": "css_right ui-icon ui-icon-carat-1-s",
252 2 mingarao
                "sSortJUIWrapper": "DataTables_sort_wrapper",
253 2 mingarao
254 2 mingarao
                /* Scrolling */
255 2 mingarao
                "sScrollWrapper": "dataTables_scroll",
256 2 mingarao
                "sScrollHead": "dataTables_scrollHead ui-state-default",
257 2 mingarao
                "sScrollHeadInner": "dataTables_scrollHeadInner",
258 2 mingarao
                "sScrollBody": "dataTables_scrollBody",
259 2 mingarao
                "sScrollFoot": "dataTables_scrollFoot ui-state-default",
260 2 mingarao
                "sScrollFootInner": "dataTables_scrollFootInner",
261 2 mingarao
262 2 mingarao
                /* Misc */
263 2 mingarao
                "sFooterTH": "ui-state-default"
264 2 mingarao
        };
265 2 mingarao
266 2 mingarao
        /*
267 2 mingarao
         * Variable: oPagination
268 2 mingarao
         * Purpose:  Container for the various type of pagination that dataTables supports
269 2 mingarao
         * Scope:    jQuery.fn.dataTableExt
270 2 mingarao
         */
271 2 mingarao
        _oExt.oPagination = {
272 2 mingarao
                /*
273 2 mingarao
                 * Variable: two_button
274 2 mingarao
                 * Purpose:  Standard two button (forward/back) pagination
275 2 mingarao
                  * Scope:    jQuery.fn.dataTableExt.oPagination
276 2 mingarao
                 */
277 2 mingarao
                "two_button": {
278 2 mingarao
                        /*
279 2 mingarao
                         * Function: oPagination.two_button.fnInit
280 2 mingarao
                         * Purpose:  Initalise dom elements required for pagination with forward/back buttons only
281 2 mingarao
                         * Returns:  -
282 2 mingarao
                          * Inputs:   object:oSettings - dataTables settings object
283 2 mingarao
             *           node:nPaging - the DIV which contains this pagination control
284 2 mingarao
                         *           function:fnCallbackDraw - draw function which must be called on update
285 2 mingarao
                         */
286 2 mingarao
                        "fnInit": function ( oSettings, nPaging, fnCallbackDraw )
287 2 mingarao
                        {
288 2 mingarao
                                var nPrevious, nNext, nPreviousInner, nNextInner;
289 2 mingarao
290 2 mingarao
                                /* Store the next and previous elements in the oSettings object as they can be very
291 2 mingarao
                                 * usful for automation - particularly testing
292 2 mingarao
                                 */
293 2 mingarao
                                if ( !oSettings.bJUI )
294 2 mingarao
                                {
295 2 mingarao
                                        nPrevious = document.createElement( 'div' );
296 2 mingarao
                                        nNext = document.createElement( 'div' );
297 2 mingarao
                                }
298 2 mingarao
                                else
299 2 mingarao
                                {
300 2 mingarao
                                        nPrevious = document.createElement( 'a' );
301 2 mingarao
                                        nNext = document.createElement( 'a' );
302 2 mingarao
303 2 mingarao
                                        nNextInner = document.createElement('span');
304 2 mingarao
                                        nNextInner.className = oSettings.oClasses.sPageJUINext;
305 2 mingarao
                                        nNext.appendChild( nNextInner );
306 2 mingarao
307 2 mingarao
                                        nPreviousInner = document.createElement('span');
308 2 mingarao
                                        nPreviousInner.className = oSettings.oClasses.sPageJUIPrev;
309 2 mingarao
                                        nPrevious.appendChild( nPreviousInner );
310 2 mingarao
                                }
311 2 mingarao
312 2 mingarao
                                nPrevious.className = oSettings.oClasses.sPagePrevDisabled;
313 2 mingarao
                                nNext.className = oSettings.oClasses.sPageNextDisabled;
314 2 mingarao
315 2 mingarao
                                nPrevious.title = oSettings.oLanguage.oPaginate.sPrevious;
316 2 mingarao
                                nNext.title = oSettings.oLanguage.oPaginate.sNext;
317 2 mingarao
318 2 mingarao
                                nPaging.appendChild( nPrevious );
319 2 mingarao
                                nPaging.appendChild( nNext );
320 2 mingarao
321 2 mingarao
                                $(nPrevious).click( function() {
322 2 mingarao
                                        if ( oSettings.oApi._fnPageChange( oSettings, "previous" ) )
323 2 mingarao
                                        {
324 2 mingarao
                                                /* Only draw when the page has actually changed */
325 2 mingarao
                                                fnCallbackDraw( oSettings );
326 2 mingarao
                                        }
327 2 mingarao
                                } );
328 2 mingarao
329 2 mingarao
                                $(nNext).click( function() {
330 2 mingarao
                                        if ( oSettings.oApi._fnPageChange( oSettings, "next" ) )
331 2 mingarao
                                        {
332 2 mingarao
                                                fnCallbackDraw( oSettings );
333 2 mingarao
                                        }
334 2 mingarao
                                } );
335 2 mingarao
336 2 mingarao
                                /* Take the brutal approach to cancelling text selection */
337 2 mingarao
                                $(nPrevious).bind( 'selectstart', function () { return false; } );
338 2 mingarao
                                $(nNext).bind( 'selectstart', function () { return false; } );
339 2 mingarao
340 2 mingarao
                                /* ID the first elements only */
341 2 mingarao
                                if ( oSettings.sTableId !== '' && typeof oSettings.aanFeatures.p == "undefined" )
342 2 mingarao
                                {
343 2 mingarao
                                        nPaging.setAttribute( 'id', oSettings.sTableId+'_paginate' );
344 2 mingarao
                                        nPrevious.setAttribute( 'id', oSettings.sTableId+'_previous' );
345 2 mingarao
                                        nNext.setAttribute( 'id', oSettings.sTableId+'_next' );
346 2 mingarao
                                }
347 2 mingarao
                        },
348 2 mingarao
349 2 mingarao
                        /*
350 2 mingarao
                         * Function: oPagination.two_button.fnUpdate
351 2 mingarao
                         * Purpose:  Update the two button pagination at the end of the draw
352 2 mingarao
                         * Returns:  -
353 2 mingarao
                          * Inputs:   object:oSettings - dataTables settings object
354 2 mingarao
                         *           function:fnCallbackDraw - draw function to call on page change
355 2 mingarao
                         */
356 2 mingarao
                        "fnUpdate": function ( oSettings, fnCallbackDraw )
357 2 mingarao
                        {
358 2 mingarao
                                if ( !oSettings.aanFeatures.p )
359 2 mingarao
                                {
360 2 mingarao
                                        return;
361 2 mingarao
                                }
362 2 mingarao
363 2 mingarao
                                /* Loop over each instance of the pager */
364 2 mingarao
                                var an = oSettings.aanFeatures.p;
365 2 mingarao
                                for ( var i=0, iLen=an.length ; i<iLen ; i++ )
366 2 mingarao
                                {
367 2 mingarao
                                        if ( an[i].childNodes.length !== 0 )
368 2 mingarao
                                        {
369 2 mingarao
                                                an[i].childNodes[0].className =
370 2 mingarao
                                                        ( oSettings._iDisplayStart === 0 ) ?
371 2 mingarao
                                                        oSettings.oClasses.sPagePrevDisabled : oSettings.oClasses.sPagePrevEnabled;
372 2 mingarao
373 2 mingarao
                                                an[i].childNodes[1].className =
374 2 mingarao
                                                        ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) ?
375 2 mingarao
                                                        oSettings.oClasses.sPageNextDisabled : oSettings.oClasses.sPageNextEnabled;
376 2 mingarao
                                        }
377 2 mingarao
                                }
378 2 mingarao
                        }
379 2 mingarao
                },
380 2 mingarao
381 2 mingarao
382 2 mingarao
                /*
383 2 mingarao
                 * Variable: iFullNumbersShowPages
384 2 mingarao
                 * Purpose:  Change the number of pages which can be seen
385 2 mingarao
                  * Scope:    jQuery.fn.dataTableExt.oPagination
386 2 mingarao
                 */
387 2 mingarao
                "iFullNumbersShowPages": 5,
388 2 mingarao
389 2 mingarao
                /*
390 2 mingarao
                 * Variable: full_numbers
391 2 mingarao
                 * Purpose:  Full numbers pagination
392 2 mingarao
                  * Scope:    jQuery.fn.dataTableExt.oPagination
393 2 mingarao
                 */
394 2 mingarao
                "full_numbers": {
395 2 mingarao
                        /*
396 2 mingarao
                         * Function: oPagination.full_numbers.fnInit
397 2 mingarao
                         * Purpose:  Initalise dom elements required for pagination with a list of the pages
398 2 mingarao
                         * Returns:  -
399 2 mingarao
                          * Inputs:   object:oSettings - dataTables settings object
400 2 mingarao
             *           node:nPaging - the DIV which contains this pagination control
401 2 mingarao
                         *           function:fnCallbackDraw - draw function which must be called on update
402 2 mingarao
                         */
403 2 mingarao
                        "fnInit": function ( oSettings, nPaging, fnCallbackDraw )
404 2 mingarao
                        {
405 2 mingarao
                                var nFirst = document.createElement( 'span' );
406 2 mingarao
                                var nPrevious = document.createElement( 'span' );
407 2 mingarao
                                var nList = document.createElement( 'span' );
408 2 mingarao
                                var nNext = document.createElement( 'span' );
409 2 mingarao
                                var nLast = document.createElement( 'span' );
410 2 mingarao
411 2 mingarao
                                nFirst.innerHTML = oSettings.oLanguage.oPaginate.sFirst;
412 2 mingarao
                                nPrevious.innerHTML = oSettings.oLanguage.oPaginate.sPrevious;
413 2 mingarao
                                nNext.innerHTML = oSettings.oLanguage.oPaginate.sNext;
414 2 mingarao
                                nLast.innerHTML = oSettings.oLanguage.oPaginate.sLast;
415 2 mingarao
416 2 mingarao
                                var oClasses = oSettings.oClasses;
417 2 mingarao
                                nFirst.className = oClasses.sPageButton+" "+oClasses.sPageFirst;
418 2 mingarao
                                nPrevious.className = oClasses.sPageButton+" "+oClasses.sPagePrevious;
419 2 mingarao
                                nNext.className= oClasses.sPageButton+" "+oClasses.sPageNext;
420 2 mingarao
                                nLast.className = oClasses.sPageButton+" "+oClasses.sPageLast;
421 2 mingarao
422 2 mingarao
                                nPaging.appendChild( nFirst );
423 2 mingarao
                                nPaging.appendChild( nPrevious );
424 2 mingarao
                                nPaging.appendChild( nList );
425 2 mingarao
                                nPaging.appendChild( nNext );
426 2 mingarao
                                nPaging.appendChild( nLast );
427 2 mingarao
428 2 mingarao
                                $(nFirst).click( function () {
429 2 mingarao
                                        if ( oSettings.oApi._fnPageChange( oSettings, "first" ) )
430 2 mingarao
                                        {
431 2 mingarao
                                                fnCallbackDraw( oSettings );
432 2 mingarao
                                        }
433 2 mingarao
                                } );
434 2 mingarao
435 2 mingarao
                                $(nPrevious).click( function() {
436 2 mingarao
                                        if ( oSettings.oApi._fnPageChange( oSettings, "previous" ) )
437 2 mingarao
                                        {
438 2 mingarao
                                                fnCallbackDraw( oSettings );
439 2 mingarao
                                        }
440 2 mingarao
                                } );
441 2 mingarao
442 2 mingarao
                                $(nNext).click( function() {
443 2 mingarao
                                        if ( oSettings.oApi._fnPageChange( oSettings, "next" ) )
444 2 mingarao
                                        {
445 2 mingarao
                                                fnCallbackDraw( oSettings );
446 2 mingarao
                                        }
447 2 mingarao
                                } );
448 2 mingarao
449 2 mingarao
                                $(nLast).click( function() {
450 2 mingarao
                                        if ( oSettings.oApi._fnPageChange( oSettings, "last" ) )
451 2 mingarao
                                        {
452 2 mingarao
                                                fnCallbackDraw( oSettings );
453 2 mingarao
                                        }
454 2 mingarao
                                } );
455 2 mingarao
456 2 mingarao
                                /* Take the brutal approach to cancelling text selection */
457 2 mingarao
                                $('span', nPaging)
458 2 mingarao
                                        .bind( 'mousedown', function () { return false; } )
459 2 mingarao
                                        .bind( 'selectstart', function () { return false; } );
460 2 mingarao
461 2 mingarao
                                /* ID the first elements only */
462 2 mingarao
                                if ( oSettings.sTableId !== '' && typeof oSettings.aanFeatures.p == "undefined" )
463 2 mingarao
                                {
464 2 mingarao
                                        nPaging.setAttribute( 'id', oSettings.sTableId+'_paginate' );
465 2 mingarao
                                        nFirst.setAttribute( 'id', oSettings.sTableId+'_first' );
466 2 mingarao
                                        nPrevious.setAttribute( 'id', oSettings.sTableId+'_previous' );
467 2 mingarao
                                        nNext.setAttribute( 'id', oSettings.sTableId+'_next' );
468 2 mingarao
                                        nLast.setAttribute( 'id', oSettings.sTableId+'_last' );
469 2 mingarao
                                }
470 2 mingarao
                        },
471 2 mingarao
472 2 mingarao
                        /*
473 2 mingarao
                         * Function: oPagination.full_numbers.fnUpdate
474 2 mingarao
                         * Purpose:  Update the list of page buttons shows
475 2 mingarao
                         * Returns:  -
476 2 mingarao
                          * Inputs:   object:oSettings - dataTables settings object
477 2 mingarao
                         *           function:fnCallbackDraw - draw function to call on page change
478 2 mingarao
                         */
479 2 mingarao
                        "fnUpdate": function ( oSettings, fnCallbackDraw )
480 2 mingarao
                        {
481 2 mingarao
                                if ( !oSettings.aanFeatures.p )
482 2 mingarao
                                {
483 2 mingarao
                                        return;
484 2 mingarao
                                }
485 2 mingarao
486 2 mingarao
                                var iPageCount = _oExt.oPagination.iFullNumbersShowPages;
487 2 mingarao
                                var iPageCountHalf = Math.floor(iPageCount / 2);
488 2 mingarao
                                var iPages = Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength);
489 2 mingarao
                                var iCurrentPage = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1;
490 2 mingarao
                                var sList = "";
491 2 mingarao
                                var iStartButton, iEndButton, i, iLen;
492 2 mingarao
                                var oClasses = oSettings.oClasses;
493 2 mingarao
494 2 mingarao
                                /* Pages calculation */
495 2 mingarao
                                if (iPages < iPageCount)
496 2 mingarao
                                {
497 2 mingarao
                                        iStartButton = 1;
498 2 mingarao
                                        iEndButton = iPages;
499 2 mingarao
                                }
500 2 mingarao
                                else
501 2 mingarao
                                {
502 2 mingarao
                                        if (iCurrentPage <= iPageCountHalf)
503 2 mingarao
                                        {
504 2 mingarao
                                                iStartButton = 1;
505 2 mingarao
                                                iEndButton = iPageCount;
506 2 mingarao
                                        }
507 2 mingarao
                                        else
508 2 mingarao
                                        {
509 2 mingarao
                                                if (iCurrentPage >= (iPages - iPageCountHalf))
510 2 mingarao
                                                {
511 2 mingarao
                                                        iStartButton = iPages - iPageCount + 1;
512 2 mingarao
                                                        iEndButton = iPages;
513 2 mingarao
                                                }
514 2 mingarao
                                                else
515 2 mingarao
                                                {
516 2 mingarao
                                                        iStartButton = iCurrentPage - Math.ceil(iPageCount / 2) + 1;
517 2 mingarao
                                                        iEndButton = iStartButton + iPageCount - 1;
518 2 mingarao
                                                }
519 2 mingarao
                                        }
520 2 mingarao
                                }
521 2 mingarao
522 2 mingarao
                                /* Build the dynamic list */
523 2 mingarao
                                for ( i=iStartButton ; i<=iEndButton ; i++ )
524 2 mingarao
                                {
525 2 mingarao
                                        if ( iCurrentPage != i )
526 2 mingarao
                                        {
527 2 mingarao
                                                sList += '<span class="'+oClasses.sPageButton+'">'+i+'</span>';
528 2 mingarao
                                        }
529 2 mingarao
                                        else
530 2 mingarao
                                        {
531 2 mingarao
                                                sList += '<span class="'+oClasses.sPageButtonActive+'">'+i+'</span>';
532 2 mingarao
                                        }
533 2 mingarao
                                }
534 2 mingarao
535 2 mingarao
                                /* Loop over each instance of the pager */
536 2 mingarao
                                var an = oSettings.aanFeatures.p;
537 2 mingarao
                                var anButtons, anStatic, nPaginateList;
538 2 mingarao
                                var fnClick = function() {
539 2 mingarao
                                        /* Use the information in the element to jump to the required page */
540 2 mingarao
                                        var iTarget = (this.innerHTML * 1) - 1;
541 2 mingarao
                                        oSettings._iDisplayStart = iTarget * oSettings._iDisplayLength;
542 2 mingarao
                                        fnCallbackDraw( oSettings );
543 2 mingarao
                                        return false;
544 2 mingarao
                                };
545 2 mingarao
                                var fnFalse = function () { return false; };
546 2 mingarao
547 2 mingarao
                                for ( i=0, iLen=an.length ; i<iLen ; i++ )
548 2 mingarao
                                {
549 2 mingarao
                                        if ( an[i].childNodes.length === 0 )
550 2 mingarao
                                        {
551 2 mingarao
                                                continue;
552 2 mingarao
                                        }
553 2 mingarao
554 2 mingarao
                                        /* Build up the dynamic list forst - html and listeners */
555 2 mingarao
                                        var qjPaginateList = $('span:eq(2)', an[i]);
556 2 mingarao
                                        qjPaginateList.html( sList );
557 2 mingarao
                                        $('span', qjPaginateList).click( fnClick ).bind( 'mousedown', fnFalse )
558 2 mingarao
                                                .bind( 'selectstart', fnFalse );
559 2 mingarao
560 2 mingarao
                                        /* Update the 'premanent botton's classes */
561 2 mingarao
                                        anButtons = an[i].getElementsByTagName('span');
562 2 mingarao
                                        anStatic = [
563 2 mingarao
                                                anButtons[0], anButtons[1],
564 2 mingarao
                                                anButtons[anButtons.length-2], anButtons[anButtons.length-1]
565 2 mingarao
                                        ];
566 2 mingarao
                                        $(anStatic).removeClass( oClasses.sPageButton+" "+oClasses.sPageButtonActive+" "+oClasses.sPageButtonStaticDisabled );
567 2 mingarao
                                        if ( iCurrentPage == 1 )
568 2 mingarao
                                        {
569 2 mingarao
                                                anStatic[0].className += " "+oClasses.sPageButtonStaticDisabled;
570 2 mingarao
                                                anStatic[1].className += " "+oClasses.sPageButtonStaticDisabled;
571 2 mingarao
                                        }
572 2 mingarao
                                        else
573 2 mingarao
                                        {
574 2 mingarao
                                                anStatic[0].className += " "+oClasses.sPageButton;
575 2 mingarao
                                                anStatic[1].className += " "+oClasses.sPageButton;
576 2 mingarao
                                        }
577 2 mingarao
578 2 mingarao
                                        if ( iPages === 0 || iCurrentPage == iPages || oSettings._iDisplayLength == -1 )
579 2 mingarao
                                        {
580 2 mingarao
                                                anStatic[2].className += " "+oClasses.sPageButtonStaticDisabled;
581 2 mingarao
                                                anStatic[3].className += " "+oClasses.sPageButtonStaticDisabled;
582 2 mingarao
                                        }
583 2 mingarao
                                        else
584 2 mingarao
                                        {
585 2 mingarao
                                                anStatic[2].className += " "+oClasses.sPageButton;
586 2 mingarao
                                                anStatic[3].className += " "+oClasses.sPageButton;
587 2 mingarao
                                        }
588 2 mingarao
                                }
589 2 mingarao
                        }
590 2 mingarao
                }
591 2 mingarao
        };
592 2 mingarao
593 2 mingarao
        /*
594 2 mingarao
         * Variable: oSort
595 2 mingarao
         * Purpose:  Wrapper for the sorting functions that can be used in DataTables
596 2 mingarao
         * Scope:    jQuery.fn.dataTableExt
597 2 mingarao
         * Notes:    The functions provided in this object are basically standard javascript sort
598 2 mingarao
         *   functions - they expect two inputs which they then compare and then return a priority
599 2 mingarao
         *   result. For each sort method added, two functions need to be defined, an ascending sort and
600 2 mingarao
         *   a descending sort.
601 2 mingarao
         */
602 2 mingarao
        _oExt.oSort = {
603 2 mingarao
                /*
604 2 mingarao
                 * text sorting
605 2 mingarao
                 */
606 2 mingarao
                "string-asc": function ( a, b )
607 2 mingarao
                {
608 2 mingarao
                        var x = a.toLowerCase();
609 2 mingarao
                        var y = b.toLowerCase();
610 2 mingarao
                        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
611 2 mingarao
                },
612 2 mingarao
613 2 mingarao
                "string-desc": function ( a, b )
614 2 mingarao
                {
615 2 mingarao
                        var x = a.toLowerCase();
616 2 mingarao
                        var y = b.toLowerCase();
617 2 mingarao
                        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
618 2 mingarao
                },
619 2 mingarao
620 2 mingarao
621 2 mingarao
                /*
622 2 mingarao
                 * html sorting (ignore html tags)
623 2 mingarao
                 */
624 2 mingarao
                "html-asc": function ( a, b )
625 2 mingarao
                {
626 2 mingarao
                        var x = a.replace( /<.*?>/g, "" ).toLowerCase();
627 2 mingarao
                        var y = b.replace( /<.*?>/g, "" ).toLowerCase();
628 2 mingarao
                        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
629 2 mingarao
                },
630 2 mingarao
631 2 mingarao
                "html-desc": function ( a, b )
632 2 mingarao
                {
633 2 mingarao
                        var x = a.replace( /<.*?>/g, "" ).toLowerCase();
634 2 mingarao
                        var y = b.replace( /<.*?>/g, "" ).toLowerCase();
635 2 mingarao
                        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
636 2 mingarao
                },
637 2 mingarao
638 2 mingarao
639 2 mingarao
                /*
640 2 mingarao
                 * date sorting
641 2 mingarao
                 */
642 2 mingarao
                "date-asc": function ( a, b )
643 2 mingarao
                {
644 2 mingarao
                        var x = Date.parse( a );
645 2 mingarao
                        var y = Date.parse( b );
646 2 mingarao
647 2 mingarao
                        if ( isNaN(x) || x==="" )
648 2 mingarao
                        {
649 2 mingarao
                    x = Date.parse( "01/01/1970 00:00:00" );
650 2 mingarao
                        }
651 2 mingarao
                        if ( isNaN(y) || y==="" )
652 2 mingarao
                        {
653 2 mingarao
                                y =        Date.parse( "01/01/1970 00:00:00" );
654 2 mingarao
                        }
655 2 mingarao
656 2 mingarao
                        return x - y;
657 2 mingarao
                },
658 2 mingarao
659 2 mingarao
                "date-desc": function ( a, b )
660 2 mingarao
                {
661 2 mingarao
                        var x = Date.parse( a );
662 2 mingarao
                        var y = Date.parse( b );
663 2 mingarao
664 2 mingarao
                        if ( isNaN(x) || x==="" )
665 2 mingarao
                        {
666 2 mingarao
                    x = Date.parse( "01/01/1970 00:00:00" );
667 2 mingarao
                        }
668 2 mingarao
                        if ( isNaN(y) || y==="" )
669 2 mingarao
                        {
670 2 mingarao
                                y =        Date.parse( "01/01/1970 00:00:00" );
671 2 mingarao
                        }
672 2 mingarao
673 2 mingarao
                        return y - x;
674 2 mingarao
                },
675 2 mingarao
676 2 mingarao
677 2 mingarao
                /*
678 2 mingarao
                 * numerical sorting
679 2 mingarao
                 */
680 2 mingarao
                "numeric-asc": function ( a, b )
681 2 mingarao
                {
682 2 mingarao
                        var x = (a=="-" || a==="") ? 0 : a*1;
683 2 mingarao
                        var y = (b=="-" || b==="") ? 0 : b*1;
684 2 mingarao
                        return x - y;
685 2 mingarao
                },
686 2 mingarao
687 2 mingarao
                "numeric-desc": function ( a, b )
688 2 mingarao
                {
689 2 mingarao
                        var x = (a=="-" || a==="") ? 0 : a*1;
690 2 mingarao
                        var y = (b=="-" || b==="") ? 0 : b*1;
691 2 mingarao
                        return y - x;
692 2 mingarao
                }
693 2 mingarao
        };
694 2 mingarao
695 2 mingarao
696 2 mingarao
        /*
697 2 mingarao
         * Variable: aTypes
698 2 mingarao
         * Purpose:  Container for the various type of type detection that dataTables supports
699 2 mingarao
         * Scope:    jQuery.fn.dataTableExt
700 2 mingarao
         * Notes:    The functions in this array are expected to parse a string to see if it is a data
701 2 mingarao
         *   type that it recognises. If so then the function should return the name of the type (a
702 2 mingarao
         *   corresponding sort function should be defined!), if the type is not recognised then the
703 2 mingarao
         *   function should return null such that the parser and move on to check the next type.
704 2 mingarao
         *   Note that ordering is important in this array - the functions are processed linearly,
705 2 mingarao
         *   starting at index 0.
706 2 mingarao
         *   Note that the input for these functions is always a string! It cannot be any other data
707 2 mingarao
         *   type
708 2 mingarao
         */
709 2 mingarao
        _oExt.aTypes = [
710 2 mingarao
                /*
711 2 mingarao
                 * Function: -
712 2 mingarao
                 * Purpose:  Check to see if a string is numeric
713 2 mingarao
                 * Returns:  string:'numeric' or null
714 2 mingarao
                 * Inputs:   string:sText - string to check
715 2 mingarao
                 */
716 2 mingarao
                function ( sData )
717 2 mingarao
                {
718 2 mingarao
                        /* Allow zero length strings as a number */
719 2 mingarao
                        if ( sData.length === 0 )
720 2 mingarao
                        {
721 2 mingarao
                                return 'numeric';
722 2 mingarao
                        }
723 2 mingarao
724 2 mingarao
                        var sValidFirstChars = "0123456789-";
725 2 mingarao
                        var sValidChars = "0123456789.";
726 2 mingarao
                        var Char;
727 2 mingarao
                        var bDecimal = false;
728 2 mingarao
729 2 mingarao
                        /* Check for a valid first char (no period and allow negatives) */
730 2 mingarao
                        Char = sData.charAt(0);
731 2 mingarao
                        if (sValidFirstChars.indexOf(Char) == -1)
732 2 mingarao
                        {
733 2 mingarao
                                return null;
734 2 mingarao
                        }
735 2 mingarao
736 2 mingarao
                        /* Check all the other characters are valid */
737 2 mingarao
                        for ( var i=1 ; i<sData.length ; i++ )
738 2 mingarao
                        {
739 2 mingarao
                                Char = sData.charAt(i);
740 2 mingarao
                                if (sValidChars.indexOf(Char) == -1)
741 2 mingarao
                                {
742 2 mingarao
                                        return null;
743 2 mingarao
                                }
744 2 mingarao
745 2 mingarao
                                /* Only allowed one decimal place... */
746 2 mingarao
                                if ( Char == "." )
747 2 mingarao
                                {
748 2 mingarao
                                        if ( bDecimal )
749 2 mingarao
                                        {
750 2 mingarao
                                                return null;
751 2 mingarao
                                        }
752 2 mingarao
                                        bDecimal = true;
753 2 mingarao
                                }
754 2 mingarao
                        }
755 2 mingarao
756 2 mingarao
                        return 'numeric';
757 2 mingarao
                },
758 2 mingarao
759 2 mingarao
                /*
760 2 mingarao
                 * Function: -
761 2 mingarao
                 * Purpose:  Check to see if a string is actually a formatted date
762 2 mingarao
                 * Returns:  string:'date' or null
763 2 mingarao
                 * Inputs:   string:sText - string to check
764 2 mingarao
                 */
765 2 mingarao
                function ( sData )
766 2 mingarao
                {
767 2 mingarao
                        var iParse = Date.parse(sData);
768 2 mingarao
                        if ( (iParse !== null && !isNaN(iParse)) || sData.length === 0 )
769 2 mingarao
                        {
770 2 mingarao
                                return 'date';
771 2 mingarao
                        }
772 2 mingarao
                        return null;
773 2 mingarao
                },
774 2 mingarao
775 2 mingarao
                /*
776 2 mingarao
                 * Function: -
777 2 mingarao
                 * Purpose:  Check to see if a string should be treated as an HTML string
778 2 mingarao
                 * Returns:  string:'html' or null
779 2 mingarao
                 * Inputs:   string:sText - string to check
780 2 mingarao
                 */
781 2 mingarao
                function ( sData )
782 2 mingarao
                {
783 2 mingarao
                        if ( sData.indexOf('<') != -1 && sData.indexOf('>') != -1 )
784 2 mingarao
                        {
785 2 mingarao
                                return 'html';
786 2 mingarao
                        }
787 2 mingarao
                        return null;
788 2 mingarao
                }
789 2 mingarao
        ];
790 2 mingarao
791 2 mingarao
        /*
792 2 mingarao
         * Function: fnVersionCheck
793 2 mingarao
         * Purpose:  Check a version string against this version of DataTables. Useful for plug-ins
794 2 mingarao
         * Returns:  bool:true -this version of DataTables is greater or equal to the required version
795 2 mingarao
         *                false -this version of DataTales is not suitable
796 2 mingarao
         * Inputs:   string:sVersion - the version to check against. May be in the following formats:
797 2 mingarao
         *             "a", "a.b" or "a.b.c"
798 2 mingarao
         * Notes:    This function will only check the first three parts of a version string. It is
799 2 mingarao
         *   assumed that beta and dev versions will meet the requirements. This might change in future
800 2 mingarao
         */
801 2 mingarao
        _oExt.fnVersionCheck = function( sVersion )
802 2 mingarao
        {
803 2 mingarao
                /* This is cheap, but very effective */
804 2 mingarao
                var fnZPad = function (Zpad, count)
805 2 mingarao
                {
806 2 mingarao
                        while(Zpad.length < count) {
807 2 mingarao
                                Zpad += '0';
808 2 mingarao
                        }
809 2 mingarao
                        return Zpad;
810 2 mingarao
                };
811 2 mingarao
                var aThis = _oExt.sVersion.split('.');
812 2 mingarao
                var aThat = sVersion.split('.');
813 2 mingarao
                var sThis = '', sThat = '';
814 2 mingarao
815 2 mingarao
                for ( var i=0, iLen=aThat.length ; i<iLen ; i++ )
816 2 mingarao
                {
817 2 mingarao
                        sThis += fnZPad( aThis[i], 3 );
818 2 mingarao
                        sThat += fnZPad( aThat[i], 3 );
819 2 mingarao
                }
820 2 mingarao
821 2 mingarao
                return parseInt(sThis, 10) >= parseInt(sThat, 10);
822 2 mingarao
        };
823 2 mingarao
824 2 mingarao
        /*
825 2 mingarao
         * Variable: _oExternConfig
826 2 mingarao
         * Purpose:  Store information for DataTables to access globally about other instances
827 2 mingarao
         * Scope:    jQuery.fn.dataTableExt
828 2 mingarao
         */
829 2 mingarao
        _oExt._oExternConfig = {
830 2 mingarao
                /* int:iNextUnique - next unique number for an instance */
831 2 mingarao
                "iNextUnique": 0
832 2 mingarao
        };
833 2 mingarao
834 2 mingarao
835 2 mingarao
        /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
836 2 mingarao
         * Section - DataTables prototype
837 2 mingarao
         * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
838 2 mingarao
839 2 mingarao
        /*
840 2 mingarao
         * Function: dataTable
841 2 mingarao
         * Purpose:  DataTables information
842 2 mingarao
         * Returns:  -
843 2 mingarao
         * Inputs:   object:oInit - initalisation options for the table
844 2 mingarao
         */
845 2 mingarao
        $.fn.dataTable = function( oInit )
846 2 mingarao
        {
847 2 mingarao
                /*
848 2 mingarao
                 * Function: classSettings
849 2 mingarao
                 * Purpose:  Settings container function for all 'class' properties which are required
850 2 mingarao
                 *   by dataTables
851 2 mingarao
                 * Returns:  -
852 2 mingarao
                 * Inputs:   -
853 2 mingarao
                 */
854 2 mingarao
                function classSettings ()
855 2 mingarao
                {
856 2 mingarao
                        this.fnRecordsTotal = function ()
857 2 mingarao
                        {
858 2 mingarao
                                if ( this.oFeatures.bServerSide ) {
859 2 mingarao
                                        return parseInt(this._iRecordsTotal, 10);
860 2 mingarao
                                } else {
861 2 mingarao
                                        return this.aiDisplayMaster.length;
862 2 mingarao
                                }
863 2 mingarao
                        };
864 2 mingarao
865 2 mingarao
                        this.fnRecordsDisplay = function ()
866 2 mingarao
                        {
867 2 mingarao
                                if ( this.oFeatures.bServerSide ) {
868 2 mingarao
                                        return parseInt(this._iRecordsDisplay, 10);
869 2 mingarao
                                } else {
870 2 mingarao
                                        return this.aiDisplay.length;
871 2 mingarao
                                }
872 2 mingarao
                        };
873 2 mingarao
874 2 mingarao
                        this.fnDisplayEnd = function ()
875 2 mingarao
                        {
876 2 mingarao
                                if ( this.oFeatures.bServerSide ) {
877 2 mingarao
                                        if ( this.oFeatures.bPaginate === false || this._iDisplayLength == -1 ) {
878 2 mingarao
                                                return this._iDisplayStart+this.aiDisplay.length;
879 2 mingarao
                                        } else {
880 2 mingarao
                                                return Math.min( this._iDisplayStart+this._iDisplayLength,
881 2 mingarao
                                                        this._iRecordsDisplay );
882 2 mingarao
                                        }
883 2 mingarao
                                } else {
884 2 mingarao
                                        return this._iDisplayEnd;
885 2 mingarao
                                }
886 2 mingarao
                        };
887 2 mingarao
888 2 mingarao
                        /*
889 2 mingarao
                         * Variable: oInstance
890 2 mingarao
                         * Purpose:  The DataTables object for this table
891 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
892 2 mingarao
                         */
893 2 mingarao
                        this.oInstance = null;
894 2 mingarao
895 2 mingarao
                        /*
896 2 mingarao
                         * Variable: sInstance
897 2 mingarao
                         * Purpose:  Unique idendifier for each instance of the DataTables object
898 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
899 2 mingarao
                         */
900 2 mingarao
                        this.sInstance = null;
901 2 mingarao
902 2 mingarao
                        /*
903 2 mingarao
                         * Variable: oFeatures
904 2 mingarao
                         * Purpose:  Indicate the enablement of key dataTable features
905 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
906 2 mingarao
                         */
907 2 mingarao
                        this.oFeatures = {
908 2 mingarao
                                "bPaginate": true,
909 2 mingarao
                                "bLengthChange": true,
910 2 mingarao
                                "bFilter": true,
911 2 mingarao
                                "bSort": true,
912 2 mingarao
                                "bInfo": true,
913 2 mingarao
                                "bAutoWidth": true,
914 2 mingarao
                                "bProcessing": false,
915 2 mingarao
                                "bSortClasses": true,
916 2 mingarao
                                "bStateSave": false,
917 2 mingarao
                                "bServerSide": false
918 2 mingarao
                        };
919 2 mingarao
920 2 mingarao
                        /*
921 2 mingarao
                         * Variable: oScroll
922 2 mingarao
                         * Purpose:  Container for scrolling options
923 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
924 2 mingarao
                         */
925 2 mingarao
                        this.oScroll = {
926 2 mingarao
                                "sX": "",
927 2 mingarao
                                "sXInner": "",
928 2 mingarao
                                "sY": "",
929 2 mingarao
                                "bCollapse": false,
930 2 mingarao
                                "bInfinite": false,
931 2 mingarao
                                "iLoadGap": 100,
932 2 mingarao
                                "iBarWidth": 0
933 2 mingarao
                        };
934 2 mingarao
935 2 mingarao
                        /*
936 2 mingarao
                         * Variable: aanFeatures
937 2 mingarao
                         * Purpose:  Array referencing the nodes which are used for the features
938 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
939 2 mingarao
                         * Notes:    The parameters of this object match what is allowed by sDom - i.e.
940 2 mingarao
                         *   'l' - Length changing
941 2 mingarao
                         *   'f' - Filtering input
942 2 mingarao
                         *   't' - The table!
943 2 mingarao
                         *   'i' - Information
944 2 mingarao
                         *   'p' - Pagination
945 2 mingarao
                         *   'r' - pRocessing
946 2 mingarao
                         */
947 2 mingarao
                        this.aanFeatures = [];
948 2 mingarao
949 2 mingarao
                        /*
950 2 mingarao
                         * Variable: oLanguage
951 2 mingarao
                         * Purpose:  Store the language strings used by dataTables
952 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
953 2 mingarao
                         * Notes:    The words in the format _VAR_ are variables which are dynamically replaced
954 2 mingarao
                         *   by javascript
955 2 mingarao
                         */
956 2 mingarao
                        this.oLanguage = {
957 2 mingarao
                                "sProcessing": "Processing...",
958 2 mingarao
                                "sLengthMenu": "Show _MENU_ entries",
959 2 mingarao
                                "sZeroRecords": "No matching records found",
960 2 mingarao
                                "sEmptyTable": "No data available in table",
961 2 mingarao
                                "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
962 2 mingarao
                                "sInfoEmpty": "Showing 0 to 0 of 0 entries",
963 2 mingarao
                                "sInfoFiltered": "(filtered from _MAX_ total entries)",
964 2 mingarao
                                "sInfoPostFix": "",
965 2 mingarao
                                "sSearch": "Search:",
966 2 mingarao
                                "sUrl": "",
967 2 mingarao
                                "oPaginate": {
968 2 mingarao
                                        "sFirst":    "First",
969 2 mingarao
                                        "sPrevious": "Previous",
970 2 mingarao
                                        "sNext":     "Next",
971 2 mingarao
                                        "sLast":     "Last"
972 2 mingarao
                                },
973 2 mingarao
                                "fnInfoCallback": null
974 2 mingarao
                        };
975 2 mingarao
976 2 mingarao
                        /*
977 2 mingarao
                         * Variable: aoData
978 2 mingarao
                         * Purpose:  Store data information
979 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
980 2 mingarao
                         * Notes:    This is an array of objects with the following parameters:
981 2 mingarao
                         *   int: _iId - internal id for tracking
982 2 mingarao
                         *   array: _aData - internal data - used for sorting / filtering etc
983 2 mingarao
                         *   node: nTr - display node
984 2 mingarao
                         *   array node: _anHidden - hidden TD nodes
985 2 mingarao
                         *   string: _sRowStripe
986 2 mingarao
                         */
987 2 mingarao
                        this.aoData = [];
988 2 mingarao
989 2 mingarao
                        /*
990 2 mingarao
                         * Variable: aiDisplay
991 2 mingarao
                         * Purpose:  Array of indexes which are in the current display (after filtering etc)
992 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
993 2 mingarao
                         */
994 2 mingarao
                        this.aiDisplay = [];
995 2 mingarao
996 2 mingarao
                        /*
997 2 mingarao
                         * Variable: aiDisplayMaster
998 2 mingarao
                         * Purpose:  Array of indexes for display - no filtering
999 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1000 2 mingarao
                         */
1001 2 mingarao
                        this.aiDisplayMaster = [];
1002 2 mingarao
1003 2 mingarao
                        /*
1004 2 mingarao
                         * Variable: aoColumns
1005 2 mingarao
                         * Purpose:  Store information about each column that is in use
1006 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1007 2 mingarao
                         */
1008 2 mingarao
                        this.aoColumns = [];
1009 2 mingarao
1010 2 mingarao
                        /*
1011 2 mingarao
                         * Variable: iNextId
1012 2 mingarao
                         * Purpose:  Store the next unique id to be used for a new row
1013 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1014 2 mingarao
                         */
1015 2 mingarao
                        this.iNextId = 0;
1016 2 mingarao
1017 2 mingarao
                        /*
1018 2 mingarao
                         * Variable: asDataSearch
1019 2 mingarao
                         * Purpose:  Search data array for regular expression searching
1020 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1021 2 mingarao
                         */
1022 2 mingarao
                        this.asDataSearch = [];
1023 2 mingarao
1024 2 mingarao
                        /*
1025 2 mingarao
                         * Variable: oPreviousSearch
1026 2 mingarao
                         * Purpose:  Store the previous search incase we want to force a re-search
1027 2 mingarao
                         *   or compare the old search to a new one
1028 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1029 2 mingarao
                         */
1030 2 mingarao
                        this.oPreviousSearch = {
1031 2 mingarao
                                "sSearch": "",
1032 2 mingarao
                                "bRegex": false,
1033 2 mingarao
                                "bSmart": true
1034 2 mingarao
                        };
1035 2 mingarao
1036 2 mingarao
                        /*
1037 2 mingarao
                         * Variable: aoPreSearchCols
1038 2 mingarao
                         * Purpose:  Store the previous search for each column
1039 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1040 2 mingarao
                         */
1041 2 mingarao
                        this.aoPreSearchCols = [];
1042 2 mingarao
1043 2 mingarao
                        /*
1044 2 mingarao
                         * Variable: aaSorting
1045 2 mingarao
                         * Purpose:  Sorting information
1046 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1047 2 mingarao
                         * Notes:    Index 0 - column number
1048 2 mingarao
                         *           Index 1 - current sorting direction
1049 2 mingarao
                         *           Index 2 - index of asSorting for this column
1050 2 mingarao
                         */
1051 2 mingarao
                        this.aaSorting = [ [0, 'asc', 0] ];
1052 2 mingarao
1053 2 mingarao
                        /*
1054 2 mingarao
                         * Variable: aaSortingFixed
1055 2 mingarao
                         * Purpose:  Sorting information that is always applied
1056 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1057 2 mingarao
                         */
1058 2 mingarao
                        this.aaSortingFixed = null;
1059 2 mingarao
1060 2 mingarao
                        /*
1061 2 mingarao
                         * Variable: asStripClasses
1062 2 mingarao
                         * Purpose:  Classes to use for the striping of a table
1063 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1064 2 mingarao
                         */
1065 2 mingarao
                        this.asStripClasses = [];
1066 2 mingarao
1067 2 mingarao
                        /*
1068 2 mingarao
                         * Variable: asDestoryStrips
1069 2 mingarao
                         * Purpose:  If restoring a table - we should restore it's striping classes as well
1070 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1071 2 mingarao
                         */
1072 2 mingarao
                        this.asDestoryStrips = [];
1073 2 mingarao
1074 2 mingarao
                        /*
1075 2 mingarao
                         * Variable: sDestroyWidth
1076 2 mingarao
                         * Purpose:  If restoring a table - we should restore it's width
1077 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1078 2 mingarao
                         */
1079 2 mingarao
                        this.sDestroyWidth = 0;
1080 2 mingarao
1081 2 mingarao
                        /*
1082 2 mingarao
                         * Variable: fnRowCallback
1083 2 mingarao
                         * Purpose:  Call this function every time a row is inserted (draw)
1084 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1085 2 mingarao
                         */
1086 2 mingarao
                        this.fnRowCallback = null;
1087 2 mingarao
1088 2 mingarao
                        /*
1089 2 mingarao
                         * Variable: fnHeaderCallback
1090 2 mingarao
                         * Purpose:  Callback function for the header on each draw
1091 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1092 2 mingarao
                         */
1093 2 mingarao
                        this.fnHeaderCallback = null;
1094 2 mingarao
1095 2 mingarao
                        /*
1096 2 mingarao
                         * Variable: fnFooterCallback
1097 2 mingarao
                         * Purpose:  Callback function for the footer on each draw
1098 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1099 2 mingarao
                         */
1100 2 mingarao
                        this.fnFooterCallback = null;
1101 2 mingarao
1102 2 mingarao
                        /*
1103 2 mingarao
                         * Variable: aoDrawCallback
1104 2 mingarao
                         * Purpose:  Array of callback functions for draw callback functions
1105 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1106 2 mingarao
                         * Notes:    Each array element is an object with the following parameters:
1107 2 mingarao
                         *   function:fn - function to call
1108 2 mingarao
                         *   string:sName - name callback (feature). useful for arranging array
1109 2 mingarao
                         */
1110 2 mingarao
                        this.aoDrawCallback = [];
1111 2 mingarao
1112 2 mingarao
                        /*
1113 2 mingarao
                         * Variable: fnInitComplete
1114 2 mingarao
                         * Purpose:  Callback function for when the table has been initalised
1115 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1116 2 mingarao
                         */
1117 2 mingarao
                        this.fnInitComplete = null;
1118 2 mingarao
1119 2 mingarao
                        /*
1120 2 mingarao
                         * Variable: sTableId
1121 2 mingarao
                         * Purpose:  Cache the table ID for quick access
1122 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1123 2 mingarao
                         */
1124 2 mingarao
                        this.sTableId = "";
1125 2 mingarao
1126 2 mingarao
                        /*
1127 2 mingarao
                         * Variable: nTable
1128 2 mingarao
                         * Purpose:  Cache the table node for quick access
1129 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1130 2 mingarao
                         */
1131 2 mingarao
                        this.nTable = null;
1132 2 mingarao
1133 2 mingarao
                        /*
1134 2 mingarao
                         * Variable: nTHead
1135 2 mingarao
                         * Purpose:  Permanent ref to the thead element
1136 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1137 2 mingarao
                         */
1138 2 mingarao
                        this.nTHead = null;
1139 2 mingarao
1140 2 mingarao
                        /*
1141 2 mingarao
                         * Variable: nTFoot
1142 2 mingarao
                         * Purpose:  Permanent ref to the tfoot element - if it exists
1143 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1144 2 mingarao
                         */
1145 2 mingarao
                        this.nTFoot = null;
1146 2 mingarao
1147 2 mingarao
                        /*
1148 2 mingarao
                         * Variable: nTBody
1149 2 mingarao
                         * Purpose:  Permanent ref to the tbody element
1150 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1151 2 mingarao
                         */
1152 2 mingarao
                        this.nTBody = null;
1153 2 mingarao
1154 2 mingarao
                        /*
1155 2 mingarao
                         * Variable: nTableWrapper
1156 2 mingarao
                         * Purpose:  Cache the wrapper node (contains all DataTables controlled elements)
1157 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1158 2 mingarao
                         */
1159 2 mingarao
                        this.nTableWrapper = null;
1160 2 mingarao
1161 2 mingarao
                        /*
1162 2 mingarao
                         * Variable: bInitialised
1163 2 mingarao
                         * Purpose:  Indicate if all required information has been read in
1164 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1165 2 mingarao
                         */
1166 2 mingarao
                        this.bInitialised = false;
1167 2 mingarao
1168 2 mingarao
                        /*
1169 2 mingarao
                         * Variable: aoOpenRows
1170 2 mingarao
                         * Purpose:  Information about open rows
1171 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1172 2 mingarao
                         * Notes:    Has the parameters 'nTr' and 'nParent'
1173 2 mingarao
                         */
1174 2 mingarao
                        this.aoOpenRows = [];
1175 2 mingarao
1176 2 mingarao
                        /*
1177 2 mingarao
                         * Variable: sDom
1178 2 mingarao
                         * Purpose:  Dictate the positioning that the created elements will take
1179 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1180 2 mingarao
                         * Notes:
1181 2 mingarao
                         *   The following options are allowed:
1182 2 mingarao
                         *     'l' - Length changing
1183 2 mingarao
                         *     'f' - Filtering input
1184 2 mingarao
                         *     't' - The table!
1185 2 mingarao
                         *     'i' - Information
1186 2 mingarao
                         *     'p' - Pagination
1187 2 mingarao
                         *     'r' - pRocessing
1188 2 mingarao
                         *   The following constants are allowed:
1189 2 mingarao
                         *     'H' - jQueryUI theme "header" classes
1190 2 mingarao
                         *     'F' - jQueryUI theme "footer" classes
1191 2 mingarao
                         *   The following syntax is expected:
1192 2 mingarao
                         *     '<' and '>' - div elements
1193 2 mingarao
                         *     '<"class" and '>' - div with a class
1194 2 mingarao
                         *   Examples:
1195 2 mingarao
                         *     '<"wrapper"flipt>', '<lf<t>ip>'
1196 2 mingarao
                         */
1197 2 mingarao
                        this.sDom = 'lfrtip';
1198 2 mingarao
1199 2 mingarao
                        /*
1200 2 mingarao
                         * Variable: sPaginationType
1201 2 mingarao
                         * Purpose:  Note which type of sorting should be used
1202 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1203 2 mingarao
                         */
1204 2 mingarao
                        this.sPaginationType = "two_button";
1205 2 mingarao
1206 2 mingarao
                        /*
1207 2 mingarao
                         * Variable: iCookieDuration
1208 2 mingarao
                         * Purpose:  The cookie duration (for bStateSave) in seconds - default 2 hours
1209 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1210 2 mingarao
                         */
1211 2 mingarao
                        this.iCookieDuration = 60 * 60 * 2;
1212 2 mingarao
1213 2 mingarao
                        /*
1214 2 mingarao
                         * Variable: sCookiePrefix
1215 2 mingarao
                         * Purpose:  The cookie name prefix
1216 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1217 2 mingarao
                         */
1218 2 mingarao
                        this.sCookiePrefix = "SpryMedia_DataTables_";
1219 2 mingarao
1220 2 mingarao
                        /*
1221 2 mingarao
                         * Variable: fnCookieCallback
1222 2 mingarao
                         * Purpose:  Callback function for cookie creation
1223 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1224 2 mingarao
                         */
1225 2 mingarao
                        this.fnCookieCallback = null;
1226 2 mingarao
1227 2 mingarao
                        /*
1228 2 mingarao
                         * Variable: aoStateSave
1229 2 mingarao
                         * Purpose:  Array of callback functions for state saving
1230 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1231 2 mingarao
                         * Notes:    Each array element is an object with the following parameters:
1232 2 mingarao
                         *   function:fn - function to call. Takes two parameters, oSettings and the JSON string to
1233 2 mingarao
                         *     save that has been thus far created. Returns a JSON string to be inserted into a
1234 2 mingarao
                         *     json object (i.e. '"param": [ 0, 1, 2]')
1235 2 mingarao
                         *   string:sName - name of callback
1236 2 mingarao
                         */
1237 2 mingarao
                        this.aoStateSave = [];
1238 2 mingarao
1239 2 mingarao
                        /*
1240 2 mingarao
                         * Variable: aoStateLoad
1241 2 mingarao
                         * Purpose:  Array of callback functions for state loading
1242 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1243 2 mingarao
                         * Notes:    Each array element is an object with the following parameters:
1244 2 mingarao
                         *   function:fn - function to call. Takes two parameters, oSettings and the object stored.
1245 2 mingarao
                         *     May return false to cancel state loading.
1246 2 mingarao
                         *   string:sName - name of callback
1247 2 mingarao
                         */
1248 2 mingarao
                        this.aoStateLoad = [];
1249 2 mingarao
1250 2 mingarao
                        /*
1251 2 mingarao
                         * Variable: oLoadedState
1252 2 mingarao
                         * Purpose:  State that was loaded from the cookie. Useful for back reference
1253 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1254 2 mingarao
                         */
1255 2 mingarao
                        this.oLoadedState = null;
1256 2 mingarao
1257 2 mingarao
                        /*
1258 2 mingarao
                         * Variable: sAjaxSource
1259 2 mingarao
                         * Purpose:  Source url for AJAX data for the table
1260 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1261 2 mingarao
                         */
1262 2 mingarao
                        this.sAjaxSource = null;
1263 2 mingarao
1264 2 mingarao
                        /*
1265 2 mingarao
                         * Variable: bAjaxDataGet
1266 2 mingarao
                         * Purpose:  Note if draw should be blocked while getting data
1267 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1268 2 mingarao
                         */
1269 2 mingarao
                        this.bAjaxDataGet = true;
1270 2 mingarao
1271 2 mingarao
                        /*
1272 2 mingarao
                         * Variable: fnServerData
1273 2 mingarao
                         * Purpose:  Function to get the server-side data - can be overruled by the developer
1274 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1275 2 mingarao
                         */
1276 2 mingarao
                        this.fnServerData = function ( url, data, callback ) {
1277 2 mingarao
                                $.ajax( {
1278 2 mingarao
                                        "url": url,
1279 2 mingarao
                                        "data": data,
1280 2 mingarao
                                        "success": callback,
1281 2 mingarao
                                        "dataType": "json",
1282 2 mingarao
                                        "cache": false,
1283 2 mingarao
                                        "error": function (xhr, error, thrown) {
1284 2 mingarao
                                                if ( error == "parsererror" ) {
1285 2 mingarao
                                                        alert( "DataTables warning: JSON data from server could not be parsed. "+
1286 2 mingarao
                                                                "This is caused by a JSON formatting error." );
1287 2 mingarao
                                                }
1288 2 mingarao
                                        }
1289 2 mingarao
                                } );
1290 2 mingarao
                        };
1291 2 mingarao
1292 2 mingarao
                        /*
1293 2 mingarao
                         * Variable: fnFormatNumber
1294 2 mingarao
                         * Purpose:  Format numbers for display
1295 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1296 2 mingarao
                         */
1297 2 mingarao
                        this.fnFormatNumber = function ( iIn )
1298 2 mingarao
                        {
1299 2 mingarao
                                if ( iIn < 1000 )
1300 2 mingarao
                                {
1301 2 mingarao
                                        /* A small optimisation for what is likely to be the vast majority of use cases */
1302 2 mingarao
                                        return iIn;
1303 2 mingarao
                                }
1304 2 mingarao
                                else
1305 2 mingarao
                                {
1306 2 mingarao
                                        var s=(iIn+""), a=s.split(""), out="", iLen=s.length;
1307 2 mingarao
1308 2 mingarao
                                        for ( var i=0 ; i<iLen ; i++ )
1309 2 mingarao
                                        {
1310 2 mingarao
                                                if ( i%3 === 0 && i !== 0 )
1311 2 mingarao
                                                {
1312 2 mingarao
                                                        out = ','+out;
1313 2 mingarao
                                                }
1314 2 mingarao
                                                out = a[iLen-i-1]+out;
1315 2 mingarao
                                        }
1316 2 mingarao
                                }
1317 2 mingarao
                                return out;
1318 2 mingarao
                        };
1319 2 mingarao
1320 2 mingarao
                        /*
1321 2 mingarao
                         * Variable: aLengthMenu
1322 2 mingarao
                         * Purpose:  List of options that can be used for the user selectable length menu
1323 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1324 2 mingarao
                         * Note:     This varaible can take for form of a 1D array, in which case the value and the
1325 2 mingarao
                         *   displayed value in the menu are the same, or a 2D array in which case the value comes
1326 2 mingarao
                         *   from the first array, and the displayed value to the end user comes from the second
1327 2 mingarao
                         *   array. 2D example: [ [ 10, 25, 50, 100, -1 ], [ 10, 25, 50, 100, 'All' ] ];
1328 2 mingarao
                         */
1329 2 mingarao
                        this.aLengthMenu = [ 10, 25, 50, 100 ];
1330 2 mingarao
1331 2 mingarao
                        /*
1332 2 mingarao
                         * Variable: iDraw
1333 2 mingarao
                         * Purpose:  Counter for the draws that the table does. Also used as a tracker for
1334 2 mingarao
                         *   server-side processing
1335 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1336 2 mingarao
                         */
1337 2 mingarao
                        this.iDraw = 0;
1338 2 mingarao
1339 2 mingarao
                        /*
1340 2 mingarao
                         * Variable: bDrawing
1341 2 mingarao
                         * Purpose:  Indicate if a redraw is being done - useful for Ajax
1342 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1343 2 mingarao
                         */
1344 2 mingarao
                        this.bDrawing = 0;
1345 2 mingarao
1346 2 mingarao
                        /*
1347 2 mingarao
                         * Variable: iDrawError
1348 2 mingarao
                         * Purpose:  Last draw error
1349 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1350 2 mingarao
                         */
1351 2 mingarao
                        this.iDrawError = -1;
1352 2 mingarao
1353 2 mingarao
                        /*
1354 2 mingarao
                         * Variable: _iDisplayLength, _iDisplayStart, _iDisplayEnd
1355 2 mingarao
                         * Purpose:  Display length variables
1356 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1357 2 mingarao
                         * Notes:    These variable must NOT be used externally to get the data length. Rather, use
1358 2 mingarao
                         *   the fnRecordsTotal() (etc) functions.
1359 2 mingarao
                         */
1360 2 mingarao
                        this._iDisplayLength = 10;
1361 2 mingarao
                        this._iDisplayStart = 0;
1362 2 mingarao
                        this._iDisplayEnd = 10;
1363 2 mingarao
1364 2 mingarao
                        /*
1365 2 mingarao
                         * Variable: _iRecordsTotal, _iRecordsDisplay
1366 2 mingarao
                         * Purpose:  Display length variables used for server side processing
1367 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1368 2 mingarao
                         * Notes:    These variable must NOT be used externally to get the data length. Rather, use
1369 2 mingarao
                         *   the fnRecordsTotal() (etc) functions.
1370 2 mingarao
                         */
1371 2 mingarao
                        this._iRecordsTotal = 0;
1372 2 mingarao
                        this._iRecordsDisplay = 0;
1373 2 mingarao
1374 2 mingarao
                        /*
1375 2 mingarao
                         * Variable: bJUI
1376 2 mingarao
                         * Purpose:  Should we add the markup needed for jQuery UI theming?
1377 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1378 2 mingarao
                         */
1379 2 mingarao
                        this.bJUI = false;
1380 2 mingarao
1381 2 mingarao
                        /*
1382 2 mingarao
                         * Variable: bJUI
1383 2 mingarao
                         * Purpose:  Should we add the markup needed for jQuery UI theming?
1384 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1385 2 mingarao
                         */
1386 2 mingarao
                        this.oClasses = _oExt.oStdClasses;
1387 2 mingarao
1388 2 mingarao
                        /*
1389 2 mingarao
                         * Variable: bFiltered and bSorted
1390 2 mingarao
                         * Purpose:  Flags to allow callback functions to see what actions have been performed
1391 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1392 2 mingarao
                         */
1393 2 mingarao
                        this.bFiltered = false;
1394 2 mingarao
                        this.bSorted = false;
1395 2 mingarao
1396 2 mingarao
                        /*
1397 2 mingarao
                         * Variable: oInit
1398 2 mingarao
                         * Purpose:  Initialisation object that is used for the table
1399 2 mingarao
                         * Scope:    jQuery.dataTable.classSettings
1400 2 mingarao
                         */
1401 2 mingarao
                        this.oInit = null;
1402 2 mingarao
                }
1403 2 mingarao
1404 2 mingarao
                /*
1405 2 mingarao
                 * Variable: oApi
1406 2 mingarao
                 * Purpose:  Container for publicly exposed 'private' functions
1407 2 mingarao
                 * Scope:    jQuery.dataTable
1408 2 mingarao
                 */
1409 2 mingarao
                this.oApi = {};
1410 2 mingarao
1411 2 mingarao
1412 2 mingarao
                /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1413 2 mingarao
                 * Section - API functions
1414 2 mingarao
                 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1415 2 mingarao
1416 2 mingarao
                /*
1417 2 mingarao
                 * Function: fnDraw
1418 2 mingarao
                 * Purpose:  Redraw the table
1419 2 mingarao
                 * Returns:  -
1420 2 mingarao
                 * Inputs:   bool:bComplete - Refilter and resort (if enabled) the table before the draw.
1421 2 mingarao
                 *             Optional: default - true
1422 2 mingarao
                 */
1423 2 mingarao
                this.fnDraw = function( bComplete )
1424 2 mingarao
                {
1425 2 mingarao
                        var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
1426 2 mingarao
                        if ( typeof bComplete != 'undefined' && bComplete === false )
1427 2 mingarao
                        {
1428 2 mingarao
                                _fnCalculateEnd( oSettings );
1429 2 mingarao
                                _fnDraw( oSettings );
1430 2 mingarao
                        }
1431 2 mingarao
                        else
1432 2 mingarao
                        {
1433 2 mingarao
                                _fnReDraw( oSettings );
1434 2 mingarao
                        }
1435 2 mingarao
                };
1436 2 mingarao
1437 2 mingarao
                /*
1438 2 mingarao
                 * Function: fnFilter
1439 2 mingarao
                 * Purpose:  Filter the input based on data
1440 2 mingarao
                 * Returns:  -
1441 2 mingarao
                 * Inputs:   string:sInput - string to filter the table on
1442 2 mingarao
                 *           int:iColumn - optional - column to limit filtering to
1443 2 mingarao
                 *           bool:bRegex - optional - treat as regular expression or not - default false
1444 2 mingarao
                 *           bool:bSmart - optional - perform smart filtering or not - default true
1445 2 mingarao
                 *           bool:bShowGlobal - optional - show the input global filter in it's input box(es)
1446 2 mingarao
                 *              - default true
1447 2 mingarao
                 */
1448 2 mingarao
                this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal )
1449 2 mingarao
                {
1450 2 mingarao
                        var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
1451 2 mingarao
1452 2 mingarao
                        if ( !oSettings.oFeatures.bFilter )
1453 2 mingarao
                        {
1454 2 mingarao
                                return;
1455 2 mingarao
                        }
1456 2 mingarao
1457 2 mingarao
                        if ( typeof bRegex == 'undefined' )
1458 2 mingarao
                        {
1459 2 mingarao
                                bRegex = false;
1460 2 mingarao
                        }
1461 2 mingarao
1462 2 mingarao
                        if ( typeof bSmart == 'undefined' )
1463 2 mingarao
                        {
1464 2 mingarao
                                bSmart = true;
1465 2 mingarao
                        }
1466 2 mingarao
1467 2 mingarao
                        if ( typeof bShowGlobal == 'undefined' )
1468 2 mingarao
                        {
1469 2 mingarao
                                bShowGlobal = true;
1470 2 mingarao
                        }
1471 2 mingarao
1472 2 mingarao
                        if ( typeof iColumn == "undefined" || iColumn === null )
1473 2 mingarao
                        {
1474 2 mingarao
                                /* Global filter */
1475 2 mingarao
                                _fnFilterComplete( oSettings, {
1476 2 mingarao
                                        "sSearch":sInput,
1477 2 mingarao
                                        "bRegex": bRegex,
1478 2 mingarao
                                        "bSmart": bSmart
1479 2 mingarao
                                }, 1 );
1480 2 mingarao
1481 2 mingarao
                                if ( bShowGlobal && typeof oSettings.aanFeatures.f != 'undefined' )
1482 2 mingarao
                                {
1483 2 mingarao
                                        var n = oSettings.aanFeatures.f;
1484 2 mingarao
                                        for ( var i=0, iLen=n.length ; i<iLen ; i++ )
1485 2 mingarao
                                        {
1486 2 mingarao
                                                $('input', n[i]).val( sInput );
1487 2 mingarao
                                        }
1488 2 mingarao
                                }
1489 2 mingarao
                        }
1490 2 mingarao
                        else
1491 2 mingarao
                        {
1492 2 mingarao
                                /* Single column filter */
1493 2 mingarao
                                oSettings.aoPreSearchCols[ iColumn ].sSearch = sInput;
1494 2 mingarao
                                oSettings.aoPreSearchCols[ iColumn ].bRegex = bRegex;
1495 2 mingarao
                                oSettings.aoPreSearchCols[ iColumn ].bSmart = bSmart;
1496 2 mingarao
                                _fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 );
1497 2 mingarao
                        }
1498 2 mingarao
                };
1499 2 mingarao
1500 2 mingarao
                /*
1501 2 mingarao
                 * Function: fnSettings
1502 2 mingarao
                 * Purpose:  Get the settings for a particular table for extern. manipulation
1503 2 mingarao
                 * Returns:  -
1504 2 mingarao
                 * Inputs:   -
1505 2 mingarao
                 */
1506 2 mingarao
                this.fnSettings = function( nNode  )
1507 2 mingarao
                {
1508 2 mingarao
                        return _fnSettingsFromNode( this[_oExt.iApiIndex] );
1509 2 mingarao
                };
1510 2 mingarao
1511 2 mingarao
                /*
1512 2 mingarao
                 * Function: fnVersionCheck
1513 2 mingarao
                 * Notes:    The function is the same as the 'static' function provided in the ext variable
1514 2 mingarao
                 */
1515 2 mingarao
                this.fnVersionCheck = _oExt.fnVersionCheck;
1516 2 mingarao
1517 2 mingarao
                /*
1518 2 mingarao
                 * Function: fnSort
1519 2 mingarao
                 * Purpose:  Sort the table by a particular row
1520 2 mingarao
                 * Returns:  -
1521 2 mingarao
                 * Inputs:   int:iCol - the data index to sort on. Note that this will
1522 2 mingarao
                 *   not match the 'display index' if you have hidden data entries
1523 2 mingarao
                 */
1524 2 mingarao
                this.fnSort = function( aaSort )
1525 2 mingarao
                {
1526 2 mingarao
                        var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
1527 2 mingarao
                        oSettings.aaSorting = aaSort;
1528 2 mingarao
                        _fnSort( oSettings );
1529 2 mingarao
                };
1530 2 mingarao
1531 2 mingarao
                /*
1532 2 mingarao
                 * Function: fnSortListener
1533 2 mingarao
                 * Purpose:  Attach a sort listener to an element for a given column
1534 2 mingarao
                 * Returns:  -
1535 2 mingarao
                 * Inputs:   node:nNode - the element to attach the sort listener to
1536 2 mingarao
                 *           int:iColumn - the column that a click on this node will sort on
1537 2 mingarao
                 *           function:fnCallback - callback function when sort is run - optional
1538 2 mingarao
                 */
1539 2 mingarao
                this.fnSortListener = function( nNode, iColumn, fnCallback )
1540 2 mingarao
                {
1541 2 mingarao
                        _fnSortAttachListener( _fnSettingsFromNode( this[_oExt.iApiIndex] ), nNode, iColumn,
1542 2 mingarao
                                 fnCallback );
1543 2 mingarao
                };
1544 2 mingarao
1545 2 mingarao
                /*
1546 2 mingarao
                 * Function: fnAddData
1547 2 mingarao
                 * Purpose:  Add new row(s) into the table
1548 2 mingarao
                 * Returns:  array int: array of indexes (aoData) which have been added (zero length on error)
1549 2 mingarao
                 * Inputs:   array:mData - the data to be added. The length must match
1550 2 mingarao
                 *               the original data from the DOM
1551 2 mingarao
                 *             or
1552 2 mingarao
                 *             array array:mData - 2D array of data to be added
1553 2 mingarao
                 *           bool:bRedraw - redraw the table or not - default true
1554 2 mingarao
                 * Notes:    Warning - the refilter here will cause the table to redraw
1555 2 mingarao
                 *             starting at zero
1556 2 mingarao
                 * Notes:    Thanks to Yekimov Denis for contributing the basis for this function!
1557 2 mingarao
                 */
1558 2 mingarao
                this.fnAddData = function( mData, bRedraw )
1559 2 mingarao
                {
1560 2 mingarao
                        if ( mData.length === 0 )
1561 2 mingarao
                        {
1562 2 mingarao
                                return [];
1563 2 mingarao
                        }
1564 2 mingarao
1565 2 mingarao
                        var aiReturn = [];
1566 2 mingarao
                        var iTest;
1567 2 mingarao
1568 2 mingarao
                        /* Find settings from table node */
1569 2 mingarao
                        var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
1570 2 mingarao
1571 2 mingarao
                        /* Check if we want to add multiple rows or not */
1572 2 mingarao
                        if ( typeof mData[0] == "object" )
1573 2 mingarao
                        {
1574 2 mingarao
                                for ( var i=0 ; i<mData.length ; i++ )
1575 2 mingarao
                                {
1576 2 mingarao
                                        iTest = _fnAddData( oSettings, mData[i] );
1577 2 mingarao
                                        if ( iTest == -1 )
1578 2 mingarao
                                        {
1579 2 mingarao
                                                return aiReturn;
1580 2 mingarao
                                        }
1581 2 mingarao
                                        aiReturn.push( iTest );
1582 2 mingarao
                                }
1583 2 mingarao
                        }
1584 2 mingarao
                        else
1585 2 mingarao
                        {
1586 2 mingarao
                                iTest = _fnAddData( oSettings, mData );
1587 2 mingarao
                                if ( iTest == -1 )
1588 2 mingarao
                                {
1589 2 mingarao
                                        return aiReturn;
1590 2 mingarao
                                }
1591 2 mingarao
                                aiReturn.push( iTest );
1592 2 mingarao
                        }
1593 2 mingarao
1594 2 mingarao
                        oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
1595 2 mingarao
1596 2 mingarao
                        if ( typeof bRedraw == 'undefined' || bRedraw )
1597 2 mingarao
                        {
1598 2 mingarao
                                _fnReDraw( oSettings );
1599 2 mingarao
                        }
1600 2 mingarao
                        return aiReturn;
1601 2 mingarao
                };
1602 2 mingarao
1603 2 mingarao
                /*
1604 2 mingarao
                 * Function: fnDeleteRow
1605 2 mingarao
                 * Purpose:  Remove a row for the table
1606 2 mingarao
                 * Returns:  array:aReturn - the row that was deleted
1607 2 mingarao
                 * Inputs:   mixed:mTarget -
1608 2 mingarao
                 *             int: - index of aoData to be deleted, or
1609 2 mingarao
                 *             node(TR): - TR element you want to delete
1610 2 mingarao
                 *           function:fnCallBack - callback function - default null
1611 2 mingarao
                 *           bool:bRedraw - redraw the table or not - default true
1612 2 mingarao
                 */
1613 2 mingarao
                this.fnDeleteRow = function( mTarget, fnCallBack, bRedraw )
1614 2 mingarao
                {
1615 2 mingarao
                        /* Find settings from table node */
1616 2 mingarao
                        var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
1617 2 mingarao
                        var i, iAODataIndex;
1618 2 mingarao
1619 2 mingarao
                        iAODataIndex = (typeof mTarget == 'object') ?
1620 2 mingarao
                                _fnNodeToDataIndex(oSettings, mTarget) : mTarget;
1621 2 mingarao
1622 2 mingarao
                        /* Return the data array from this row */
1623 2 mingarao
                        var oData = oSettings.aoData.splice( iAODataIndex, 1 );
1624 2 mingarao
1625 2 mingarao
                        /* Remove the target row from the search array */
1626 2 mingarao
                        var iDisplayIndex = $.inArray( iAODataIndex, oSettings.aiDisplay );
1627 2 mingarao
                        oSettings.asDataSearch.splice( iDisplayIndex, 1 );
1628 2 mingarao
1629 2 mingarao
                        /* Delete from the display arrays */
1630 2 mingarao
                        _fnDeleteIndex( oSettings.aiDisplayMaster, iAODataIndex );
1631 2 mingarao
                        _fnDeleteIndex( oSettings.aiDisplay, iAODataIndex );
1632 2 mingarao
1633 2 mingarao
                        /* If there is a user callback function - call it */
1634 2 mingarao
                        if ( typeof fnCallBack == "function" )
1635 2 mingarao
                        {
1636 2 mingarao
                                fnCallBack.call( this, oSettings, oData );
1637 2 mingarao
                        }
1638 2 mingarao
1639 2 mingarao
                        /* Check for an 'overflow' they case for dislaying the table */
1640 2 mingarao
                        if ( oSettings._iDisplayStart >= oSettings.aiDisplay.length )
1641 2 mingarao
                        {
1642 2 mingarao
                                oSettings._iDisplayStart -= oSettings._iDisplayLength;
1643 2 mingarao
                                if ( oSettings._iDisplayStart < 0 )
1644 2 mingarao
                                {
1645 2 mingarao
                                        oSettings._iDisplayStart = 0;
1646 2 mingarao
                                }
1647 2 mingarao
                        }
1648 2 mingarao
1649 2 mingarao
                        if ( typeof bRedraw == 'undefined' || bRedraw )
1650 2 mingarao
                        {
1651 2 mingarao
                                _fnCalculateEnd( oSettings );
1652 2 mingarao
                                _fnDraw( oSettings );
1653 2 mingarao
                        }
1654 2 mingarao
1655 2 mingarao
                        return oData;
1656 2 mingarao
                };
1657 2 mingarao
1658 2 mingarao
                /*
1659 2 mingarao
                 * Function: fnClearTable
1660 2 mingarao
                 * Purpose:  Quickly and simply clear a table
1661 2 mingarao
                 * Returns:  -
1662 2 mingarao
                 * Inputs:   bool:bRedraw - redraw the table or not - default true
1663 2 mingarao
                 * Notes:    Thanks to Yekimov Denis for contributing the basis for this function!
1664 2 mingarao
                 */
1665 2 mingarao
                this.fnClearTable = function( bRedraw )
1666 2 mingarao
                {
1667 2 mingarao
                        /* Find settings from table node */
1668 2 mingarao
                        var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
1669 2 mingarao
                        _fnClearTable( oSettings );
1670 2 mingarao
1671 2 mingarao
                        if ( typeof bRedraw == 'undefined' || bRedraw )
1672 2 mingarao
                        {
1673 2 mingarao
                                _fnDraw( oSettings );
1674 2 mingarao
                        }
1675 2 mingarao
                };
1676 2 mingarao
1677 2 mingarao
                /*
1678 2 mingarao
                 * Function: fnOpen
1679 2 mingarao
                 * Purpose:  Open a display row (append a row after the row in question)
1680 2 mingarao
                 * Returns:  node:nNewRow - the row opened
1681 2 mingarao
                 * Inputs:   node:nTr - the table row to 'open'
1682 2 mingarao
                 *           string:sHtml - the HTML to put into the row
1683 2 mingarao
                 *           string:sClass - class to give the new TD cell
1684 2 mingarao
                 */
1685 2 mingarao
                this.fnOpen = function( nTr, sHtml, sClass )
1686 2 mingarao
                {
1687 2 mingarao
                        /* Find settings from table node */
1688 2 mingarao
                        var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
1689 2 mingarao
1690 2 mingarao
                        /* the old open one if there is one */
1691 2 mingarao
                        this.fnClose( nTr );
1692 2 mingarao
1693 2 mingarao
                        var nNewRow = document.createElement("tr");
1694 2 mingarao
                        var nNewCell = document.createElement("td");
1695 2 mingarao
                        nNewRow.appendChild( nNewCell );
1696 2 mingarao
                        nNewCell.className = sClass;
1697 2 mingarao
                        nNewCell.colSpan = _fnVisbleColumns( oSettings );
1698 2 mingarao
                        nNewCell.innerHTML = sHtml;
1699 2 mingarao
1700 2 mingarao
                        /* If the nTr isn't on the page at the moment - then we don't insert at the moment */
1701 2 mingarao
                        var nTrs = $('tr', oSettings.nTBody);
1702 2 mingarao
                        if ( $.inArray(nTr, nTrs) != -1 )
1703 2 mingarao
                        {
1704 2 mingarao
                                $(nNewRow).insertAfter(nTr);
1705 2 mingarao
                        }
1706 2 mingarao
1707 2 mingarao
                        oSettings.aoOpenRows.push( {
1708 2 mingarao
                                "nTr": nNewRow,
1709 2 mingarao
                                "nParent": nTr
1710 2 mingarao
                        } );
1711 2 mingarao
1712 2 mingarao
                        return nNewRow;
1713 2 mingarao
                };
1714 2 mingarao
1715 2 mingarao
                /*
1716 2 mingarao
                 * Function: fnClose
1717 2 mingarao
                 * Purpose:  Close a display row
1718 2 mingarao
                 * Returns:  int: 0 (success) or 1 (failed)
1719 2 mingarao
                 * Inputs:   node:nTr - the table row to 'close'
1720 2 mingarao
                 */
1721 2 mingarao
                this.fnClose = function( nTr )
1722 2 mingarao
                {
1723 2 mingarao
                        /* Find settings from table node */
1724 2 mingarao
                        var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
1725 2 mingarao
1726 2 mingarao
                        for ( var i=0 ; i<oSettings.aoOpenRows.length ; i++ )
1727 2 mingarao
                        {
1728 2 mingarao
                                if ( oSettings.aoOpenRows[i].nParent == nTr )
1729 2 mingarao
                                {
1730 2 mingarao
                                        var nTrParent = oSettings.aoOpenRows[i].nTr.parentNode;
1731 2 mingarao
                                        if ( nTrParent )
1732 2 mingarao
                                        {
1733 2 mingarao
                                                /* Remove it if it is currently on display */
1734 2 mingarao
                                                nTrParent.removeChild( oSettings.aoOpenRows[i].nTr );
1735 2 mingarao
                                        }
1736 2 mingarao
                                        oSettings.aoOpenRows.splice( i, 1 );
1737 2 mingarao
                                        return 0;
1738 2 mingarao
                                }
1739 2 mingarao
                        }
1740 2 mingarao
                        return 1;
1741 2 mingarao
                };
1742 2 mingarao
1743 2 mingarao
                /*
1744 2 mingarao
                 * Function: fnGetData
1745 2 mingarao
                 * Purpose:  Return an array with the data which is used to make up the table
1746 2 mingarao
                 * Returns:  array array string: 2d data array ([row][column]) or array string: 1d data array
1747 2 mingarao
                 *           or
1748 2 mingarao
                 *           array string (if iRow specified)
1749 2 mingarao
                 * Inputs:   mixed:mRow - optional - if not present, then the full 2D array for the table
1750 2 mingarao
                 *             if given then:
1751 2 mingarao
                 *               int: - return 1D array for aoData entry of this index
1752 2 mingarao
                 *               node(TR): - return 1D array for this TR element
1753 2 mingarao
                 * Inputs:   int:iRow - optional - if present then the array returned will be the data for
1754 2 mingarao
                 *             the row with the index 'iRow'
1755 2 mingarao
                 */
1756 2 mingarao
                this.fnGetData = function( mRow )
1757 2 mingarao
                {
1758 2 mingarao
                        var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
1759 2 mingarao
1760 2 mingarao
                        if ( typeof mRow != 'undefined' )
1761 2 mingarao
                        {
1762 2 mingarao
                                var iRow = (typeof mRow == 'object') ?
1763 2 mingarao
                                        _fnNodeToDataIndex(oSettings, mRow) : mRow;
1764 2 mingarao
                                return oSettings.aoData[iRow]._aData;
1765 2 mingarao
                        }
1766 2 mingarao
                        return _fnGetDataMaster( oSettings );
1767 2 mingarao
                };
1768 2 mingarao
1769 2 mingarao
                /*
1770 2 mingarao
                 * Function: fnGetNodes
1771 2 mingarao
                 * Purpose:  Return an array with the TR nodes used for drawing the table
1772 2 mingarao
                 * Returns:  array node: TR elements
1773 2 mingarao
                 *           or
1774 2 mingarao
                 *           node (if iRow specified)
1775 2 mingarao
                 * Inputs:   int:iRow - optional - if present then the array returned will be the node for
1776 2 mingarao
                 *             the row with the index 'iRow'
1777 2 mingarao
                 */
1778 2 mingarao
                this.fnGetNodes = function( iRow )
1779 2 mingarao
                {
1780 2 mingarao
                        var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
1781 2 mingarao
1782 2 mingarao
                        if ( typeof iRow != 'undefined' )
1783 2 mingarao
                        {
1784 2 mingarao
                                return oSettings.aoData[iRow].nTr;
1785 2 mingarao
                        }
1786 2 mingarao
                        return _fnGetTrNodes( oSettings );
1787 2 mingarao
                };
1788 2 mingarao
1789 2 mingarao
                /*
1790 2 mingarao
                 * Function: fnGetPosition
1791 2 mingarao
                 * Purpose:  Get the array indexes of a particular cell from it's DOM element
1792 2 mingarao
                 * Returns:  int: - row index, or array[ int, int, int ]: - row index, column index (visible)
1793 2 mingarao
                 *             and column index including hidden columns
1794 2 mingarao
                 * Inputs:   node:nNode - this can either be a TR or a TD in the table, the return is
1795 2 mingarao
                 *             dependent on this input
1796 2 mingarao
                 */
1797 2 mingarao
                this.fnGetPosition = function( nNode )
1798 2 mingarao
                {
1799 2 mingarao
                        var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
1800 2 mingarao
                        var i;
1801 2 mingarao
1802 2 mingarao
                        if ( nNode.nodeName.toUpperCase() == "TR" )
1803 2 mingarao
                        {
1804 2 mingarao
                                return _fnNodeToDataIndex(oSettings, nNode);
1805 2 mingarao
                        }
1806 2 mingarao
                        else if ( nNode.nodeName.toUpperCase() == "TD" )
1807 2 mingarao
                        {
1808 2 mingarao
                                var iDataIndex = _fnNodeToDataIndex(oSettings, nNode.parentNode);
1809 2 mingarao
                                var iCorrector = 0;
1810 2 mingarao
                                for ( var j=0 ; j<oSettings.aoColumns.length ; j++ )
1811 2 mingarao
                                {
1812 2 mingarao
                                        if ( oSettings.aoColumns[j].bVisible )
1813 2 mingarao
                                        {
1814 2 mingarao
                                                if ( oSettings.aoData[iDataIndex].nTr.getElementsByTagName('td')[j-iCorrector] == nNode )
1815 2 mingarao
                                                {
1816 2 mingarao
                                                        return [ iDataIndex, j-iCorrector, j ];
1817 2 mingarao
                                                }
1818 2 mingarao
                                        }
1819 2 mingarao
                                        else
1820 2 mingarao
                                        {
1821 2 mingarao
                                                iCorrector++;
1822 2 mingarao
                                        }
1823 2 mingarao
                                }
1824 2 mingarao
                        }
1825 2 mingarao
                        return null;
1826 2 mingarao
                };
1827 2 mingarao
1828 2 mingarao
                /*
1829 2 mingarao
                 * Function: fnUpdate
1830 2 mingarao
                 * Purpose:  Update a table cell or row
1831 2 mingarao
                 * Returns:  int: 0 okay, 1 error
1832 2 mingarao
                 * Inputs:   array string 'or' string:mData - data to update the cell/row with
1833 2 mingarao
                 *           mixed:mRow -
1834 2 mingarao
                 *             int: - index of aoData to be updated, or
1835 2 mingarao
                 *             node(TR): - TR element you want to update
1836 2 mingarao
                 *           int:iColumn - the column to update - optional (not used of mData is 2D)
1837 2 mingarao
                 *           bool:bRedraw - redraw the table or not - default true
1838 2 mingarao
                 *           bool:bAction - perform predraw actions or not (you will want this as 'true' if
1839 2 mingarao
                 *             you have bRedraw as true) - default true
1840 2 mingarao
                 */
1841 2 mingarao
                this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
1842 2 mingarao
                {
1843 2 mingarao
                        var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
1844 2 mingarao
                        var iVisibleColumn;
1845 2 mingarao
                        var sDisplay;
1846 2 mingarao
                        var iRow = (typeof mRow == 'object') ?
1847 2 mingarao
                                _fnNodeToDataIndex(oSettings, mRow) : mRow;
1848 2 mingarao
1849 2 mingarao
                        if ( typeof mData != 'object' )
1850 2 mingarao
                        {
1851 2 mingarao
                                sDisplay = mData;
1852 2 mingarao
                                oSettings.aoData[iRow]._aData[iColumn] = sDisplay;
1853 2 mingarao
1854 2 mingarao
                                if ( oSettings.aoColumns[iColumn].fnRender !== null )
1855 2 mingarao
                                {
1856 2 mingarao
                                        sDisplay = oSettings.aoColumns[iColumn].fnRender( {
1857 2 mingarao
                                                "iDataRow": iRow,
1858 2 mingarao
                                                "iDataColumn": iColumn,
1859 2 mingarao
                                                "aData": oSettings.aoData[iRow]._aData,
1860 2 mingarao
                                                "oSettings": oSettings
1861 2 mingarao
                                        } );
1862 2 mingarao
1863 2 mingarao
                                        if ( oSettings.aoColumns[iColumn].bUseRendered )
1864 2 mingarao
                                        {
1865 2 mingarao
                                                oSettings.aoData[iRow]._aData[iColumn] = sDisplay;
1866 2 mingarao
                                        }
1867 2 mingarao
                                }
1868 2 mingarao
1869 2 mingarao
                                iVisibleColumn = _fnColumnIndexToVisible( oSettings, iColumn );
1870 2 mingarao
                                if ( iVisibleColumn !== null )
1871 2 mingarao
                                {
1872 2 mingarao
                                        oSettings.aoData[iRow].nTr.getElementsByTagName('td')[iVisibleColumn].innerHTML =
1873 2 mingarao
                                                sDisplay;
1874 2 mingarao
                                }
1875 2 mingarao
                        }
1876 2 mingarao
                        else
1877 2 mingarao
                        {
1878 2 mingarao
                                if ( mData.length != oSettings.aoColumns.length )
1879 2 mingarao
                                {
1880 2 mingarao
                                        _fnLog( oSettings, 0, 'An array passed to fnUpdate must have the same number of '+
1881 2 mingarao
                                                'columns as the table in question - in this case '+oSettings.aoColumns.length );
1882 2 mingarao
                                        return 1;
1883 2 mingarao
                                }
1884 2 mingarao
1885 2 mingarao
                                for ( var i=0 ; i<mData.length ; i++ )
1886 2 mingarao
                                {
1887 2 mingarao
                                        sDisplay = mData[i];
1888 2 mingarao
                                        oSettings.aoData[iRow]._aData[i] = sDisplay;
1889 2 mingarao
1890 2 mingarao
                                        if ( oSettings.aoColumns[i].fnRender !== null )
1891 2 mingarao
                                        {
1892 2 mingarao
                                                sDisplay = oSettings.aoColumns[i].fnRender( {
1893 2 mingarao
                                                        "iDataRow": iRow,
1894 2 mingarao
                                                        "iDataColumn": i,
1895 2 mingarao
                                                        "aData": oSettings.aoData[iRow]._aData,
1896 2 mingarao
                                                        "oSettings": oSettings
1897 2 mingarao
                                                } );
1898 2 mingarao
1899 2 mingarao
                                                if ( oSettings.aoColumns[i].bUseRendered )
1900 2 mingarao
                                                {
1901 2 mingarao
                                                        oSettings.aoData[iRow]._aData[i] = sDisplay;
1902 2 mingarao
                                                }
1903 2 mingarao
                                        }
1904 2 mingarao
1905 2 mingarao
                                        iVisibleColumn = _fnColumnIndexToVisible( oSettings, i );
1906 2 mingarao
                                        if ( iVisibleColumn !== null )
1907 2 mingarao
                                        {
1908 2 mingarao
                                                oSettings.aoData[iRow].nTr.getElementsByTagName('td')[iVisibleColumn].innerHTML =
1909 2 mingarao
                                                        sDisplay;
1910 2 mingarao
                                        }
1911 2 mingarao
                                }
1912 2 mingarao
                        }
1913 2 mingarao
1914 2 mingarao
                        /* Modify the search index for this row (strictly this is likely not needed, since fnReDraw
1915 2 mingarao
                         * will rebuild the search array - however, the redraw might be disabled by the user)
1916 2 mingarao
                         */
1917 2 mingarao
                        var iDisplayIndex = $.inArray( iRow, oSettings.aiDisplay );
1918 2 mingarao
                        oSettings.asDataSearch[iDisplayIndex] = _fnBuildSearchRow( oSettings,
1919 2 mingarao
                                oSettings.aoData[iRow]._aData );
1920 2 mingarao
1921 2 mingarao
                        /* Perform pre-draw actions */
1922 2 mingarao
                        if ( typeof bAction == 'undefined' || bAction )
1923 2 mingarao
                        {
1924 2 mingarao
                                _fnAjustColumnSizing( oSettings );
1925 2 mingarao
                        }
1926 2 mingarao
1927 2 mingarao
                        /* Redraw the table */
1928 2 mingarao
                        if ( typeof bRedraw == 'undefined' || bRedraw )
1929 2 mingarao
                        {
1930 2 mingarao
                                _fnReDraw( oSettings );
1931 2 mingarao
                        }
1932 2 mingarao
                        return 0;
1933 2 mingarao
                };
1934 2 mingarao
1935 2 mingarao
1936 2 mingarao
                /*
1937 2 mingarao
                 * Function: fnShowColoumn
1938 2 mingarao
                 * Purpose:  Show a particular column
1939 2 mingarao
                 * Returns:  -
1940 2 mingarao
                 * Inputs:   int:iCol - the column whose display should be changed
1941 2 mingarao
                 *           bool:bShow - show (true) or hide (false) the column
1942 2 mingarao
                 *           bool:bRedraw - redraw the table or not - default true
1943 2 mingarao
                 */
1944 2 mingarao
                this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
1945 2 mingarao
                {
1946 2 mingarao
                        var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
1947 2 mingarao
                        var i, iLen;
1948 2 mingarao
                        var iColumns = oSettings.aoColumns.length;
1949 2 mingarao
                        var nTd, anTds;
1950 2 mingarao
1951 2 mingarao
                        /* No point in doing anything if we are requesting what is already true */
1952 2 mingarao
                        if ( oSettings.aoColumns[iCol].bVisible == bShow )
1953 2 mingarao
                        {
1954 2 mingarao
                                return;
1955 2 mingarao
                        }
1956 2 mingarao
1957 2 mingarao
                        var nTrHead = $('>tr', oSettings.nTHead)[0];
1958 2 mingarao
                        var nTrFoot = $('>tr', oSettings.nTFoot)[0];
1959 2 mingarao
                        var anTheadTh = [];
1960 2 mingarao
                        var anTfootTh = [];
1961 2 mingarao
                        for ( i=0 ; i<iColumns ; i++ )
1962 2 mingarao
                        {
1963 2 mingarao
                                anTheadTh.push( oSettings.aoColumns[i].nTh );
1964 2 mingarao
                                anTfootTh.push( oSettings.aoColumns[i].nTf );
1965 2 mingarao
                        }
1966 2 mingarao
1967 2 mingarao
                        /* Show the column */
1968 2 mingarao
                        if ( bShow )
1969 2 mingarao
                        {
1970 2 mingarao
                                var iInsert = 0;
1971 2 mingarao
                                for ( i=0 ; i<iCol ; i++ )
1972 2 mingarao
                                {
1973 2 mingarao
                                        if ( oSettings.aoColumns[i].bVisible )
1974 2 mingarao
                                        {
1975 2 mingarao
                                                iInsert++;
1976 2 mingarao
                                        }
1977 2 mingarao
                                }
1978 2 mingarao
1979 2 mingarao
                                /* Need to decide if we should use appendChild or insertBefore */
1980 2 mingarao
                                if ( iInsert >= _fnVisbleColumns( oSettings ) )
1981 2 mingarao
                                {
1982 2 mingarao
                                        nTrHead.appendChild( anTheadTh[iCol] );
1983 2 mingarao
                                        if ( nTrFoot )
1984 2 mingarao
                                        {
1985 2 mingarao
                                                nTrFoot.appendChild( anTfootTh[iCol] );
1986 2 mingarao
                                        }
1987 2 mingarao
1988 2 mingarao
                                        for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
1989 2 mingarao
                                        {
1990 2 mingarao
                                                nTd = oSettings.aoData[i]._anHidden[iCol];
1991 2 mingarao
                                                oSettings.aoData[i].nTr.appendChild( nTd );
1992 2 mingarao
                                        }
1993 2 mingarao
                                }
1994 2 mingarao
                                else
1995 2 mingarao
                                {
1996 2 mingarao
                                        /* Which coloumn should we be inserting before? */
1997 2 mingarao
                                        var iBefore;
1998 2 mingarao
                                        for ( i=iCol ; i<iColumns ; i++ )
1999 2 mingarao
                                        {
2000 2 mingarao
                                                iBefore = _fnColumnIndexToVisible( oSettings, i );
2001 2 mingarao
                                                if ( iBefore !== null )
2002 2 mingarao
                                                {
2003 2 mingarao
                                                        break;
2004 2 mingarao
                                                }
2005 2 mingarao
                                        }
2006 2 mingarao
2007 2 mingarao
                                        nTrHead.insertBefore( anTheadTh[iCol], nTrHead.getElementsByTagName('th')[iBefore] );
2008 2 mingarao
                                        if ( nTrFoot )
2009 2 mingarao
                                        {
2010 2 mingarao
                                                nTrFoot.insertBefore( anTfootTh[iCol], nTrFoot.getElementsByTagName('th')[iBefore] );
2011 2 mingarao
                                        }
2012 2 mingarao
2013 2 mingarao
                                        anTds = _fnGetTdNodes( oSettings );
2014 2 mingarao
                                        for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
2015 2 mingarao
                                        {
2016 2 mingarao
                                                nTd = oSettings.aoData[i]._anHidden[iCol];
2017 2 mingarao
                                                oSettings.aoData[i].nTr.insertBefore( nTd, $('>td:eq('+iBefore+')',
2018 2 mingarao
                                                        oSettings.aoData[i].nTr)[0] );
2019 2 mingarao
                                        }
2020 2 mingarao
                                }
2021 2 mingarao
2022 2 mingarao
                                oSettings.aoColumns[iCol].bVisible = true;
2023 2 mingarao
                        }
2024 2 mingarao
                        else
2025 2 mingarao
                        {
2026 2 mingarao
                                /* Remove a column from display */
2027 2 mingarao
                                nTrHead.removeChild( anTheadTh[iCol] );
2028 2 mingarao
                                if ( nTrFoot )
2029 2 mingarao
                                {
2030 2 mingarao
                                        nTrFoot.removeChild( anTfootTh[iCol] );
2031 2 mingarao
                                }
2032 2 mingarao
2033 2 mingarao
                                anTds = _fnGetTdNodes( oSettings );
2034 2 mingarao
                                for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
2035 2 mingarao
                                {
2036 2 mingarao
                                        nTd = anTds[ ( i*oSettings.aoColumns.length) + (iCol*1) ];
2037 2 mingarao
                                        oSettings.aoData[i]._anHidden[iCol] = nTd;
2038 2 mingarao
                                        nTd.parentNode.removeChild( nTd );
2039 2 mingarao
                                }
2040 2 mingarao
2041 2 mingarao
                                oSettings.aoColumns[iCol].bVisible = false;
2042 2 mingarao
                        }
2043 2 mingarao
2044 2 mingarao
                        /* If there are any 'open' rows, then we need to alter the colspan for this col change */
2045 2 mingarao
                        for ( i=0, iLen=oSettings.aoOpenRows.length ; i<iLen ; i++ )
2046 2 mingarao
                        {
2047 2 mingarao
                                oSettings.aoOpenRows[i].nTr.colSpan = _fnVisbleColumns( oSettings );
2048 2 mingarao
                        }
2049 2 mingarao
2050 2 mingarao
                        /* Do a redraw incase anything depending on the table columns needs it
2051 2 mingarao
                         * (built-in: scrolling)
2052 2 mingarao
                         */
2053 2 mingarao
                        if ( typeof bRedraw == 'undefined' || bRedraw )
2054 2 mingarao
                        {
2055 2 mingarao
                                _fnAjustColumnSizing( oSettings );
2056 2 mingarao
                                _fnDraw( oSettings );
2057 2 mingarao
                        }
2058 2 mingarao
2059 2 mingarao
                        _fnSaveState( oSettings );
2060 2 mingarao
                };
2061 2 mingarao
2062 2 mingarao
                /*
2063 2 mingarao
                 * Function: fnPageChange
2064 2 mingarao
                 * Purpose:  Change the pagination
2065 2 mingarao
                 * Returns:  -
2066 2 mingarao
                 * Inputs:   string:sAction - paging action to take: "first", "previous", "next" or "last"
2067 2 mingarao
                 *           bool:bRedraw - redraw the table or not - optional - default true
2068 2 mingarao
                 */
2069 2 mingarao
                this.fnPageChange = function ( sAction, bRedraw )
2070 2 mingarao
                {
2071 2 mingarao
                        var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
2072 2 mingarao
                        _fnPageChange( oSettings, sAction );
2073 2 mingarao
                        _fnCalculateEnd( oSettings );
2074 2 mingarao
2075 2 mingarao
                        if ( typeof bRedraw == 'undefined' || bRedraw )
2076 2 mingarao
                        {
2077 2 mingarao
                                _fnDraw( oSettings );
2078 2 mingarao
                        }
2079 2 mingarao
                };
2080 2 mingarao
2081 2 mingarao
                /*
2082 2 mingarao
                 * Function: fnDestroy
2083 2 mingarao
                 * Purpose:  Destructor for the DataTable
2084 2 mingarao
                 * Returns:  -
2085 2 mingarao
                 * Inputs:   -
2086 2 mingarao
                 */
2087 2 mingarao
                this.fnDestroy = function ( )
2088 2 mingarao
                {
2089 2 mingarao
                        var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
2090 2 mingarao
                        var nOrig = oSettings.nTableWrapper.parentNode;
2091 2 mingarao
                        var nBody = oSettings.nTBody;
2092 2 mingarao
                        var i, iLen;
2093 2 mingarao
2094 2 mingarao
                        /* Flag to note that the table is currently being destoryed - no action should be taken */
2095 2 mingarao
                        oSettings.bDestroying = true;
2096 2 mingarao
2097 2 mingarao
                        /* Restore hidden columns */
2098 2 mingarao
                        for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
2099 2 mingarao
                        {
2100 2 mingarao
                                if ( oSettings.aoColumns[i].bVisible === false )
2101 2 mingarao
                                {
2102 2 mingarao
                                        this.fnSetColumnVis( i, true );
2103 2 mingarao
                                }
2104 2 mingarao
                        }
2105 2 mingarao
2106 2 mingarao
                        /* If there is an 'empty' indicator row, remove it */
2107 2 mingarao
                        $('tbody>tr>td.'+oSettings.oClasses.sRowEmpty, oSettings.nTable).parent().remove();
2108 2 mingarao
2109 2 mingarao
                        /* When scrolling we had to break the table up - restore it */
2110 2 mingarao
                        if ( oSettings.nTable != oSettings.nTHead.parentNode )
2111 2 mingarao
                        {
2112 2 mingarao
                                $('>thead', oSettings.nTable).remove();
2113 2 mingarao
                                oSettings.nTable.appendChild( oSettings.nTHead );
2114 2 mingarao
                        }
2115 2 mingarao
2116 2 mingarao
                        if ( oSettings.nTFoot && oSettings.nTable != oSettings.nTFoot.parentNode )
2117 2 mingarao
                        {
2118 2 mingarao
                                $('>tfoot', oSettings.nTable).remove();
2119 2 mingarao
                                oSettings.nTable.appendChild( oSettings.nTFoot );
2120 2 mingarao
                        }
2121 2 mingarao
2122 2 mingarao
                        /* Remove the DataTables generated nodes, events and classes */
2123 2 mingarao
                        oSettings.nTable.parentNode.removeChild( oSettings.nTable );
2124 2 mingarao
                        $(oSettings.nTableWrapper).remove();
2125 2 mingarao
2126 2 mingarao
                        oSettings.aaSorting = [];
2127 2 mingarao
                        oSettings.aaSortingFixed = [];
2128 2 mingarao
                        _fnSortingClasses( oSettings );
2129 2 mingarao
2130 2 mingarao
                        $(_fnGetTrNodes( oSettings )).removeClass( oSettings.asStripClasses.join(' ') );
2131 2 mingarao
2132 2 mingarao
                        if ( !oSettings.bJUI )
2133 2 mingarao
                        {
2134 2 mingarao
                                $('th', oSettings.nTHead).removeClass( [ _oExt.oStdClasses.sSortable,
2135 2 mingarao
                                        _oExt.oStdClasses.sSortableAsc,
2136 2 mingarao
                                        _oExt.oStdClasses.sSortableDesc,
2137 2 mingarao
                                        _oExt.oStdClasses.sSortableNone ].join(' ')
2138 2 mingarao
                                );
2139 2 mingarao
                        }
2140 2 mingarao
                        else
2141 2 mingarao
                        {
2142 2 mingarao
                                $('th', oSettings.nTHead).removeClass( [ _oExt.oStdClasses.sSortable,
2143 2 mingarao
                                        _oExt.oJUIClasses.sSortableAsc,
2144 2 mingarao
                                        _oExt.oJUIClasses.sSortableDesc,
2145 2 mingarao
                                        _oExt.oJUIClasses.sSortableNone ].join(' ')
2146 2 mingarao
                                );
2147 2 mingarao
                                $('th span', oSettings.nTHead).remove();
2148 2 mingarao
                        }
2149 2 mingarao
2150 2 mingarao
                        /* Add the TR elements back into the table in their original order */
2151 2 mingarao
                        nOrig.appendChild( oSettings.nTable );
2152 2 mingarao
                        for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
2153 2 mingarao
                        {
2154 2 mingarao
                                nBody.appendChild( oSettings.aoData[i].nTr );
2155 2 mingarao
                        }
2156 2 mingarao
2157 2 mingarao
                        /* Restore the width of the original table */
2158 2 mingarao
                        oSettings.nTable.style.width = _fnStringToCss(oSettings.sDestroyWidth);
2159 2 mingarao
2160 2 mingarao
                        /* If the were originally odd/even type classes - then we add them back here. Note
2161 2 mingarao
                         * this is not fool proof (for example if not all rows as odd/even classes - but
2162 2 mingarao
                         * it's a good effort without getting carried away
2163 2 mingarao
                         */
2164 2 mingarao
                        $('>tr:even', nBody).addClass( oSettings.asDestoryStrips[0] );
2165 2 mingarao
                        $('>tr:odd', nBody).addClass( oSettings.asDestoryStrips[1] );
2166 2 mingarao
2167 2 mingarao
                        /* Remove the settings object from the settings array */
2168 2 mingarao
                        for ( i=0, iLen=_aoSettings.length ; i<iLen ; i++ )
2169 2 mingarao
                        {
2170 2 mingarao
                                if ( _aoSettings[i] == oSettings )
2171 2 mingarao
                                {
2172 2 mingarao
                                        _aoSettings.splice( i, 1 );
2173 2 mingarao
                                }
2174 2 mingarao
                        }
2175 2 mingarao
2176 2 mingarao
                        /* End it all */
2177 2 mingarao
                        oSettings = null;
2178 2 mingarao
                };
2179 2 mingarao
2180 2 mingarao
                /*
2181 2 mingarao
                 * Function: _fnAjustColumnSizing
2182 2 mingarao
                 * Purpose:  Update tale sizing based on content. This would most likely be used for scrolling
2183 2 mingarao
                 *   and will typically need a redraw after it.
2184 2 mingarao
                 * Returns:  -
2185 2 mingarao
                 * Inputs:   bool:bRedraw - redraw the table or not, you will typically want to - default true
2186 2 mingarao
                 */
2187 2 mingarao
                this.fnAdjustColumnSizing = function ( bRedraw )
2188 2 mingarao
                {
2189 2 mingarao
                        _fnAjustColumnSizing( _fnSettingsFromNode( this[_oExt.iApiIndex] ) );
2190 2 mingarao
2191 2 mingarao
                        if ( typeof bRedraw == 'undefined' || bRedraw )
2192 2 mingarao
                        {
2193 2 mingarao
                                this.fnDraw( false );
2194 2 mingarao
                        }
2195 2 mingarao
                };
2196 2 mingarao
2197 2 mingarao
                /*
2198 2 mingarao
                 * Plugin API functions
2199 2 mingarao
                 *
2200 2 mingarao
                 * This call will add the functions which are defined in _oExt.oApi to the
2201 2 mingarao
                 * DataTables object, providing a rather nice way to allow plug-in API functions. Note that
2202 2 mingarao
                 * this is done here, so that API function can actually override the built in API functions if
2203 2 mingarao
                 * required for a particular purpose.
2204 2 mingarao
                 */
2205 2 mingarao
2206 2 mingarao
                /*
2207 2 mingarao
                 * Function: _fnExternApiFunc
2208 2 mingarao
                 * Purpose:  Create a wrapper function for exporting an internal func to an external API func
2209 2 mingarao
                 * Returns:  function: - wrapped function
2210 2 mingarao
                 * Inputs:   string:sFunc - API function name
2211 2 mingarao
                 */
2212 2 mingarao
                function _fnExternApiFunc (sFunc)
2213 2 mingarao
                {
2214 2 mingarao
                        return function() {
2215 2 mingarao
                                        var aArgs = [_fnSettingsFromNode(this[_oExt.iApiIndex])].concat(
2216 2 mingarao
                                                Array.prototype.slice.call(arguments) );
2217 2 mingarao
                                        return _oExt.oApi[sFunc].apply( this, aArgs );
2218 2 mingarao
                                };
2219 2 mingarao
                }
2220 2 mingarao
2221 2 mingarao
                for ( var sFunc in _oExt.oApi )
2222 2 mingarao
                {
2223 2 mingarao
                        if ( sFunc )
2224 2 mingarao
                        {
2225 2 mingarao
                                /*
2226 2 mingarao
                                 * Function: anon
2227 2 mingarao
                                 * Purpose:  Wrap the plug-in API functions in order to provide the settings as 1st arg
2228 2 mingarao
                                 *   and execute in this scope
2229 2 mingarao
                                 * Returns:  -
2230 2 mingarao
                                 * Inputs:   -
2231 2 mingarao
                                 */
2232 2 mingarao
                                this[sFunc] = _fnExternApiFunc(sFunc);
2233 2 mingarao
                        }
2234 2 mingarao
                }
2235 2 mingarao
2236 2 mingarao
2237 2 mingarao
2238 2 mingarao
                /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2239 2 mingarao
                 * Section - Local functions
2240 2 mingarao
                 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2241 2 mingarao
2242 2 mingarao
                /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2243 2 mingarao
                 * Section - Initalisation
2244 2 mingarao
                 */
2245 2 mingarao
2246 2 mingarao
                /*
2247 2 mingarao
                 * Function: _fnInitalise
2248 2 mingarao
                 * Purpose:  Draw the table for the first time, adding all required features
2249 2 mingarao
                 * Returns:  -
2250 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
2251 2 mingarao
                 */
2252 2 mingarao
                function _fnInitalise ( oSettings )
2253 2 mingarao
                {
2254 2 mingarao
                        var i, iLen;
2255 2 mingarao
2256 2 mingarao
                        /* Ensure that the table data is fully initialised */
2257 2 mingarao
                        if ( oSettings.bInitialised === false )
2258 2 mingarao
                        {
2259 2 mingarao
                                setTimeout( function(){ _fnInitalise( oSettings ); }, 200 );
2260 2 mingarao
                                return;
2261 2 mingarao
                        }
2262 2 mingarao
2263 2 mingarao
                        /* Show the display HTML options */
2264 2 mingarao
                        _fnAddOptionsHtml( oSettings );
2265 2 mingarao
2266 2 mingarao
                        /* Draw the headers for the table */
2267 2 mingarao
                        _fnDrawHead( oSettings );
2268 2 mingarao
2269 2 mingarao
                        /* Okay to show that something is going on now */
2270 2 mingarao
                        _fnProcessingDisplay( oSettings, true );
2271 2 mingarao
2272 2 mingarao
                        /* Calculate sizes for columns */
2273 2 mingarao
                        if ( oSettings.oFeatures.bAutoWidth )
2274 2 mingarao
                        {
2275 2 mingarao
                                _fnCalculateColumnWidths( oSettings );
2276 2 mingarao
                        }
2277 2 mingarao
2278 2 mingarao
                        for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
2279 2 mingarao
                        {
2280 2 mingarao
                                if ( oSettings.aoColumns[i].sWidth !== null )
2281 2 mingarao
                                {
2282 2 mingarao
                                        oSettings.aoColumns[i].nTh.style.width = _fnStringToCss( oSettings.aoColumns[i].sWidth );
2283 2 mingarao
                                }
2284 2 mingarao
                        }
2285 2 mingarao
2286 2 mingarao
                        /* If there is default sorting required - let's do it. The sort function
2287 2 mingarao
                         * will do the drawing for us. Otherwise we draw the table
2288 2 mingarao
                         */
2289 2 mingarao
                        if ( oSettings.oFeatures.bSort )
2290 2 mingarao
                        {
2291 2 mingarao
                                _fnSort( oSettings );
2292 2 mingarao
                        }
2293 2 mingarao
                        else
2294 2 mingarao
                        {
2295 2 mingarao
                                oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
2296 2 mingarao
                                _fnCalculateEnd( oSettings );
2297 2 mingarao
                                _fnDraw( oSettings );
2298 2 mingarao
                        }
2299 2 mingarao
2300 2 mingarao
                        /* if there is an ajax source */
2301 2 mingarao
                        if ( oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide )
2302 2 mingarao
                        {
2303 2 mingarao
                                oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, [], function(json) {
2304 2 mingarao
                                        /* Got the data - add it to the table */
2305 2 mingarao
                                        for ( i=0 ; i<json.aaData.length ; i++ )
2306 2 mingarao
                                        {
2307 2 mingarao
                                                _fnAddData( oSettings, json.aaData[i] );
2308 2 mingarao
                                        }
2309 2 mingarao
2310 2 mingarao
                                        /* Reset the init display for cookie saving. We've already done a filter, and
2311 2 mingarao
                                         * therefore cleared it before. So we need to make it appear 'fresh'
2312 2 mingarao
                                         */
2313 2 mingarao
                                        oSettings.iInitDisplayStart = oSettings._iDisplayStart;
2314 2 mingarao
2315 2 mingarao
                                        if ( oSettings.oFeatures.bSort )
2316 2 mingarao
                                        {
2317 2 mingarao
                                                _fnSort( oSettings );
2318 2 mingarao
                                        }
2319 2 mingarao
                                        else
2320 2 mingarao
                                        {
2321 2 mingarao
                                                oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
2322 2 mingarao
                                                _fnCalculateEnd( oSettings );
2323 2 mingarao
                                                _fnDraw( oSettings );
2324 2 mingarao
                                        }
2325 2 mingarao
2326 2 mingarao
                                        _fnProcessingDisplay( oSettings, false );
2327 2 mingarao
2328 2 mingarao
                                        /* Run the init callback if there is one - done here for ajax source for json obj */
2329 2 mingarao
                                        if ( typeof oSettings.fnInitComplete == 'function' )
2330 2 mingarao
                                        {
2331 2 mingarao
                                                oSettings.fnInitComplete.call( oSettings.oInstance, oSettings, json );
2332 2 mingarao
                                        }
2333 2 mingarao
                                } );
2334 2 mingarao
                                return;
2335 2 mingarao
                        }
2336 2 mingarao
2337 2 mingarao
                        if ( !oSettings.oFeatures.bServerSide )
2338 2 mingarao
                        {
2339 2 mingarao
                                _fnProcessingDisplay( oSettings, false );
2340 2 mingarao
                        }
2341 2 mingarao
                }
2342 2 mingarao
2343 2 mingarao
                /*
2344 2 mingarao
                 * Function: _fnLanguageProcess
2345 2 mingarao
                 * Purpose:  Copy language variables from remote object to a local one
2346 2 mingarao
                 * Returns:  -
2347 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
2348 2 mingarao
                 *           object:oLanguage - Language information
2349 2 mingarao
                 *           bool:bInit - init once complete
2350 2 mingarao
                 */
2351 2 mingarao
                function _fnLanguageProcess( oSettings, oLanguage, bInit )
2352 2 mingarao
                {
2353 2 mingarao
                        _fnMap( oSettings.oLanguage, oLanguage, 'sProcessing' );
2354 2 mingarao
                        _fnMap( oSettings.oLanguage, oLanguage, 'sLengthMenu' );
2355 2 mingarao
                        _fnMap( oSettings.oLanguage, oLanguage, 'sEmptyTable' );
2356 2 mingarao
                        _fnMap( oSettings.oLanguage, oLanguage, 'sZeroRecords' );
2357 2 mingarao
                        _fnMap( oSettings.oLanguage, oLanguage, 'sInfo' );
2358 2 mingarao
                        _fnMap( oSettings.oLanguage, oLanguage, 'sInfoEmpty' );
2359 2 mingarao
                        _fnMap( oSettings.oLanguage, oLanguage, 'sInfoFiltered' );
2360 2 mingarao
                        _fnMap( oSettings.oLanguage, oLanguage, 'sInfoPostFix' );
2361 2 mingarao
                        _fnMap( oSettings.oLanguage, oLanguage, 'sSearch' );
2362 2 mingarao
2363 2 mingarao
                        if ( typeof oLanguage.oPaginate != 'undefined' )
2364 2 mingarao
                        {
2365 2 mingarao
                                _fnMap( oSettings.oLanguage.oPaginate, oLanguage.oPaginate, 'sFirst' );
2366 2 mingarao
                                _fnMap( oSettings.oLanguage.oPaginate, oLanguage.oPaginate, 'sPrevious' );
2367 2 mingarao
                                _fnMap( oSettings.oLanguage.oPaginate, oLanguage.oPaginate, 'sNext' );
2368 2 mingarao
                                _fnMap( oSettings.oLanguage.oPaginate, oLanguage.oPaginate, 'sLast' );
2369 2 mingarao
                        }
2370 2 mingarao
2371 2 mingarao
                        /* Backwards compatibility - if there is no sEmptyTable given, then use the same as
2372 2 mingarao
                         * sZeroRecords - assuming that is given.
2373 2 mingarao
                         */
2374 2 mingarao
                        if ( typeof oLanguage.sEmptyTable == 'undefined' &&
2375 2 mingarao
                             typeof oLanguage.sZeroRecords != 'undefined' )
2376 2 mingarao
                        {
2377 2 mingarao
                                _fnMap( oSettings.oLanguage, oLanguage, 'sZeroRecords', 'sEmptyTable' );
2378 2 mingarao
                        }
2379 2 mingarao
2380 2 mingarao
                        if ( bInit )
2381 2 mingarao
                        {
2382 2 mingarao
                                _fnInitalise( oSettings );
2383 2 mingarao
                        }
2384 2 mingarao
                }
2385 2 mingarao
2386 2 mingarao
                /*
2387 2 mingarao
                 * Function: _fnAddColumn
2388 2 mingarao
                 * Purpose:  Add a column to the list used for the table with default values
2389 2 mingarao
                 * Returns:  -
2390 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
2391 2 mingarao
                 *           node:nTh - the th element for this column
2392 2 mingarao
                 */
2393 2 mingarao
                function _fnAddColumn( oSettings, nTh )
2394 2 mingarao
                {
2395 2 mingarao
                        oSettings.aoColumns[ oSettings.aoColumns.length++ ] = {
2396 2 mingarao
                                "sType": null,
2397 2 mingarao
                                "_bAutoType": true,
2398 2 mingarao
                                "bVisible": true,
2399 2 mingarao
                                "bSearchable": true,
2400 2 mingarao
                                "bSortable": true,
2401 2 mingarao
                                "asSorting": [ 'asc', 'desc' ],
2402 2 mingarao
                                "sSortingClass": oSettings.oClasses.sSortable,
2403 2 mingarao
                                "sSortingClassJUI": oSettings.oClasses.sSortJUI,
2404 2 mingarao
                                "sTitle": nTh ? nTh.innerHTML : '',
2405 2 mingarao
                                "sName": '',
2406 2 mingarao
                                "sWidth": null,
2407 2 mingarao
                                "sWidthOrig": null,
2408 2 mingarao
                                "sClass": null,
2409 2 mingarao
                                "fnRender": null,
2410 2 mingarao
                                "bUseRendered": true,
2411 2 mingarao
                                "iDataSort": oSettings.aoColumns.length-1,
2412 2 mingarao
                                "sSortDataType": 'std',
2413 2 mingarao
                                "nTh": nTh ? nTh : document.createElement('th'),
2414 2 mingarao
                                "nTf": null
2415 2 mingarao
                        };
2416 2 mingarao
2417 2 mingarao
                        var iCol = oSettings.aoColumns.length-1;
2418 2 mingarao
                        var oCol = oSettings.aoColumns[ iCol ];
2419 2 mingarao
2420 2 mingarao
                        /* Add a column specific filter */
2421 2 mingarao
                        if ( typeof oSettings.aoPreSearchCols[ iCol ] == 'undefined' ||
2422 2 mingarao
                             oSettings.aoPreSearchCols[ iCol ] === null )
2423 2 mingarao
                        {
2424 2 mingarao
                                oSettings.aoPreSearchCols[ iCol ] = {
2425 2 mingarao
                                        "sSearch": "",
2426 2 mingarao
                                        "bRegex": false,
2427 2 mingarao
                                        "bSmart": true
2428 2 mingarao
                                };
2429 2 mingarao
                        }
2430 2 mingarao
                        else
2431 2 mingarao
                        {
2432 2 mingarao
                                /* Don't require that the user must specify bRegex and / or bSmart */
2433 2 mingarao
                                if ( typeof oSettings.aoPreSearchCols[ iCol ].bRegex == 'undefined' )
2434 2 mingarao
                                {
2435 2 mingarao
                                        oSettings.aoPreSearchCols[ iCol ].bRegex = true;
2436 2 mingarao
                                }
2437 2 mingarao
2438 2 mingarao
                                if ( typeof oSettings.aoPreSearchCols[ iCol ].bSmart == 'undefined' )
2439 2 mingarao
                                {
2440 2 mingarao
                                        oSettings.aoPreSearchCols[ iCol ].bSmart = true;
2441 2 mingarao
                                }
2442 2 mingarao
                        }
2443 2 mingarao
2444 2 mingarao
                        /* Use the column options function to initialise classes etc */
2445 2 mingarao
                        _fnColumnOptions( oSettings, iCol, null );
2446 2 mingarao
                }
2447 2 mingarao
2448 2 mingarao
                /*
2449 2 mingarao
                 * Function: _fnColumnOptions
2450 2 mingarao
                 * Purpose:  Apply options for a column
2451 2 mingarao
                 * Returns:  -
2452 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
2453 2 mingarao
                 *           int:iCol - column index to consider
2454 2 mingarao
                 *           object:oOptions - object with sType, bVisible and bSearchable
2455 2 mingarao
                 */
2456 2 mingarao
                function _fnColumnOptions( oSettings, iCol, oOptions )
2457 2 mingarao
                {
2458 2 mingarao
                        var oCol = oSettings.aoColumns[ iCol ];
2459 2 mingarao
2460 2 mingarao
                        /* User specified column options */
2461 2 mingarao
                        if ( typeof oOptions != 'undefined' && oOptions !== null )
2462 2 mingarao
                        {
2463 2 mingarao
                                if ( typeof oOptions.sType != 'undefined' )
2464 2 mingarao
                                {
2465 2 mingarao
                                        oCol.sType = oOptions.sType;
2466 2 mingarao
                                        oCol._bAutoType = false;
2467 2 mingarao
                                }
2468 2 mingarao
2469 2 mingarao
                                _fnMap( oCol, oOptions, "bVisible" );
2470 2 mingarao
                                _fnMap( oCol, oOptions, "bSearchable" );
2471 2 mingarao
                                _fnMap( oCol, oOptions, "bSortable" );
2472 2 mingarao
                                _fnMap( oCol, oOptions, "sTitle" );
2473 2 mingarao
                                _fnMap( oCol, oOptions, "sName" );
2474 2 mingarao
                                _fnMap( oCol, oOptions, "sWidth" );
2475 2 mingarao
                                _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
2476 2 mingarao
                                _fnMap( oCol, oOptions, "sClass" );
2477 2 mingarao
                                _fnMap( oCol, oOptions, "fnRender" );
2478 2 mingarao
                                _fnMap( oCol, oOptions, "bUseRendered" );
2479 2 mingarao
                                _fnMap( oCol, oOptions, "iDataSort" );
2480 2 mingarao
                                _fnMap( oCol, oOptions, "asSorting" );
2481 2 mingarao
                                _fnMap( oCol, oOptions, "sSortDataType" );
2482 2 mingarao
                        }
2483 2 mingarao
2484 2 mingarao
                        /* Feature sorting overrides column specific when off */
2485 2 mingarao
                        if ( !oSettings.oFeatures.bSort )
2486 2 mingarao
                        {
2487 2 mingarao
                                oCol.bSortable = false;
2488 2 mingarao
                        }
2489 2 mingarao
2490 2 mingarao
                        /* Check that the class assignment is correct for sorting */
2491 2 mingarao
                        if ( !oCol.bSortable ||
2492 2 mingarao
                                         ($.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1) )
2493 2 mingarao
                        {
2494 2 mingarao
                                oCol.sSortingClass = oSettings.oClasses.sSortableNone;
2495 2 mingarao
                                oCol.sSortingClassJUI = "";
2496 2 mingarao
                        }
2497 2 mingarao
                        else if ( $.inArray('asc', oCol.asSorting) != -1 && $.inArray('desc', oCol.asSorting) == -1 )
2498 2 mingarao
                        {
2499 2 mingarao
                                oCol.sSortingClass = oSettings.oClasses.sSortableAsc;
2500 2 mingarao
                                oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIAscAllowed;
2501 2 mingarao
                        }
2502 2 mingarao
                        else if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) != -1 )
2503 2 mingarao
                        {
2504 2 mingarao
                                oCol.sSortingClass = oSettings.oClasses.sSortableDesc;
2505 2 mingarao
                                oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIDescAllowed;
2506 2 mingarao
                        }
2507 2 mingarao
                }
2508 2 mingarao
2509 2 mingarao
                /*
2510 2 mingarao
                 * Function: _fnAddData
2511 2 mingarao
                 * Purpose:  Add a data array to the table, creating DOM node etc
2512 2 mingarao
                 * Returns:  int: - >=0 if successful (index of new aoData entry), -1 if failed
2513 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
2514 2 mingarao
                 *           array:aData - data array to be added
2515 2 mingarao
                 * Notes:    There are two basic methods for DataTables to get data to display - a JS array
2516 2 mingarao
                 *   (which is dealt with by this function), and the DOM, which has it's own optimised
2517 2 mingarao
                 *   function (_fnGatherData). Be careful to make the same changes here as there and vice-versa
2518 2 mingarao
                 */
2519 2 mingarao
                function _fnAddData ( oSettings, aDataSupplied )
2520 2 mingarao
                {
2521 2 mingarao
                        /* Sanity check the length of the new array */
2522 2 mingarao
                        if ( aDataSupplied.length != oSettings.aoColumns.length &&
2523 2 mingarao
                                oSettings.iDrawError != oSettings.iDraw )
2524 2 mingarao
                        {
2525 2 mingarao
                                _fnLog( oSettings, 0, "Added data (size "+aDataSupplied.length+") does not match known "+
2526 2 mingarao
                                        "number of columns ("+oSettings.aoColumns.length+")" );
2527 2 mingarao
                                oSettings.iDrawError = oSettings.iDraw;
2528 2 mingarao
                                return -1;
2529 2 mingarao
                        }
2530 2 mingarao
2531 2 mingarao
2532 2 mingarao
                        /* Create the object for storing information about this new row */
2533 2 mingarao
                        var aData = aDataSupplied.slice();
2534 2 mingarao
                        var iThisIndex = oSettings.aoData.length;
2535 2 mingarao
                        oSettings.aoData.push( {
2536 2 mingarao
                                "nTr": document.createElement('tr'),
2537 2 mingarao
                                "_iId": oSettings.iNextId++,
2538 2 mingarao
                                "_aData": aData,
2539 2 mingarao
                                "_anHidden": [],
2540 2 mingarao
                                "_sRowStripe": ''
2541 2 mingarao
                        } );
2542 2 mingarao
2543 2 mingarao
                        /* Create the cells */
2544 2 mingarao
                        var nTd, sThisType;
2545 2 mingarao
                        for ( var i=0 ; i<aData.length ; i++ )
2546 2 mingarao
                        {
2547 2 mingarao
                                nTd = document.createElement('td');
2548 2 mingarao
2549 2 mingarao
                                /* Allow null data (from a data array) - simply deal with it as a blank string */
2550 2 mingarao
                                if ( aData[i] === null )
2551 2 mingarao
                                {
2552 2 mingarao
                                        aData[i] = '';
2553 2 mingarao
                                }
2554 2 mingarao
2555 2 mingarao
                                if ( typeof oSettings.aoColumns[i].fnRender == 'function' )
2556 2 mingarao
                                {
2557 2 mingarao
                                        var sRendered = oSettings.aoColumns[i].fnRender( {
2558 2 mingarao
                                                        "iDataRow": iThisIndex,
2559 2 mingarao
                                                        "iDataColumn": i,
2560 2 mingarao
                                                        "aData": aData,
2561 2 mingarao
                                                        "oSettings": oSettings
2562 2 mingarao
                                                } );
2563 2 mingarao
                                        nTd.innerHTML = sRendered;
2564 2 mingarao
                                        if ( oSettings.aoColumns[i].bUseRendered )
2565 2 mingarao
                                        {
2566 2 mingarao
                                                /* Use the rendered data for filtering/sorting */
2567 2 mingarao
                                                oSettings.aoData[iThisIndex]._aData[i] = sRendered;
2568 2 mingarao
                                        }
2569 2 mingarao
                                }
2570 2 mingarao
                                else
2571 2 mingarao
                                {
2572 2 mingarao
                                        nTd.innerHTML = aData[i];
2573 2 mingarao
                                }
2574 2 mingarao
2575 2 mingarao
                                /* Cast everything as a string - so we can treat everything equally when sorting */
2576 2 mingarao
                                if ( typeof aData[i] != 'string' )
2577 2 mingarao
                                {
2578 2 mingarao
                                        aData[i] += "";
2579 2 mingarao
                                }
2580 2 mingarao
                                aData[i] = $.trim(aData[i]);
2581 2 mingarao
2582 2 mingarao
                                /* Add user defined class */
2583 2 mingarao
                                if ( oSettings.aoColumns[i].sClass !== null )
2584 2 mingarao
                                {
2585 2 mingarao
                                        nTd.className = oSettings.aoColumns[i].sClass;
2586 2 mingarao
                                }
2587 2 mingarao
2588 2 mingarao
                                /* See if we should auto-detect the column type */
2589 2 mingarao
                                if ( oSettings.aoColumns[i]._bAutoType && oSettings.aoColumns[i].sType != 'string' )
2590 2 mingarao
                                {
2591 2 mingarao
                                        /* Attempt to auto detect the type - same as _fnGatherData() */
2592 2 mingarao
                                        sThisType = _fnDetectType( oSettings.aoData[iThisIndex]._aData[i] );
2593 2 mingarao
                                        if ( oSettings.aoColumns[i].sType === null )
2594 2 mingarao
                                        {
2595 2 mingarao
                                                oSettings.aoColumns[i].sType = sThisType;
2596 2 mingarao
                                        }
2597 2 mingarao
                                        else if ( oSettings.aoColumns[i].sType != sThisType )
2598 2 mingarao
                                        {
2599 2 mingarao
                                                /* String is always the 'fallback' option */
2600 2 mingarao
                                                oSettings.aoColumns[i].sType = 'string';
2601 2 mingarao
                                        }
2602 2 mingarao
                                }
2603 2 mingarao
2604 2 mingarao
                                if ( oSettings.aoColumns[i].bVisible )
2605 2 mingarao
                                {
2606 2 mingarao
                                        oSettings.aoData[iThisIndex].nTr.appendChild( nTd );
2607 2 mingarao
                                        oSettings.aoData[iThisIndex]._anHidden[i] = null;
2608 2 mingarao
                                }
2609 2 mingarao
                                else
2610 2 mingarao
                                {
2611 2 mingarao
                                        oSettings.aoData[iThisIndex]._anHidden[i] = nTd;
2612 2 mingarao
                                }
2613 2 mingarao
                        }
2614 2 mingarao
2615 2 mingarao
                        /* Add to the display array */
2616 2 mingarao
                        oSettings.aiDisplayMaster.push( iThisIndex );
2617 2 mingarao
                        return iThisIndex;
2618 2 mingarao
                }
2619 2 mingarao
2620 2 mingarao
                /*
2621 2 mingarao
                 * Function: _fnGatherData
2622 2 mingarao
                 * Purpose:  Read in the data from the target table from the DOM
2623 2 mingarao
                 * Returns:  -
2624 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
2625 2 mingarao
                 * Notes:    This is a optimised version of _fnAddData (more or less) for reading information
2626 2 mingarao
                 *   from the DOM. The basic actions must be identical in the two functions.
2627 2 mingarao
                 */
2628 2 mingarao
                function _fnGatherData( oSettings )
2629 2 mingarao
                {
2630 2 mingarao
                        var iLoop, i, iLen, j, jLen, jInner,
2631 2 mingarao
                                 nTds, nTrs, nTd, aLocalData, iThisIndex,
2632 2 mingarao
                                iRow, iRows, iColumn, iColumns;
2633 2 mingarao
2634 2 mingarao
                        /*
2635 2 mingarao
                         * Process by row first
2636 2 mingarao
                         * Add the data object for the whole table - storing the tr node. Note - no point in getting
2637 2 mingarao
                         * DOM based data if we are going to go and replace it with Ajax source data.
2638 2 mingarao
                         */
2639 2 mingarao
                        if ( oSettings.sAjaxSource === null )
2640 2 mingarao
                        {
2641 2 mingarao
                                nTrs = oSettings.nTBody.childNodes;
2642 2 mingarao
                                for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
2643 2 mingarao
                                {
2644 2 mingarao
                                        if ( nTrs[i].nodeName.toUpperCase() == "TR" )
2645 2 mingarao
                                        {
2646 2 mingarao
                                                iThisIndex = oSettings.aoData.length;
2647 2 mingarao
                                                oSettings.aoData.push( {
2648 2 mingarao
                                                        "nTr": nTrs[i],
2649 2 mingarao
                                                        "_iId": oSettings.iNextId++,
2650 2 mingarao
                                                        "_aData": [],
2651 2 mingarao
                                                        "_anHidden": [],
2652 2 mingarao
                                                        "_sRowStripe": ''
2653 2 mingarao
                                                } );
2654 2 mingarao
2655 2 mingarao
                                                oSettings.aiDisplayMaster.push( iThisIndex );
2656 2 mingarao
2657 2 mingarao
                                                aLocalData = oSettings.aoData[iThisIndex]._aData;
2658 2 mingarao
                                                nTds = nTrs[i].childNodes;
2659 2 mingarao
                                                jInner = 0;
2660 2 mingarao
2661 2 mingarao
                                                for ( j=0, jLen=nTds.length ; j<jLen ; j++ )
2662 2 mingarao
                                                {
2663 2 mingarao
                                                        if ( nTds[j].nodeName.toUpperCase() == "TD" )
2664 2 mingarao
                                                        {
2665 2 mingarao
                                                                aLocalData[jInner] = $.trim(nTds[j].innerHTML);
2666 2 mingarao
                                                                jInner++;
2667 2 mingarao
                                                        }
2668 2 mingarao
                                                }
2669 2 mingarao
                                        }
2670 2 mingarao
                                }
2671 2 mingarao
                        }
2672 2 mingarao
2673 2 mingarao
                        /* Gather in the TD elements of the Table - note that this is basically the same as
2674 2 mingarao
                         * fnGetTdNodes, but that function takes account of hidden columns, which we haven't yet
2675 2 mingarao
                         * setup!
2676 2 mingarao
                         */
2677 2 mingarao
                        nTrs = _fnGetTrNodes( oSettings );
2678 2 mingarao
                        nTds = [];
2679 2 mingarao
                        for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
2680 2 mingarao
                        {
2681 2 mingarao
                                for ( j=0, jLen=nTrs[i].childNodes.length ; j<jLen ; j++ )
2682 2 mingarao
                                {
2683 2 mingarao
                                        nTd = nTrs[i].childNodes[j];
2684 2 mingarao
                                        if ( nTd.nodeName.toUpperCase() == "TD" )
2685 2 mingarao
                                        {
2686 2 mingarao
                                                nTds.push( nTd );
2687 2 mingarao
                                        }
2688 2 mingarao
                                }
2689 2 mingarao
                        }
2690 2 mingarao
2691 2 mingarao
                        /* Sanity check */
2692 2 mingarao
                        if ( nTds.length != nTrs.length * oSettings.aoColumns.length )
2693 2 mingarao
                        {
2694 2 mingarao
                                _fnLog( oSettings, 1, "Unexpected number of TD elements. Expected "+
2695 2 mingarao
                                        (nTrs.length * oSettings.aoColumns.length)+" and got "+nTds.length+". DataTables does "+
2696 2 mingarao
                                        "not support rowspan / colspan in the table body, and there must be one cell for each "+
2697 2 mingarao
                                        "row/column combination." );
2698 2 mingarao
                        }
2699 2 mingarao
2700 2 mingarao
                        /* Now process by column */
2701 2 mingarao
                        for ( iColumn=0, iColumns=oSettings.aoColumns.length ; iColumn<iColumns ; iColumn++ )
2702 2 mingarao
                        {
2703 2 mingarao
                                /* Get the title of the column - unless there is a user set one */
2704 2 mingarao
                                if ( oSettings.aoColumns[iColumn].sTitle === null )
2705 2 mingarao
                                {
2706 2 mingarao
                                        oSettings.aoColumns[iColumn].sTitle = oSettings.aoColumns[iColumn].nTh.innerHTML;
2707 2 mingarao
                                }
2708 2 mingarao
2709 2 mingarao
                                var
2710 2 mingarao
                                        bAutoType = oSettings.aoColumns[iColumn]._bAutoType,
2711 2 mingarao
                                        bRender = typeof oSettings.aoColumns[iColumn].fnRender == 'function',
2712 2 mingarao
                                        bClass = oSettings.aoColumns[iColumn].sClass !== null,
2713 2 mingarao
                                        bVisible = oSettings.aoColumns[iColumn].bVisible,
2714 2 mingarao
                                        nCell, sThisType, sRendered;
2715 2 mingarao
2716 2 mingarao
                                /* A single loop to rule them all (and be more efficient) */
2717 2 mingarao
                                if ( bAutoType || bRender || bClass || !bVisible )
2718 2 mingarao
                                {
2719 2 mingarao
                                        for ( iRow=0, iRows=oSettings.aoData.length ; iRow<iRows ; iRow++ )
2720 2 mingarao
                                        {
2721 2 mingarao
                                                nCell = nTds[ (iRow*iColumns) + iColumn ];
2722 2 mingarao
2723 2 mingarao
                                                /* Type detection */
2724 2 mingarao
                                                if ( bAutoType )
2725 2 mingarao
                                                {
2726 2 mingarao
                                                        if ( oSettings.aoColumns[iColumn].sType != 'string' )
2727 2 mingarao
                                                        {
2728 2 mingarao
                                                                sThisType = _fnDetectType( oSettings.aoData[iRow]._aData[iColumn] );
2729 2 mingarao
                                                                if ( oSettings.aoColumns[iColumn].sType === null )
2730 2 mingarao
                                                                {
2731 2 mingarao
                                                                        oSettings.aoColumns[iColumn].sType = sThisType;
2732 2 mingarao
                                                                }
2733 2 mingarao
                                                                else if ( oSettings.aoColumns[iColumn].sType != sThisType )
2734 2 mingarao
                                                                {
2735 2 mingarao
                                                                        /* String is always the 'fallback' option */
2736 2 mingarao
                                                                        oSettings.aoColumns[iColumn].sType = 'string';
2737 2 mingarao
                                                                }
2738 2 mingarao
                                                        }
2739 2 mingarao
                                                }
2740 2 mingarao
2741 2 mingarao
                                                /* Rendering */
2742 2 mingarao
                                                if ( bRender )
2743 2 mingarao
                                                {
2744 2 mingarao
                                                        sRendered = oSettings.aoColumns[iColumn].fnRender( {
2745 2 mingarao
                                                                        "iDataRow": iRow,
2746 2 mingarao
                                                                        "iDataColumn": iColumn,
2747 2 mingarao
                                                                        "aData": oSettings.aoData[iRow]._aData,
2748 2 mingarao
                                                                        "oSettings": oSettings
2749 2 mingarao
                                                                } );
2750 2 mingarao
                                                        nCell.innerHTML = sRendered;
2751 2 mingarao
                                                        if ( oSettings.aoColumns[iColumn].bUseRendered )
2752 2 mingarao
                                                        {
2753 2 mingarao
                                                                /* Use the rendered data for filtering/sorting */
2754 2 mingarao
                                                                oSettings.aoData[iRow]._aData[iColumn] = sRendered;
2755 2 mingarao
                                                        }
2756 2 mingarao
                                                }
2757 2 mingarao
2758 2 mingarao
                                                /* Classes */
2759 2 mingarao
                                                if ( bClass )
2760 2 mingarao
                                                {
2761 2 mingarao
                                                        nCell.className += ' '+oSettings.aoColumns[iColumn].sClass;
2762 2 mingarao
                                                }
2763 2 mingarao
2764 2 mingarao
                                                /* Column visability */
2765 2 mingarao
                                                if ( !bVisible )
2766 2 mingarao
                                                {
2767 2 mingarao
                                                        oSettings.aoData[iRow]._anHidden[iColumn] = nCell;
2768 2 mingarao
                                                        nCell.parentNode.removeChild( nCell );
2769 2 mingarao
                                                }
2770 2 mingarao
                                                else
2771 2 mingarao
                                                {
2772 2 mingarao
                                                        oSettings.aoData[iRow]._anHidden[iColumn] = null;
2773 2 mingarao
                                                }
2774 2 mingarao
                                        }
2775 2 mingarao
                                }
2776 2 mingarao
                        }
2777 2 mingarao
                }
2778 2 mingarao
2779 2 mingarao
2780 2 mingarao
2781 2 mingarao
                /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2782 2 mingarao
                 * Section - Drawing functions
2783 2 mingarao
                 */
2784 2 mingarao
2785 2 mingarao
                /*
2786 2 mingarao
                 * Function: _fnDrawHead
2787 2 mingarao
                 * Purpose:  Create the HTML header for the table
2788 2 mingarao
                 * Returns:  -
2789 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
2790 2 mingarao
                 */
2791 2 mingarao
                function _fnDrawHead( oSettings )
2792 2 mingarao
                {
2793 2 mingarao
                        var i, nTh, iLen, j, jLen;
2794 2 mingarao
                        var iThs = oSettings.nTHead.getElementsByTagName('th').length;
2795 2 mingarao
                        var iCorrector = 0;
2796 2 mingarao
2797 2 mingarao
                        /* If there is a header in place - then use it - otherwise it's going to get nuked... */
2798 2 mingarao
                        if ( iThs !== 0 )
2799 2 mingarao
                        {
2800 2 mingarao
                                /* We've got a thead from the DOM, so remove hidden columns and apply width to vis cols */
2801 2 mingarao
                                for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
2802 2 mingarao
                                {
2803 2 mingarao
                                        nTh = oSettings.aoColumns[i].nTh;
2804 2 mingarao
2805 2 mingarao
                                        if ( oSettings.aoColumns[i].bVisible )
2806 2 mingarao
                                        {
2807 2 mingarao
                                                /* Set the title of the column if it is user defined (not what was auto detected) */
2808 2 mingarao
                                                if ( oSettings.aoColumns[i].sTitle != nTh.innerHTML )
2809 2 mingarao
                                                {
2810 2 mingarao
                                                        nTh.innerHTML = oSettings.aoColumns[i].sTitle;
2811 2 mingarao
                                                }
2812 2 mingarao
                                        }
2813 2 mingarao
                                        else
2814 2 mingarao
                                        {
2815 2 mingarao
                                                nTh.parentNode.removeChild( nTh );
2816 2 mingarao
                                                iCorrector++;
2817 2 mingarao
                                        }
2818 2 mingarao
                                }
2819 2 mingarao
                        }
2820 2 mingarao
                        else
2821 2 mingarao
                        {
2822 2 mingarao
                                /* We don't have a header in the DOM - so we are going to have to create one */
2823 2 mingarao
                                var nTr = document.createElement( "tr" );
2824 2 mingarao
2825 2 mingarao
                                for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
2826 2 mingarao
                                {
2827 2 mingarao
                                        nTh = oSettings.aoColumns[i].nTh;
2828 2 mingarao
                                        nTh.innerHTML = oSettings.aoColumns[i].sTitle;
2829 2 mingarao
2830 2 mingarao
                                        if ( oSettings.aoColumns[i].bVisible )
2831 2 mingarao
                                        {
2832 2 mingarao
                                                if ( oSettings.aoColumns[i].sClass !== null )
2833 2 mingarao
                                                {
2834 2 mingarao
                                                        nTh.className = oSettings.aoColumns[i].sClass;
2835 2 mingarao
                                                }
2836 2 mingarao
2837 2 mingarao
                                                nTr.appendChild( nTh );
2838 2 mingarao
                                        }
2839 2 mingarao
                                }
2840 2 mingarao
                                $(oSettings.nTHead).html( '' )[0].appendChild( nTr );
2841 2 mingarao
                        }
2842 2 mingarao
2843 2 mingarao
                        /* Add the extra markup needed by jQuery UI's themes */
2844 2 mingarao
                        if ( oSettings.bJUI )
2845 2 mingarao
                        {
2846 2 mingarao
                                for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
2847 2 mingarao
                                {
2848 2 mingarao
                                        nTh = oSettings.aoColumns[i].nTh;
2849 2 mingarao
2850 2 mingarao
                                        var nDiv = document.createElement('div');
2851 2 mingarao
                                        nDiv.className = oSettings.oClasses.sSortJUIWrapper;
2852 2 mingarao
                                        $(nTh).contents().appendTo(nDiv);
2853 2 mingarao
2854 2 mingarao
                                        nDiv.appendChild( document.createElement('span') );
2855 2 mingarao
                                        nTh.appendChild( nDiv );
2856 2 mingarao
                                }
2857 2 mingarao
                        }
2858 2 mingarao
2859 2 mingarao
                        /* Add sort listener */
2860 2 mingarao
                        var fnNoSelect = function (e) {
2861 2 mingarao
                                this.onselectstart = function() { return false; };
2862 2 mingarao
                                return false;
2863 2 mingarao
                        };
2864 2 mingarao
2865 2 mingarao
                        if ( oSettings.oFeatures.bSort )
2866 2 mingarao
                        {
2867 2 mingarao
                                for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
2868 2 mingarao
                                {
2869 2 mingarao
                                        if ( oSettings.aoColumns[i].bSortable !== false )
2870 2 mingarao
                                        {
2871 2 mingarao
                                                _fnSortAttachListener( oSettings, oSettings.aoColumns[i].nTh, i );
2872 2 mingarao
2873 2 mingarao
                                                /* Take the brutal approach to cancelling text selection in header */
2874 2 mingarao
                                                $(oSettings.aoColumns[i].nTh).mousedown( fnNoSelect );
2875 2 mingarao
                                        }
2876 2 mingarao
                                        else
2877 2 mingarao
                                        {
2878 2 mingarao
                                                $(oSettings.aoColumns[i].nTh).addClass( oSettings.oClasses.sSortableNone );
2879 2 mingarao
                                        }
2880 2 mingarao
                                }
2881 2 mingarao
                        }
2882 2 mingarao
2883 2 mingarao
                        /* Cache the footer elements */
2884 2 mingarao
                        if ( oSettings.nTFoot !== null )
2885 2 mingarao
                        {
2886 2 mingarao
                                iCorrector = 0;
2887 2 mingarao
                                var nTfs = oSettings.nTFoot.getElementsByTagName('th');
2888 2 mingarao
                                for ( i=0, iLen=nTfs.length ; i<iLen ; i++ )
2889 2 mingarao
                                {
2890 2 mingarao
                                        if ( typeof oSettings.aoColumns[i] != 'undefined' )
2891 2 mingarao
                                        {
2892 2 mingarao
                                                oSettings.aoColumns[i].nTf = nTfs[i-iCorrector];
2893 2 mingarao
2894 2 mingarao
                                                if ( oSettings.oClasses.sFooterTH !== "" )
2895 2 mingarao
                                                {
2896 2 mingarao
                                                        oSettings.aoColumns[i].nTf.className += " "+oSettings.oClasses.sFooterTH;
2897 2 mingarao
                                                }
2898 2 mingarao
2899 2 mingarao
                                                if ( !oSettings.aoColumns[i].bVisible )
2900 2 mingarao
                                                {
2901 2 mingarao
                                                        nTfs[i-iCorrector].parentNode.removeChild( nTfs[i-iCorrector] );
2902 2 mingarao
                                                        iCorrector++;
2903 2 mingarao
                                                }
2904 2 mingarao
                                        }
2905 2 mingarao
                                }
2906 2 mingarao
                        }
2907 2 mingarao
                }
2908 2 mingarao
2909 2 mingarao
                /*
2910 2 mingarao
                 * Function: _fnDraw
2911 2 mingarao
                 * Purpose:  Insert the required TR nodes into the table for display
2912 2 mingarao
                 * Returns:  -
2913 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
2914 2 mingarao
                 */
2915 2 mingarao
                function _fnDraw( oSettings )
2916 2 mingarao
                {
2917 2 mingarao
                        var i, iLen;
2918 2 mingarao
                        var anRows = [];
2919 2 mingarao
                        var iRowCount = 0;
2920 2 mingarao
                        var bRowError = false;
2921 2 mingarao
                        var iStrips = oSettings.asStripClasses.length;
2922 2 mingarao
                        var iOpenRows = oSettings.aoOpenRows.length;
2923 2 mingarao
2924 2 mingarao
                        oSettings.bDrawing = true;
2925 2 mingarao
2926 2 mingarao
                        /* Check and see if we have an initial draw position from state saving */
2927 2 mingarao
                        if ( typeof oSettings.iInitDisplayStart != 'undefined' && oSettings.iInitDisplayStart != -1 )
2928 2 mingarao
                        {
2929 2 mingarao
                                if ( oSettings.oFeatures.bServerSide )
2930 2 mingarao
                                {
2931 2 mingarao
                                        oSettings._iDisplayStart = oSettings.iInitDisplayStart;
2932 2 mingarao
                                }
2933 2 mingarao
                                else
2934 2 mingarao
                                {
2935 2 mingarao
                                        oSettings._iDisplayStart = (oSettings.iInitDisplayStart >= oSettings.fnRecordsDisplay()) ?
2936 2 mingarao
                                                0 : oSettings.iInitDisplayStart;
2937 2 mingarao
                                }
2938 2 mingarao
                                oSettings.iInitDisplayStart = -1;
2939 2 mingarao
                                _fnCalculateEnd( oSettings );
2940 2 mingarao
                        }
2941 2 mingarao
2942 2 mingarao
                        /* If we are dealing with Ajax - do it here */
2943 2 mingarao
                        if ( oSettings.oFeatures.bServerSide &&
2944 2 mingarao
                             !_fnAjaxUpdate( oSettings ) )
2945 2 mingarao
                        {
2946 2 mingarao
                                return;
2947 2 mingarao
                        }
2948 2 mingarao
                        else if ( !oSettings.oFeatures.bServerSide )
2949 2 mingarao
                        {
2950 2 mingarao
                                oSettings.iDraw++;
2951 2 mingarao
                        }
2952 2 mingarao
2953 2 mingarao
                        if ( oSettings.aiDisplay.length !== 0 )
2954 2 mingarao
                        {
2955 2 mingarao
                                var iStart = oSettings._iDisplayStart;
2956 2 mingarao
                                var iEnd = oSettings._iDisplayEnd;
2957 2 mingarao
2958 2 mingarao
                                if ( oSettings.oFeatures.bServerSide )
2959 2 mingarao
                                {
2960 2 mingarao
                                        iStart = 0;
2961 2 mingarao
                                        iEnd = oSettings.aoData.length;
2962 2 mingarao
                                }
2963 2 mingarao
2964 2 mingarao
                                for ( var j=iStart ; j<iEnd ; j++ )
2965 2 mingarao
                                {
2966 2 mingarao
                                        var aoData = oSettings.aoData[ oSettings.aiDisplay[j] ];
2967 2 mingarao
                                        var nRow = aoData.nTr;
2968 2 mingarao
2969 2 mingarao
                                        /* Remove the old stripping classes and then add the new one */
2970 2 mingarao
                                        if ( iStrips !== 0 )
2971 2 mingarao
                                        {
2972 2 mingarao
                                                var sStrip = oSettings.asStripClasses[ iRowCount % iStrips ];
2973 2 mingarao
                                                if ( aoData._sRowStripe != sStrip )
2974 2 mingarao
                                                {
2975 2 mingarao
                                                        $(nRow).removeClass( aoData._sRowStripe ).addClass( sStrip );
2976 2 mingarao
                                                        aoData._sRowStripe = sStrip;
2977 2 mingarao
                                                }
2978 2 mingarao
                                        }
2979 2 mingarao
2980 2 mingarao
                                        /* Custom row callback function - might want to manipule the row */
2981 2 mingarao
                                        if ( typeof oSettings.fnRowCallback == "function" )
2982 2 mingarao
                                        {
2983 2 mingarao
                                                nRow = oSettings.fnRowCallback.call( oSettings.oInstance, nRow,
2984 2 mingarao
                                                        oSettings.aoData[ oSettings.aiDisplay[j] ]._aData, iRowCount, j );
2985 2 mingarao
                                                if ( !nRow && !bRowError )
2986 2 mingarao
                                                {
2987 2 mingarao
                                                        _fnLog( oSettings, 0, "A node was not returned by fnRowCallback" );
2988 2 mingarao
                                                        bRowError = true;
2989 2 mingarao
                                                }
2990 2 mingarao
                                        }
2991 2 mingarao
2992 2 mingarao
                                        anRows.push( nRow );
2993 2 mingarao
                                        iRowCount++;
2994 2 mingarao
2995 2 mingarao
                                        /* If there is an open row - and it is attached to this parent - attach it on redraw */
2996 2 mingarao
                                        if ( iOpenRows !== 0 )
2997 2 mingarao
                                        {
2998 2 mingarao
                                                for ( var k=0 ; k<iOpenRows ; k++ )
2999 2 mingarao
                                                {
3000 2 mingarao
                                                        if ( nRow == oSettings.aoOpenRows[k].nParent )
3001 2 mingarao
                                                        {
3002 2 mingarao
                                                                anRows.push( oSettings.aoOpenRows[k].nTr );
3003 2 mingarao
                                                        }
3004 2 mingarao
                                                }
3005 2 mingarao
                                        }
3006 2 mingarao
                                }
3007 2 mingarao
                        }
3008 2 mingarao
                        else
3009 2 mingarao
                        {
3010 2 mingarao
                                /* Table is empty - create a row with an empty message in it */
3011 2 mingarao
                                anRows[ 0 ] = document.createElement( 'tr' );
3012 2 mingarao
3013 2 mingarao
                                if ( typeof oSettings.asStripClasses[0] != 'undefined' )
3014 2 mingarao
                                {
3015 2 mingarao
                                        anRows[ 0 ].className = oSettings.asStripClasses[0];
3016 2 mingarao
                                }
3017 2 mingarao
3018 2 mingarao
                                var nTd = document.createElement( 'td' );
3019 2 mingarao
                                nTd.setAttribute( 'valign', "top" );
3020 2 mingarao
                                nTd.colSpan = _fnVisbleColumns( oSettings );
3021 2 mingarao
                                nTd.className = oSettings.oClasses.sRowEmpty;
3022 2 mingarao
                                if ( typeof oSettings.oLanguage.sEmptyTable != 'undefined' &&
3023 2 mingarao
                                     oSettings.fnRecordsTotal() === 0 )
3024 2 mingarao
                                {
3025 2 mingarao
                                        nTd.innerHTML = oSettings.oLanguage.sEmptyTable;
3026 2 mingarao
                                }
3027 2 mingarao
                                else
3028 2 mingarao
                                {
3029 2 mingarao
                                        nTd.innerHTML = oSettings.oLanguage.sZeroRecords.replace(
3030 2 mingarao
                                                '_MAX_', oSettings.fnFormatNumber(oSettings.fnRecordsTotal()) );
3031 2 mingarao
                                }
3032 2 mingarao
3033 2 mingarao
                                anRows[ iRowCount ].appendChild( nTd );
3034 2 mingarao
                        }
3035 2 mingarao
3036 2 mingarao
                        /* Callback the header and footer custom funcation if there is one */
3037 2 mingarao
                        if ( typeof oSettings.fnHeaderCallback == 'function' )
3038 2 mingarao
                        {
3039 2 mingarao
                                oSettings.fnHeaderCallback.call( oSettings.oInstance, $('>tr', oSettings.nTHead)[0],
3040 2 mingarao
                                        _fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(),
3041 2 mingarao
                                        oSettings.aiDisplay );
3042 2 mingarao
                        }
3043 2 mingarao
3044 2 mingarao
                        if ( typeof oSettings.fnFooterCallback == 'function' )
3045 2 mingarao
                        {
3046 2 mingarao
                                oSettings.fnFooterCallback.call( oSettings.oInstance, $('>tr', oSettings.nTFoot)[0],
3047 2 mingarao
                                        _fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(),
3048 2 mingarao
                                        oSettings.aiDisplay );
3049 2 mingarao
                        }
3050 2 mingarao
3051 2 mingarao
                        /*
3052 2 mingarao
                         * Need to remove any old row from the display - note we can't just empty the tbody using
3053 2 mingarao
                         * $().html('') since this will unbind the jQuery event handlers (even although the node
3054 2 mingarao
                         * still exists!) - equally we can't use innerHTML, since IE throws an exception.
3055 2 mingarao
                         */
3056 2 mingarao
                        var
3057 2 mingarao
                                nAddFrag = document.createDocumentFragment(),
3058 2 mingarao
                                nRemoveFrag = document.createDocumentFragment(),
3059 2 mingarao
                                nBodyPar, nTrs;
3060 2 mingarao
3061 2 mingarao
                        if ( oSettings.nTBody )
3062 2 mingarao
                        {
3063 2 mingarao
                                nBodyPar = oSettings.nTBody.parentNode;
3064 2 mingarao
                                nRemoveFrag.appendChild( oSettings.nTBody );
3065 2 mingarao
3066 2 mingarao
                                /* When doing infinite scrolling, only remove child rows when sorting, filtering or start
3067 2 mingarao
                                 * up. When not infinite scroll, always do it.
3068 2 mingarao
                                 */
3069 2 mingarao
                                if ( !oSettings.oScroll.bInfinite || !oSettings._bInitComplete ||
3070 2 mingarao
                                         oSettings.bSorted || oSettings.bFiltered )
3071 2 mingarao
                                {
3072 2 mingarao
                                        nTrs = oSettings.nTBody.childNodes;
3073 2 mingarao
                                        for ( i=nTrs.length-1 ; i>=0 ; i-- )
3074 2 mingarao
                                        {
3075 2 mingarao
                                                nTrs[i].parentNode.removeChild( nTrs[i] );
3076 2 mingarao
                                        }
3077 2 mingarao
                                }
3078 2 mingarao
3079 2 mingarao
                                /* Put the draw table into the dom */
3080 2 mingarao
                                for ( i=0, iLen=anRows.length ; i<iLen ; i++ )
3081 2 mingarao
                                {
3082 2 mingarao
                                        nAddFrag.appendChild( anRows[i] );
3083 2 mingarao
                                }
3084 2 mingarao
3085 2 mingarao
                                oSettings.nTBody.appendChild( nAddFrag );
3086 2 mingarao
                                if ( nBodyPar !== null )
3087 2 mingarao
                                {
3088 2 mingarao
                                        nBodyPar.appendChild( oSettings.nTBody );
3089 2 mingarao
                                }
3090 2 mingarao
                        }
3091 2 mingarao
3092 2 mingarao
                        /* Call all required callback functions for the end of a draw */
3093 2 mingarao
                        for ( i=0, iLen=oSettings.aoDrawCallback.length ; i<iLen ; i++ )
3094 2 mingarao
                        {
3095 2 mingarao
                                oSettings.aoDrawCallback[i].fn.call( oSettings.oInstance, oSettings );
3096 2 mingarao
                        }
3097 2 mingarao
3098 2 mingarao
                        /* Draw is complete, sorting and filtering must be as well */
3099 2 mingarao
                        oSettings.bSorted = false;
3100 2 mingarao
                        oSettings.bFiltered = false;
3101 2 mingarao
                        oSettings.bDrawing = false;
3102 2 mingarao
3103 2 mingarao
                        /* On first draw, initilaisation is now complete */
3104 2 mingarao
                        if ( typeof oSettings._bInitComplete == "undefined" )
3105 2 mingarao
                        {
3106 2 mingarao
                                oSettings._bInitComplete = true;
3107 2 mingarao
3108 2 mingarao
                                if ( typeof oSettings.fnInitComplete == 'function' &&
3109 2 mingarao
                                           (oSettings.oFeatures.bServerSide || oSettings.sAjaxSource === null) )
3110 2 mingarao
                                {
3111 2 mingarao
                                        oSettings.fnInitComplete.call( oSettings.oInstance, oSettings );
3112 2 mingarao
                                }
3113 2 mingarao
                        }
3114 2 mingarao
                }
3115 2 mingarao
3116 2 mingarao
                /*
3117 2 mingarao
                 * Function: _fnReDraw
3118 2 mingarao
                 * Purpose:  Redraw the table - taking account of the various features which are enabled
3119 2 mingarao
                 * Returns:  -
3120 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
3121 2 mingarao
                 */
3122 2 mingarao
                function _fnReDraw( oSettings )
3123 2 mingarao
                {
3124 2 mingarao
                        if ( oSettings.oFeatures.bSort )
3125 2 mingarao
                        {
3126 2 mingarao
                                /* Sorting will refilter and draw for us */
3127 2 mingarao
                                _fnSort( oSettings, oSettings.oPreviousSearch );
3128 2 mingarao
                        }
3129 2 mingarao
                        else if ( oSettings.oFeatures.bFilter )
3130 2 mingarao
                        {
3131 2 mingarao
                                /* Filtering will redraw for us */
3132 2 mingarao
                                _fnFilterComplete( oSettings, oSettings.oPreviousSearch );
3133 2 mingarao
                        }
3134 2 mingarao
                        else
3135 2 mingarao
                        {
3136 2 mingarao
                                _fnCalculateEnd( oSettings );
3137 2 mingarao
                                _fnDraw( oSettings );
3138 2 mingarao
                        }
3139 2 mingarao
                }
3140 2 mingarao
3141 2 mingarao
                /*
3142 2 mingarao
                 * Function: _fnAjaxUpdate
3143 2 mingarao
                 * Purpose:  Update the table using an Ajax call
3144 2 mingarao
                 * Returns:  bool: block the table drawing or not
3145 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
3146 2 mingarao
                 */
3147 2 mingarao
                function _fnAjaxUpdate( oSettings )
3148 2 mingarao
                {
3149 2 mingarao
                        if ( oSettings.bAjaxDataGet )
3150 2 mingarao
                        {
3151 2 mingarao
                                _fnProcessingDisplay( oSettings, true );
3152 2 mingarao
                                var iColumns = oSettings.aoColumns.length;
3153 2 mingarao
                                var aoData = [];
3154 2 mingarao
                                var i;
3155 2 mingarao
3156 2 mingarao
                                /* Paging and general */
3157 2 mingarao
                                oSettings.iDraw++;
3158 2 mingarao
                                aoData.push( { "name": "sEcho",          "value": oSettings.iDraw } );
3159 2 mingarao
                                aoData.push( { "name": "iColumns",       "value": iColumns } );
3160 2 mingarao
                                aoData.push( { "name": "sColumns",       "value": _fnColumnOrdering(oSettings) } );
3161 2 mingarao
                                aoData.push( { "name": "iDisplayStart",  "value": oSettings._iDisplayStart } );
3162 2 mingarao
                                aoData.push( { "name": "iDisplayLength", "value": oSettings.oFeatures.bPaginate !== false ?
3163 2 mingarao
                                        oSettings._iDisplayLength : -1 } );
3164 2 mingarao
3165 2 mingarao
                                /* Column names */
3166 2 mingarao
                                var aNames = [];
3167 2 mingarao
                                for ( i=0 ; i<iColumns ; i++ )
3168 2 mingarao
                                {
3169 2 mingarao
                                        aNames.push( oSettings.aoColumns[i].sName );
3170 2 mingarao
                                }
3171 2 mingarao
                                aoData.push( { "name": "sNames", "value": aNames.join(',') } );
3172 2 mingarao
3173 2 mingarao
                                /* Filtering */
3174 2 mingarao
                                if ( oSettings.oFeatures.bFilter !== false )
3175 2 mingarao
                                {
3176 2 mingarao
                                        aoData.push( { "name": "sSearch", "value": oSettings.oPreviousSearch.sSearch } );
3177 2 mingarao
                                        aoData.push( { "name": "bRegex",  "value": oSettings.oPreviousSearch.bRegex } );
3178 2 mingarao
                                        for ( i=0 ; i<iColumns ; i++ )
3179 2 mingarao
                                        {
3180 2 mingarao
                                                aoData.push( { "name": "sSearch_"+i,     "value": oSettings.aoPreSearchCols[i].sSearch } );
3181 2 mingarao
                                                aoData.push( { "name": "bRegex_"+i,      "value": oSettings.aoPreSearchCols[i].bRegex } );
3182 2 mingarao
                                                aoData.push( { "name": "bSearchable_"+i, "value": oSettings.aoColumns[i].bSearchable } );
3183 2 mingarao
                                        }
3184 2 mingarao
                                }
3185 2 mingarao
3186 2 mingarao
                                /* Sorting */
3187 2 mingarao
                                if ( oSettings.oFeatures.bSort !== false )
3188 2 mingarao
                                {
3189 2 mingarao
                                        var iFixed = oSettings.aaSortingFixed !== null ? oSettings.aaSortingFixed.length : 0;
3190 2 mingarao
                                        var iUser = oSettings.aaSorting.length;
3191 2 mingarao
                                        aoData.push( { "name": "iSortingCols",   "value": iFixed+iUser } );
3192 2 mingarao
                                        for ( i=0 ; i<iFixed ; i++ )
3193 2 mingarao
                                        {
3194 2 mingarao
                                                aoData.push( { "name": "iSortCol_"+i,  "value": oSettings.aaSortingFixed[i][0] } );
3195 2 mingarao
                                                aoData.push( { "name": "sSortDir_"+i,  "value": oSettings.aaSortingFixed[i][1] } );
3196 2 mingarao
                                        }
3197 2 mingarao
3198 2 mingarao
                                        for ( i=0 ; i<iUser ; i++ )
3199 2 mingarao
                                        {
3200 2 mingarao
                                                aoData.push( { "name": "iSortCol_"+(i+iFixed),  "value": oSettings.aaSorting[i][0] } );
3201 2 mingarao
                                                aoData.push( { "name": "sSortDir_"+(i+iFixed),  "value": oSettings.aaSorting[i][1] } );
3202 2 mingarao
                                        }
3203 2 mingarao
3204 2 mingarao
                                        for ( i=0 ; i<iColumns ; i++ )
3205 2 mingarao
                                        {
3206 2 mingarao
                                                aoData.push( { "name": "bSortable_"+i,  "value": oSettings.aoColumns[i].bSortable } );
3207 2 mingarao
                                        }
3208 2 mingarao
                                }
3209 2 mingarao
3210 2 mingarao
                                oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aoData,
3211 2 mingarao
                                        function(json) {
3212 2 mingarao
                                                _fnAjaxUpdateDraw( oSettings, json );
3213 2 mingarao
                                        } );
3214 2 mingarao
                                return false;
3215 2 mingarao
                        }
3216 2 mingarao
                        else
3217 2 mingarao
                        {
3218 2 mingarao
                                return true;
3219 2 mingarao
                        }
3220 2 mingarao
                }
3221 2 mingarao
3222 2 mingarao
                /*
3223 2 mingarao
                 * Function: _fnAjaxUpdateDraw
3224 2 mingarao
                 * Purpose:  Data the data from the server (nuking the old) and redraw the table
3225 2 mingarao
                 * Returns:  -
3226 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
3227 2 mingarao
                 *           object:json - json data return from the server.
3228 2 mingarao
                 *             The following must be defined:
3229 2 mingarao
                 *               iTotalRecords, iTotalDisplayRecords, aaData
3230 2 mingarao
                 *             The following may be defined:
3231 2 mingarao
                 *               sColumns
3232 2 mingarao
                 */
3233 2 mingarao
                function _fnAjaxUpdateDraw ( oSettings, json )
3234 2 mingarao
                {
3235 2 mingarao
                        if ( typeof json.sEcho != 'undefined' )
3236 2 mingarao
                        {
3237 2 mingarao
                                /* Protect against old returns over-writing a new one. Possible when you get
3238 2 mingarao
                                 * very fast interaction, and later queires are completed much faster
3239 2 mingarao
                                 */
3240 2 mingarao
                                if ( json.sEcho*1 < oSettings.iDraw )
3241 2 mingarao
                                {
3242 2 mingarao
                                        return;
3243 2 mingarao
                                }
3244 2 mingarao
                                else
3245 2 mingarao
                                {
3246 2 mingarao
                                        oSettings.iDraw = json.sEcho * 1;
3247 2 mingarao
                                }
3248 2 mingarao
                        }
3249 2 mingarao
3250 2 mingarao
                        if ( !oSettings.oScroll.bInfinite ||
3251 2 mingarao
                                   (oSettings.oScroll.bInfinite && (oSettings.bSorted || oSettings.bFiltered)) )
3252 2 mingarao
                        {
3253 2 mingarao
                                _fnClearTable( oSettings );
3254 2 mingarao
                        }
3255 2 mingarao
                        oSettings._iRecordsTotal = json.iTotalRecords;
3256 2 mingarao
                        oSettings._iRecordsDisplay = json.iTotalDisplayRecords;
3257 2 mingarao
3258 2 mingarao
                        /* Determine if reordering is required */
3259 2 mingarao
                        var sOrdering = _fnColumnOrdering(oSettings);
3260 2 mingarao
                        var bReOrder = (typeof json.sColumns != 'undefined' && sOrdering !== "" && json.sColumns != sOrdering );
3261 2 mingarao
                        if ( bReOrder )
3262 2 mingarao
                        {
3263 2 mingarao
                                var aiIndex = _fnReOrderIndex( oSettings, json.sColumns );
3264 2 mingarao
                        }
3265 2 mingarao
3266 2 mingarao
                        for ( var i=0, iLen=json.aaData.length ; i<iLen ; i++ )
3267 2 mingarao
                        {
3268 2 mingarao
                                if ( bReOrder )
3269 2 mingarao
                                {
3270 2 mingarao
                                        /* If we need to re-order, then create a new array with the correct order and add it */
3271 2 mingarao
                                        var aData = [];
3272 2 mingarao
                                        for ( var j=0, jLen=oSettings.aoColumns.length ; j<jLen ; j++ )
3273 2 mingarao
                                        {
3274 2 mingarao
                                                aData.push( json.aaData[i][ aiIndex[j] ] );
3275 2 mingarao
                                        }
3276 2 mingarao
                                        _fnAddData( oSettings, aData );
3277 2 mingarao
                                }
3278 2 mingarao
                                else
3279 2 mingarao
                                {
3280 2 mingarao
                                        /* No re-order required, sever got it "right" - just straight add */
3281 2 mingarao
                                        _fnAddData( oSettings, json.aaData[i] );
3282 2 mingarao
                                }
3283 2 mingarao
                        }
3284 2 mingarao
                        oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
3285 2 mingarao
3286 2 mingarao
                        oSettings.bAjaxDataGet = false;
3287 2 mingarao
                        _fnDraw( oSettings );
3288 2 mingarao
                        oSettings.bAjaxDataGet = true;
3289 2 mingarao
                        _fnProcessingDisplay( oSettings, false );
3290 2 mingarao
                }
3291 2 mingarao
3292 2 mingarao
3293 2 mingarao
                /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3294 2 mingarao
                 * Section - Options (features) HTML
3295 2 mingarao
                 */
3296 2 mingarao
3297 2 mingarao
                /*
3298 2 mingarao
                 * Function: _fnAddOptionsHtml
3299 2 mingarao
                 * Purpose:  Add the options to the page HTML for the table
3300 2 mingarao
                 * Returns:  -
3301 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
3302 2 mingarao
                 */
3303 2 mingarao
                function _fnAddOptionsHtml ( oSettings )
3304 2 mingarao
                {
3305 2 mingarao
                        /*
3306 2 mingarao
                         * Create a temporary, empty, div which we can later on replace with what we have generated
3307 2 mingarao
                         * we do it this way to rendering the 'options' html offline - speed :-)
3308 2 mingarao
                         */
3309 2 mingarao
                        var nHolding = document.createElement( 'div' );
3310 2 mingarao
                        oSettings.nTable.parentNode.insertBefore( nHolding, oSettings.nTable );
3311 2 mingarao
3312 2 mingarao
                        /*
3313 2 mingarao
                         * All DataTables are wrapped in a div - this is not currently optional - backwards
3314 2 mingarao
                         * compatability. It can be removed if you don't want it.
3315 2 mingarao
                         */
3316 2 mingarao
                        oSettings.nTableWrapper = document.createElement( 'div' );
3317 2 mingarao
                        oSettings.nTableWrapper.className = oSettings.oClasses.sWrapper;
3318 2 mingarao
                        if ( oSettings.sTableId !== '' )
3319 2 mingarao
                        {
3320 2 mingarao
                                oSettings.nTableWrapper.setAttribute( 'id', oSettings.sTableId+'_wrapper' );
3321 2 mingarao
                        }
3322 2 mingarao
3323 2 mingarao
                        /* Track where we want to insert the option */
3324 2 mingarao
                        var nInsertNode = oSettings.nTableWrapper;
3325 2 mingarao
3326 2 mingarao
                        /* Loop over the user set positioning and place the elements as needed */
3327 2 mingarao
                        var aDom = oSettings.sDom.split('');
3328 2 mingarao
                        var nTmp, iPushFeature, cOption, nNewNode, cNext, sAttr, j;
3329 2 mingarao
                        for ( var i=0 ; i<aDom.length ; i++ )
3330 2 mingarao
                        {
3331 2 mingarao
                                iPushFeature = 0;
3332 2 mingarao
                                cOption = aDom[i];
3333 2 mingarao
3334 2 mingarao
                                if ( cOption == '<' )
3335 2 mingarao
                                {
3336 2 mingarao
                                        /* New container div */
3337 2 mingarao
                                        nNewNode = document.createElement( 'div' );
3338 2 mingarao
3339 2 mingarao
                                        /* Check to see if we should append an id and/or a class name to the container */
3340 2 mingarao
                                        cNext = aDom[i+1];
3341 2 mingarao
                                        if ( cNext == "'" || cNext == '"' )
3342 2 mingarao
                                        {
3343 2 mingarao
                                                sAttr = "";
3344 2 mingarao
                                                j = 2;
3345 2 mingarao
                                                while ( aDom[i+j] != cNext )
3346 2 mingarao
                                                {
3347 2 mingarao
                                                        sAttr += aDom[i+j];
3348 2 mingarao
                                                        j++;
3349 2 mingarao
                                                }
3350 2 mingarao
3351 2 mingarao
                                                /* Replace jQuery UI constants */
3352 2 mingarao
                                                if ( sAttr == "H" )
3353 2 mingarao
                                                {
3354 2 mingarao
                                                        sAttr = "fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix";
3355 2 mingarao
                                                }
3356 2 mingarao
                                                else if ( sAttr == "F" )
3357 2 mingarao
                                                {
3358 2 mingarao
                                                        sAttr = "fg-toolbar ui-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix";
3359 2 mingarao
                                                }
3360 2 mingarao
3361 2 mingarao
                                                /* The attribute can be in the format of "#id.class", "#id" or "class" This logic
3362 2 mingarao
                                                 * breaks the string into parts and applies them as needed
3363 2 mingarao
                                                 */
3364 2 mingarao
                                                if ( sAttr.indexOf('.') != -1 )
3365 2 mingarao
                                                {
3366 2 mingarao
                                                        var aSplit = sAttr.split('.');
3367 2 mingarao
                                                        nNewNode.setAttribute('id', aSplit[0].substr(1, aSplit[0].length-1) );
3368 2 mingarao
                                                        nNewNode.className = aSplit[1];
3369 2 mingarao
                                                }
3370 2 mingarao
                                                else if ( sAttr.charAt(0) == "#" )
3371 2 mingarao
                                                {
3372 2 mingarao
                                                        nNewNode.setAttribute('id', sAttr.substr(1, sAttr.length-1) );
3373 2 mingarao
                                                }
3374 2 mingarao
                                                else
3375 2 mingarao
                                                {
3376 2 mingarao
                                                        nNewNode.className = sAttr;
3377 2 mingarao
                                                }
3378 2 mingarao
3379 2 mingarao
                                                i += j; /* Move along the position array */
3380 2 mingarao
                                        }
3381 2 mingarao
3382 2 mingarao
                                        nInsertNode.appendChild( nNewNode );
3383 2 mingarao
                                        nInsertNode = nNewNode;
3384 2 mingarao
                                }
3385 2 mingarao
                                else if ( cOption == '>' )
3386 2 mingarao
                                {
3387 2 mingarao
                                        /* End container div */
3388 2 mingarao
                                        nInsertNode = nInsertNode.parentNode;
3389 2 mingarao
                                }
3390 2 mingarao
                                else if ( cOption == 'l' && oSettings.oFeatures.bPaginate && oSettings.oFeatures.bLengthChange )
3391 2 mingarao
                                {
3392 2 mingarao
                                        /* Length */
3393 2 mingarao
                                        nTmp = _fnFeatureHtmlLength( oSettings );
3394 2 mingarao
                                        iPushFeature = 1;
3395 2 mingarao
                                }
3396 2 mingarao
                                else if ( cOption == 'f' && oSettings.oFeatures.bFilter )
3397 2 mingarao
                                {
3398 2 mingarao
                                        /* Filter */
3399 2 mingarao
                                        nTmp = _fnFeatureHtmlFilter( oSettings );
3400 2 mingarao
                                        iPushFeature = 1;
3401 2 mingarao
                                }
3402 2 mingarao
                                else if ( cOption == 'r' && oSettings.oFeatures.bProcessing )
3403 2 mingarao
                                {
3404 2 mingarao
                                        /* pRocessing */
3405 2 mingarao
                                        nTmp = _fnFeatureHtmlProcessing( oSettings );
3406 2 mingarao
                                        iPushFeature = 1;
3407 2 mingarao
                                }
3408 2 mingarao
                                else if ( cOption == 't' )
3409 2 mingarao
                                {
3410 2 mingarao
                                        /* Table */
3411 2 mingarao
                                        nTmp = _fnFeatureHtmlTable( oSettings );
3412 2 mingarao
                                        iPushFeature = 1;
3413 2 mingarao
                                }
3414 2 mingarao
                                else if ( cOption ==  'i' && oSettings.oFeatures.bInfo )
3415 2 mingarao
                                {
3416 2 mingarao
                                        /* Info */
3417 2 mingarao
                                        nTmp = _fnFeatureHtmlInfo( oSettings );
3418 2 mingarao
                                        iPushFeature = 1;
3419 2 mingarao
                                }
3420 2 mingarao
                                else if ( cOption == 'p' && oSettings.oFeatures.bPaginate )
3421 2 mingarao
                                {
3422 2 mingarao
                                        /* Pagination */
3423 2 mingarao
                                        nTmp = _fnFeatureHtmlPaginate( oSettings );
3424 2 mingarao
                                        iPushFeature = 1;
3425 2 mingarao
                                }
3426 2 mingarao
                                else if ( _oExt.aoFeatures.length !== 0 )
3427 2 mingarao
                                {
3428 2 mingarao
                                        /* Plug-in features */
3429 2 mingarao
                                        var aoFeatures = _oExt.aoFeatures;
3430 2 mingarao
                                        for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
3431 2 mingarao
                                        {
3432 2 mingarao
                                                if ( cOption == aoFeatures[k].cFeature )
3433 2 mingarao
                                                {
3434 2 mingarao
                                                        nTmp = aoFeatures[k].fnInit( oSettings );
3435 2 mingarao
                                                        if ( nTmp )
3436 2 mingarao
                                                        {
3437 2 mingarao
                                                                iPushFeature = 1;
3438 2 mingarao
                                                        }
3439 2 mingarao
                                                        break;
3440 2 mingarao
                                                }
3441 2 mingarao
                                        }
3442 2 mingarao
                                }
3443 2 mingarao
3444 2 mingarao
                                /* Add to the 2D features array */
3445 2 mingarao
                                if ( iPushFeature == 1 && nTmp !== null )
3446 2 mingarao
                                {
3447 2 mingarao
                                        if ( typeof oSettings.aanFeatures[cOption] != 'object' )
3448 2 mingarao
                                        {
3449 2 mingarao
                                                oSettings.aanFeatures[cOption] = [];
3450 2 mingarao
                                        }
3451 2 mingarao
                                        oSettings.aanFeatures[cOption].push( nTmp );
3452 2 mingarao
                                        nInsertNode.appendChild( nTmp );
3453 2 mingarao
                                }
3454 2 mingarao
                        }
3455 2 mingarao
3456 2 mingarao
                        /* Built our DOM structure - replace the holding div with what we want */
3457 2 mingarao
                        nHolding.parentNode.replaceChild( oSettings.nTableWrapper, nHolding );
3458 2 mingarao
                }
3459 2 mingarao
3460 2 mingarao
3461 2 mingarao
                /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3462 2 mingarao
                 * Section - Feature: Filtering
3463 2 mingarao
                 */
3464 2 mingarao
3465 2 mingarao
                /*
3466 2 mingarao
                 * Function: _fnFeatureHtmlTable
3467 2 mingarao
                 * Purpose:  Add any control elements for the table - specifically scrolling
3468 2 mingarao
                 * Returns:  node: - Node to add to the DOM
3469 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
3470 2 mingarao
                 */
3471 2 mingarao
                function _fnFeatureHtmlTable ( oSettings )
3472 2 mingarao
                {
3473 2 mingarao
                        /* Chack if scrolling is enabled or not - if not then leave the DOM unaltered */
3474 2 mingarao
                        if ( oSettings.oScroll.sX === "" && oSettings.oScroll.sY === "" )
3475 2 mingarao
                        {
3476 2 mingarao
                                return oSettings.nTable;
3477 2 mingarao
                        }
3478 2 mingarao
3479 2 mingarao
                        /*
3480 2 mingarao
                         * The HTML structure that we want to generate in this function is:
3481 2 mingarao
                         *  div - nScroller
3482 2 mingarao
                         *    div - nScrollHead
3483 2 mingarao
                         *      div - nScrollHeadInner
3484 2 mingarao
                         *        table - nScrollHeadTable
3485 2 mingarao
                         *          thead - nThead
3486 2 mingarao
                         *    div - nScrollBody
3487 2 mingarao
                         *      table - oSettings.nTable
3488 2 mingarao
                         *        thead - nTheadSize
3489 2 mingarao
                         *        tbody - nTbody
3490 2 mingarao
                         *    div - nScrollFoot
3491 2 mingarao
                         *      div - nScrollFootInner
3492 2 mingarao
                         *        table - nScrollFootTable
3493 2 mingarao
                         *          tfoot - nTfoot
3494 2 mingarao
                         */
3495 2 mingarao
                        var
3496 2 mingarao
                                 nScroller = document.createElement('div'),
3497 2 mingarao
                                 nScrollHead = document.createElement('div'),
3498 2 mingarao
                                 nScrollHeadInner = document.createElement('div'),
3499 2 mingarao
                                 nScrollBody = document.createElement('div'),
3500 2 mingarao
                                 nScrollFoot = document.createElement('div'),
3501 2 mingarao
                                 nScrollFootInner = document.createElement('div'),
3502 2 mingarao
                                 nScrollHeadTable = oSettings.nTable.cloneNode(false),
3503 2 mingarao
                                 nScrollFootTable = oSettings.nTable.cloneNode(false),
3504 2 mingarao
                                nThead = oSettings.nTable.getElementsByTagName('thead')[0],
3505 2 mingarao
                                 nTfoot = oSettings.nTable.getElementsByTagName('tfoot').length === 0 ? null :
3506 2 mingarao
                                        oSettings.nTable.getElementsByTagName('tfoot')[0],
3507 2 mingarao
                                oClasses = (typeof oInit.bJQueryUI != 'undefined' && oInit.bJQueryUI) ?
3508 2 mingarao
                                         _oExt.oJUIClasses : _oExt.oStdClasses;
3509 2 mingarao
3510 2 mingarao
                        nScrollHead.appendChild( nScrollHeadInner );
3511 2 mingarao
                        nScrollFoot.appendChild( nScrollFootInner );
3512 2 mingarao
                        nScrollBody.appendChild( oSettings.nTable );
3513 2 mingarao
                        nScroller.appendChild( nScrollHead );
3514 2 mingarao
                        nScroller.appendChild( nScrollBody );
3515 2 mingarao
                        nScrollHeadInner.appendChild( nScrollHeadTable );
3516 2 mingarao
                        nScrollHeadTable.appendChild( nThead );
3517 2 mingarao
                        if ( nTfoot !== null )
3518 2 mingarao
                        {
3519 2 mingarao
                                nScroller.appendChild( nScrollFoot );
3520 2 mingarao
                                nScrollFootInner.appendChild( nScrollFootTable );
3521 2 mingarao
                                nScrollFootTable.appendChild( nTfoot );
3522 2 mingarao
                        }
3523 2 mingarao
3524 2 mingarao
                        nScroller.className = oClasses.sScrollWrapper;
3525 2 mingarao
                        nScrollHead.className = oClasses.sScrollHead;
3526 2 mingarao
                        nScrollHeadInner.className = oClasses.sScrollHeadInner;
3527 2 mingarao
                        nScrollBody.className = oClasses.sScrollBody;
3528 2 mingarao
                        nScrollFoot.className = oClasses.sScrollFoot;
3529 2 mingarao
                        nScrollFootInner.className = oClasses.sScrollFootInner;
3530 2 mingarao
3531 2 mingarao
                        nScrollHead.style.overflow = "hidden";
3532 2 mingarao
                        nScrollHead.style.position = "relative";
3533 2 mingarao
                        nScrollFoot.style.overflow = "hidden";
3534 2 mingarao
                        nScrollBody.style.overflow = "auto";
3535 2 mingarao
                        nScrollHead.style.border = "0";
3536 2 mingarao
                        nScrollFoot.style.border = "0";
3537 2 mingarao
                        nScrollHeadInner.style.width = "150%"; /* will be overwritten */
3538 2 mingarao
3539 2 mingarao
                        /* Modify attributes to respect the clones */
3540 2 mingarao
                        nScrollHeadTable.removeAttribute('id');
3541 2 mingarao
                        nScrollHeadTable.style.marginLeft = "0";
3542 2 mingarao
                        oSettings.nTable.style.marginLeft = "0";
3543 2 mingarao
                        if ( nTfoot !== null )
3544 2 mingarao
                        {
3545 2 mingarao
                                nScrollFootTable.removeAttribute('id');
3546 2 mingarao
                                nScrollFootTable.style.marginLeft = "0";
3547 2 mingarao
                        }
3548 2 mingarao
3549 2 mingarao
                        /* Move any caption elements from the body to the header */
3550 2 mingarao
                        var nCaptions = $('>caption', oSettings.nTable);
3551 2 mingarao
                        for ( var i=0, iLen=nCaptions.length ; i<iLen ; i++ )
3552 2 mingarao
                        {
3553 2 mingarao
                                nScrollHeadTable.appendChild( nCaptions[i] );
3554 2 mingarao
                        }
3555 2 mingarao
3556 2 mingarao
                        /*
3557 2 mingarao
                         * Sizing
3558 2 mingarao
                         */
3559 2 mingarao
                        /* When xscrolling add the width and a scroller to move the header with the body */
3560 2 mingarao
                        if ( oSettings.oScroll.sX !== "" )
3561 2 mingarao
                        {
3562 2 mingarao
                                nScrollHead.style.width = _fnStringToCss( oSettings.oScroll.sX );
3563 2 mingarao
                                nScrollBody.style.width = _fnStringToCss( oSettings.oScroll.sX );
3564 2 mingarao
3565 2 mingarao
                                if ( nTfoot !== null )
3566 2 mingarao
                                {
3567 2 mingarao
                                        nScrollFoot.style.width = _fnStringToCss( oSettings.oScroll.sX );
3568 2 mingarao
                                }
3569 2 mingarao
3570 2 mingarao
                                /* When the body is scrolled, then we also want to scroll the headers */
3571 2 mingarao
                                $(nScrollBody).scroll( function (e) {
3572 2 mingarao
                                        nScrollHead.scrollLeft = this.scrollLeft;
3573 2 mingarao
3574 2 mingarao
                                        if ( nTfoot !== null )
3575 2 mingarao
                                        {
3576 2 mingarao
                                                nScrollFoot.scrollLeft = this.scrollLeft;
3577 2 mingarao
                                        }
3578 2 mingarao
                                } );
3579 2 mingarao
                        }
3580 2 mingarao
3581 2 mingarao
                        /* When yscrolling, add the height */
3582 2 mingarao
                        if ( oSettings.oScroll.sY !== "" )
3583 2 mingarao
                        {
3584 2 mingarao
                                nScrollBody.style.height = _fnStringToCss( oSettings.oScroll.sY );
3585 2 mingarao
                        }
3586 2 mingarao
3587 2 mingarao
                        /* Redraw - align columns across the tables */
3588 2 mingarao
                        oSettings.aoDrawCallback.push( {
3589 2 mingarao
                                "fn": _fnScrollDraw,
3590 2 mingarao
                                "sName": "scrolling"
3591 2 mingarao
                        } );
3592 2 mingarao
3593 2 mingarao
                        /* Infinite scrolling event handlers */
3594 2 mingarao
                        if ( oSettings.oScroll.bInfinite )
3595 2 mingarao
                        {
3596 2 mingarao
                                $(nScrollBody).scroll( function() {
3597 2 mingarao
                                        /* Use a blocker to stop scrolling from loading more data while other data is still loading */
3598 2 mingarao
                                        if ( !oSettings.bDrawing )
3599 2 mingarao
                                        {
3600 2 mingarao
                                                /* Check if we should load the next data set */
3601 2 mingarao
                                                if ( $(this).scrollTop() + $(this).height() >
3602 2 mingarao
                                                        $(oSettings.nTable).height() - oSettings.oScroll.iLoadGap )
3603 2 mingarao
                                                {
3604 2 mingarao
                                                        /* Only do the redraw if we have to - we might be at the end of the data */
3605 2 mingarao
                                                        if ( oSettings.fnDisplayEnd() < oSettings.fnRecordsDisplay() )
3606 2 mingarao
                                                        {
3607 2 mingarao
                                                                _fnPageChange( oSettings, 'next' );
3608 2 mingarao
                                                                _fnCalculateEnd( oSettings );
3609 2 mingarao
                                                                _fnDraw( oSettings );
3610 2 mingarao
                                                        }
3611 2 mingarao
                                                }
3612 2 mingarao
                                        }
3613 2 mingarao
                                } );
3614 2 mingarao
                        }
3615 2 mingarao
3616 2 mingarao
                        oSettings.nScrollHead = nScrollHead;
3617 2 mingarao
                        oSettings.nScrollFoot = nScrollFoot;
3618 2 mingarao
3619 2 mingarao
                        return nScroller;
3620 2 mingarao
                }
3621 2 mingarao
3622 2 mingarao
                /*
3623 2 mingarao
                 * Function: _fnScrollDraw
3624 2 mingarao
                 * Purpose:  Update the various tables for resizing
3625 2 mingarao
                 * Returns:  node: - Node to add to the DOM
3626 2 mingarao
                 * Inputs:   object:o - dataTables settings object
3627 2 mingarao
                 * Notes:    It's a bit of a pig this function, but basically the idea to:
3628 2 mingarao
                 *   1. Re-create the table inside the scrolling div
3629 2 mingarao
                 *   2. Take live measurements from the DOM
3630 2 mingarao
                 *   3. Apply the measurements
3631 2 mingarao
                 *   4. Clean up
3632 2 mingarao
                 */
3633 2 mingarao
                function _fnScrollDraw ( o )
3634 2 mingarao
                {
3635 2 mingarao
                        var
3636 2 mingarao
                                nScrollHeadInner = o.nScrollHead.getElementsByTagName('div')[0],
3637 2 mingarao
                                nScrollHeadTable = nScrollHeadInner.getElementsByTagName('table')[0],
3638 2 mingarao
                                nScrollBody = o.nTable.parentNode,
3639 2 mingarao
                                i, iLen, j, jLen, anHeadToSize, anHeadSizers, anFootSizers, anFootToSize, oStyle, iVis,
3640 2 mingarao
                                iWidth, aApplied=[], iSanityWidth;
3641 2 mingarao
3642 2 mingarao
                        /*
3643 2 mingarao
                         * 1. Re-create the table inside the scrolling div
3644 2 mingarao
                         */
3645 2 mingarao
3646 2 mingarao
                        /* Remove the old minimised thead and tfoot elements in the inner table */
3647 2 mingarao
                        var nTheadSize = o.nTable.getElementsByTagName('thead');
3648 2 mingarao
                        if ( nTheadSize.length > 0 )
3649 2 mingarao
                        {
3650 2 mingarao
                                o.nTable.removeChild( nTheadSize[0] );
3651 2 mingarao
                        }
3652 2 mingarao
3653 2 mingarao
                        if ( o.nTFoot !== null )
3654 2 mingarao
                        {
3655 2 mingarao
                                /* Remove the old minimised footer element in the cloned header */
3656 2 mingarao
                                var nTfootSize = o.nTable.getElementsByTagName('tfoot');
3657 2 mingarao
                                if ( nTfootSize.length > 0 )
3658 2 mingarao
                                {
3659 2 mingarao
                                        o.nTable.removeChild( nTfootSize[0] );
3660 2 mingarao
                                }
3661 2 mingarao
                        }
3662 2 mingarao
3663 2 mingarao
                        /* Clone the current header and footer elements and then place it into the inner table */
3664 2 mingarao
                        nTheadSize = o.nTHead.cloneNode(true);
3665 2 mingarao
                        o.nTable.insertBefore( nTheadSize, o.nTable.childNodes[0] );
3666 2 mingarao
3667 2 mingarao
                        if ( o.nTFoot !== null )
3668 2 mingarao
                        {
3669 2 mingarao
                                nTfootSize = o.nTFoot.cloneNode(true);
3670 2 mingarao
                                o.nTable.insertBefore( nTfootSize, o.nTable.childNodes[1] );
3671 2 mingarao
                        }
3672 2 mingarao
3673 2 mingarao
                        /*
3674 2 mingarao
                         * 2. Take live measurements from the DOM - do not alter the DOM itself!
3675 2 mingarao
                         */
3676 2 mingarao
3677 2 mingarao
                        /* Remove old sizing and apply the calculated column widths
3678 2 mingarao
                         * Get the unique column headers in the newly created (cloned) header. We want to apply the
3679 2 mingarao
                         * calclated sizes to this header
3680 2 mingarao
                         */
3681 2 mingarao
                        var nThs = _fnGetUniqueThs( nTheadSize );
3682 2 mingarao
                        for ( i=0, iLen=nThs.length ; i<iLen ; i++ )
3683 2 mingarao
                        {
3684 2 mingarao
                                iVis = _fnVisibleToColumnIndex( o, i );
3685 2 mingarao
                                nThs[i].style.width = o.aoColumns[iVis].sWidth;
3686 2 mingarao
                        }
3687 2 mingarao
3688 2 mingarao
                        if ( o.nTFoot !== null )
3689 2 mingarao
                        {
3690 2 mingarao
                                _fnApplyToChildren( function(n) {
3691 2 mingarao
                                        n.style.width = "";
3692 2 mingarao
                                }, nTfootSize.getElementsByTagName('tr') );
3693 2 mingarao
                        }
3694 2 mingarao
3695 2 mingarao
                        /* Size the table as a whole */
3696 2 mingarao
                        iSanityWidth = $(o.nTable).outerWidth();
3697 2 mingarao
                        if ( o.oScroll.sX === "" )
3698 2 mingarao
                        {
3699 2 mingarao
                                /* No x scrolling */
3700 2 mingarao
                                o.nTable.style.width = "100%";
3701 2 mingarao
3702 2 mingarao
                                /* I know this is rubbish - but IE7 will make the width of the table when 100% include
3703 2 mingarao
                                 * the scrollbar - which is shouldn't. This needs feature detection in future - to do
3704 2 mingarao
                                 */
3705 2 mingarao
                                if ( $.browser.msie && $.browser.version <= 7 )
3706 2 mingarao
                                {
3707 2 mingarao
                                        o.nTable.style.width = _fnStringToCss( $(o.nTable).outerWidth()-o.oScroll.iBarWidth );
3708 2 mingarao
                                }
3709 2 mingarao
                        }
3710 2 mingarao
                        else
3711 2 mingarao
                        {
3712 2 mingarao
                                if ( o.oScroll.sXInner !== "" )
3713 2 mingarao
                                {
3714 2 mingarao
                                        /* x scroll inner has been given - use it */
3715 2 mingarao
                                        o.nTable.style.width = _fnStringToCss(o.oScroll.sXInner);
3716 2 mingarao
                                }
3717 2 mingarao
                                else if ( iSanityWidth == $(nScrollBody).width() &&
3718 2 mingarao
                                   $(nScrollBody).height() < $(o.nTable).height() )
3719 2 mingarao
                                {
3720 2 mingarao
                                        /* There is y-scrolling - try to take account of the y scroll bar */
3721 2 mingarao
                                        o.nTable.style.width = _fnStringToCss( iSanityWidth-o.oScroll.iBarWidth );
3722 2 mingarao
                                        if ( $(o.nTable).outerWidth() > iSanityWidth-o.oScroll.iBarWidth )
3723 2 mingarao
                                        {
3724 2 mingarao
                                                /* Not possible to take account of it */
3725 2 mingarao
                                                o.nTable.style.width = _fnStringToCss( iSanityWidth );
3726 2 mingarao
                                        }
3727 2 mingarao
                                }
3728 2 mingarao
                                else
3729 2 mingarao
                                {
3730 2 mingarao
                                        /* All else fails */
3731 2 mingarao
                                        o.nTable.style.width = _fnStringToCss( iSanityWidth );
3732 2 mingarao
                                }
3733 2 mingarao
                        }
3734 2 mingarao
3735 2 mingarao
                        /* Recalculate the sanity width - now that we've applied the required width, before it was
3736 2 mingarao
                         * a temporary variable. This is required because the column width calculation is done
3737 2 mingarao
                         * before this table DOM is created.
3738 2 mingarao
                         */
3739 2 mingarao
                        iSanityWidth = $(o.nTable).outerWidth();
3740 2 mingarao
3741 2 mingarao
                        /* We want the hidden header to have zero height, so remove padding and borders. Then
3742 2 mingarao
                         * set the width based on the real headers
3743 2 mingarao
                         */
3744 2 mingarao
                        anHeadToSize = o.nTHead.getElementsByTagName('tr');
3745 2 mingarao
                        anHeadSizers = nTheadSize.getElementsByTagName('tr');
3746 2 mingarao
3747 2 mingarao
                        _fnApplyToChildren( function(nSizer, nToSize) {
3748 2 mingarao
                                oStyle = nSizer.style;
3749 2 mingarao
                                oStyle.paddingTop = "0";
3750 2 mingarao
                                oStyle.paddingBottom = "0";
3751 2 mingarao
                                oStyle.borderTopWidth = "0";
3752 2 mingarao
                                oStyle.borderBottomWidth = "0";
3753 2 mingarao
                                oStyle.height = 0;
3754 2 mingarao
3755 2 mingarao
                                iWidth = $(nSizer).width();
3756 2 mingarao
                                nToSize.style.width = _fnStringToCss( iWidth );
3757 2 mingarao
                                aApplied.push( iWidth );
3758 2 mingarao
                        }, anHeadSizers, anHeadToSize );
3759 2 mingarao
                        $(anHeadSizers).height(0);
3760 2 mingarao
3761 2 mingarao
                        if ( o.nTFoot !== null )
3762 2 mingarao
                        {
3763 2 mingarao
                                /* Clone the current footer and then place it into the body table as a "hidden header" */
3764 2 mingarao
                                anFootSizers = nTfootSize.getElementsByTagName('tr');
3765 2 mingarao
                                anFootToSize = o.nTFoot.getElementsByTagName('tr');
3766 2 mingarao
3767 2 mingarao
                                _fnApplyToChildren( function(nSizer, nToSize) {
3768 2 mingarao
                                        oStyle = nSizer.style;
3769 2 mingarao
                                        oStyle.paddingTop = "0";
3770 2 mingarao
                                        oStyle.paddingBottom = "0";
3771 2 mingarao
                                        oStyle.borderTopWidth = "0";
3772 2 mingarao
                                        oStyle.borderBottomWidth = "0";
3773 2 mingarao
3774 2 mingarao
                                        iWidth = $(nSizer).width();
3775 2 mingarao
                                        nToSize.style.width = _fnStringToCss( iWidth );
3776 2 mingarao
                                        aApplied.push( iWidth );
3777 2 mingarao
                                }, anFootSizers, anFootToSize );
3778 2 mingarao
                                $(anFootSizers).height(0);
3779 2 mingarao
                        }
3780 2 mingarao
3781 2 mingarao
                        /*
3782 2 mingarao
                         * 3. Apply the measurements
3783 2 mingarao
                         */
3784 2 mingarao
3785 2 mingarao
                        /* "Hide" the header and footer that we used for the sizing. We want to also fix their width
3786 2 mingarao
                         * to what they currently are
3787 2 mingarao
                         */
3788 2 mingarao
                        _fnApplyToChildren( function(nSizer) {
3789 2 mingarao
                                nSizer.innerHTML = "";
3790 2 mingarao
                                nSizer.style.width = _fnStringToCss( aApplied.shift() );
3791 2 mingarao
                        }, anHeadSizers );
3792 2 mingarao
3793 2 mingarao
                        if ( o.nTFoot !== null )
3794 2 mingarao
                        {
3795 2 mingarao
                                _fnApplyToChildren( function(nSizer) {
3796 2 mingarao
                                        nSizer.innerHTML = "";
3797 2 mingarao
                                        nSizer.style.width = _fnStringToCss( aApplied.shift() );
3798 2 mingarao
                                }, anFootSizers );
3799 2 mingarao
                        }
3800 2 mingarao
3801 2 mingarao
                        /* Sanity check that the table is of a sensible width. If not then we are going to get
3802 2 mingarao
                         * misalignment
3803 2 mingarao
                         */
3804 2 mingarao
                        if ( $(o.nTable).outerWidth() < iSanityWidth )
3805 2 mingarao
                        {
3806 2 mingarao
                                if ( o.oScroll.sX === "" )
3807 2 mingarao
                                {
3808 2 mingarao
                                        _fnLog( o, 1, "The table cannot fit into the current element which will cause column"+
3809 2 mingarao
                                                " misalignment. It is suggested that you enable x-scrolling or increase the width"+
3810 2 mingarao
                                                " the table has in which to be drawn" );
3811 2 mingarao
                                }
3812 2 mingarao
                                else if ( o.oScroll.sXInner !== "" )
3813 2 mingarao
                                {
3814 2 mingarao
                                        _fnLog( o, 1, "The table cannot fit into the current element which will cause column"+
3815 2 mingarao
                                                " misalignment. It is suggested that you increase the sScrollXInner property to"+
3816 2 mingarao
                                                " allow it to draw in a larger area, or simply remove that parameter to allow"+
3817 2 mingarao
                                                " automatic calculation" );
3818 2 mingarao
                                }
3819 2 mingarao
                        }
3820 2 mingarao
3821 2 mingarao
3822 2 mingarao
                        /*
3823 2 mingarao
                         * 4. Clean up
3824 2 mingarao
                         */
3825 2 mingarao
3826 2 mingarao
                        if ( o.oScroll.sY === "" )
3827 2 mingarao
                        {
3828 2 mingarao
                                /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
3829 2 mingarao
                                 * the scrollbar height from the visible display, rather than adding it on. We need to
3830 2 mingarao
                                 * set the height in order to sort this. Don't want to do it in any other browsers.
3831 2 mingarao
                                 */
3832 2 mingarao
                                if ( $.browser.msie && $.browser.version <= 7 )
3833 2 mingarao
                                {
3834 2 mingarao
                                        nScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+o.oScroll.iBarWidth );
3835 2 mingarao
                                }
3836 2 mingarao
                        }
3837 2 mingarao
3838 2 mingarao
                        if ( o.oScroll.sY !== "" && o.oScroll.bCollapse )
3839 2 mingarao
                        {
3840 2 mingarao
                                nScrollBody.style.height = _fnStringToCss( o.oScroll.sY );
3841 2 mingarao
3842 2 mingarao
                                var iExtra = (o.oScroll.sX !== "" && o.nTable.offsetWidth > nScrollBody.offsetWidth) ?
3843 2 mingarao
                                         o.oScroll.iBarWidth : 0;
3844 2 mingarao
                                if ( o.nTable.offsetHeight < nScrollBody.offsetHeight )
3845 2 mingarao
                                {
3846 2 mingarao
                                        nScrollBody.style.height = _fnStringToCss( $(o.nTable).height()+iExtra );
3847 2 mingarao
                                }
3848 2 mingarao
                        }
3849 2 mingarao
3850 2 mingarao
                        /* Finally set the width's of the header and footer tables */
3851 2 mingarao
                        var iOuterWidth = $(o.nTable).outerWidth();
3852 2 mingarao
                        nScrollHeadTable.style.width = _fnStringToCss( iOuterWidth );
3853 2 mingarao
                        nScrollHeadInner.style.width = _fnStringToCss( iOuterWidth+o.oScroll.iBarWidth );
3854 2 mingarao
                        nScrollHeadInner.parentNode.style.width = _fnStringToCss( $(nScrollBody).width() );
3855 2 mingarao
3856 2 mingarao
                        if ( o.nTFoot !== null )
3857 2 mingarao
                        {
3858 2 mingarao
                                var
3859 2 mingarao
                                        nScrollFootInner = o.nScrollFoot.getElementsByTagName('div')[0],
3860 2 mingarao
                                        nScrollFootTable = nScrollFootInner.getElementsByTagName('table')[0];
3861 2 mingarao
3862 2 mingarao
                                nScrollFootInner.style.width = _fnStringToCss( o.nTable.offsetWidth+o.oScroll.iBarWidth );
3863 2 mingarao
                                nScrollFootTable.style.width = _fnStringToCss( o.nTable.offsetWidth );
3864 2 mingarao
                        }
3865 2 mingarao
3866 2 mingarao
                        /* If sorting or filtering has occured, jump the scrolling back to the top */
3867 2 mingarao
                        if ( o.bSorted || o.bFiltered )
3868 2 mingarao
                        {
3869 2 mingarao
                                nScrollBody.scrollTop = 0;
3870 2 mingarao
                        }
3871 2 mingarao
                }
3872 2 mingarao
3873 2 mingarao
                /*
3874 2 mingarao
                 * Function: _fnAjustColumnSizing
3875 2 mingarao
                 * Purpose:  Ajust the table column widths for new data
3876 2 mingarao
                 * Returns:  -
3877 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
3878 2 mingarao
                 * Notes:    You would probably want to do a redraw after calling this function!
3879 2 mingarao
                 */
3880 2 mingarao
                function _fnAjustColumnSizing ( oSettings )
3881 2 mingarao
                {
3882 2 mingarao
                        /* Not interested in doing column width calculation if autowidth is disabled */
3883 2 mingarao
                        if ( oSettings.oFeatures.bAutoWidth === false )
3884 2 mingarao
                        {
3885 2 mingarao
                                return false;
3886 2 mingarao
                        }
3887 2 mingarao
3888 2 mingarao
                        _fnCalculateColumnWidths( oSettings );
3889 2 mingarao
                        for ( var i=0 , iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
3890 2 mingarao
                        {
3891 2 mingarao
                                oSettings.aoColumns[i].nTh.style.width = oSettings.aoColumns[i].sWidth;
3892 2 mingarao
                        }
3893 2 mingarao
                }
3894 2 mingarao
3895 2 mingarao
3896 2 mingarao
                /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3897 2 mingarao
                 * Section - Feature: Filtering
3898 2 mingarao
                 */
3899 2 mingarao
3900 2 mingarao
                /*
3901 2 mingarao
                 * Function: _fnFeatureHtmlFilter
3902 2 mingarao
                 * Purpose:  Generate the node required for filtering text
3903 2 mingarao
                 * Returns:  node
3904 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
3905 2 mingarao
                 */
3906 2 mingarao
                function _fnFeatureHtmlFilter ( oSettings )
3907 2 mingarao
                {
3908 2 mingarao
                        var nFilter = document.createElement( 'div' );
3909 2 mingarao
                        if ( oSettings.sTableId !== '' && typeof oSettings.aanFeatures.f == "undefined" )
3910 2 mingarao
                        {
3911 2 mingarao
                                nFilter.setAttribute( 'id', oSettings.sTableId+'_filter' );
3912 2 mingarao
                        }
3913 2 mingarao
                        nFilter.className = oSettings.oClasses.sFilter;
3914 2 mingarao
                        var sSpace = oSettings.oLanguage.sSearch==="" ? "" : " ";
3915 2 mingarao
                        nFilter.innerHTML = oSettings.oLanguage.sSearch+sSpace+'<input type="text" />';
3916 2 mingarao
3917 2 mingarao
                        var jqFilter = $("input", nFilter);
3918 2 mingarao
                        jqFilter.val( oSettings.oPreviousSearch.sSearch.replace('"','&quot;') );
3919 2 mingarao
                        jqFilter.keyup( function(e) {
3920 2 mingarao
                                /* Update all other filter input elements for the new display */
3921 2 mingarao
                                var n = oSettings.aanFeatures.f;
3922 2 mingarao
                                for ( var i=0, iLen=n.length ; i<iLen ; i++ )
3923 2 mingarao
                                {
3924 2 mingarao
                                        if ( n[i] != this.parentNode )
3925 2 mingarao
                                        {
3926 2 mingarao
                                                $('input', n[i]).val( this.value );
3927 2 mingarao
                                        }
3928 2 mingarao
                                }
3929 2 mingarao
3930 2 mingarao
                                /* Now do the filter */
3931 2 mingarao
                                if ( this.value != oSettings.oPreviousSearch.sSearch )
3932 2 mingarao
                                {
3933 2 mingarao
                                        _fnFilterComplete( oSettings, {
3934 2 mingarao
                                                "sSearch": this.value,
3935 2 mingarao
                                                "bRegex":  oSettings.oPreviousSearch.bRegex,
3936 2 mingarao
                                                "bSmart":  oSettings.oPreviousSearch.bSmart
3937 2 mingarao
                                        } );
3938 2 mingarao
                                }
3939 2 mingarao
                        } );
3940 2 mingarao
3941 2 mingarao
                        jqFilter.keypress( function(e) {
3942 2 mingarao
                                /* Prevent default */
3943 2 mingarao
                                if ( e.keyCode == 13 )
3944 2 mingarao
                                {
3945 2 mingarao
                                        return false;
3946 2 mingarao
                                }
3947 2 mingarao
                        } );
3948 2 mingarao
3949 2 mingarao
                        return nFilter;
3950 2 mingarao
                }
3951 2 mingarao
3952 2 mingarao
                /*
3953 2 mingarao
                 * Function: _fnFilterComplete
3954 2 mingarao
                 * Purpose:  Filter the table using both the global filter and column based filtering
3955 2 mingarao
                 * Returns:  -
3956 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
3957 2 mingarao
                 *           object:oSearch: search information
3958 2 mingarao
                 *           int:iForce - optional - force a research of the master array (1) or not (undefined or 0)
3959 2 mingarao
                 */
3960 2 mingarao
                function _fnFilterComplete ( oSettings, oInput, iForce )
3961 2 mingarao
                {
3962 2 mingarao
                        /* Filter on everything */
3963 2 mingarao
                        _fnFilter( oSettings, oInput.sSearch, iForce, oInput.bRegex, oInput.bSmart );
3964 2 mingarao
3965 2 mingarao
                        /* Now do the individual column filter */
3966 2 mingarao
                        for ( var i=0 ; i<oSettings.aoPreSearchCols.length ; i++ )
3967 2 mingarao
                        {
3968 2 mingarao
                                _fnFilterColumn( oSettings, oSettings.aoPreSearchCols[i].sSearch, i,
3969 2 mingarao
                                        oSettings.aoPreSearchCols[i].bRegex, oSettings.aoPreSearchCols[i].bSmart );
3970 2 mingarao
                        }
3971 2 mingarao
3972 2 mingarao
                        /* Custom filtering */
3973 2 mingarao
                        if ( _oExt.afnFiltering.length !== 0 )
3974 2 mingarao
                        {
3975 2 mingarao
                                _fnFilterCustom( oSettings );
3976 2 mingarao
                        }
3977 2 mingarao
3978 2 mingarao
                        /* Tell the draw function we have been filtering */
3979 2 mingarao
                        oSettings.bFiltered = true;
3980 2 mingarao
3981 2 mingarao
                        /* Redraw the table */
3982 2 mingarao
                        oSettings._iDisplayStart = 0;
3983 2 mingarao
                        _fnCalculateEnd( oSettings );
3984 2 mingarao
                        _fnDraw( oSettings );
3985 2 mingarao
3986 2 mingarao
                        /* Rebuild search array 'offline' */
3987 2 mingarao
                        _fnBuildSearchArray( oSettings, 0 );
3988 2 mingarao
                }
3989 2 mingarao
3990 2 mingarao
                /*
3991 2 mingarao
                 * Function: _fnFilterCustom
3992 2 mingarao
                 * Purpose:  Apply custom filtering functions
3993 2 mingarao
                 * Returns:  -
3994 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
3995 2 mingarao
                 */
3996 2 mingarao
                function _fnFilterCustom( oSettings )
3997 2 mingarao
                {
3998 2 mingarao
                        var afnFilters = _oExt.afnFiltering;
3999 2 mingarao
                        for ( var i=0, iLen=afnFilters.length ; i<iLen ; i++ )
4000 2 mingarao
                        {
4001 2 mingarao
                                var iCorrector = 0;
4002 2 mingarao
                                for ( var j=0, jLen=oSettings.aiDisplay.length ; j<jLen ; j++ )
4003 2 mingarao
                                {
4004 2 mingarao
                                        var iDisIndex = oSettings.aiDisplay[j-iCorrector];
4005 2 mingarao
4006 2 mingarao
                                        /* Check if we should use this row based on the filtering function */
4007 2 mingarao
                                        if ( !afnFilters[i]( oSettings, oSettings.aoData[iDisIndex]._aData, iDisIndex ) )
4008 2 mingarao
                                        {
4009 2 mingarao
                                                oSettings.aiDisplay.splice( j-iCorrector, 1 );
4010 2 mingarao
                                                iCorrector++;
4011 2 mingarao
                                        }
4012 2 mingarao
                                }
4013 2 mingarao
                        }
4014 2 mingarao
                }
4015 2 mingarao
4016 2 mingarao
                /*
4017 2 mingarao
                 * Function: _fnFilterColumn
4018 2 mingarao
                 * Purpose:  Filter the table on a per-column basis
4019 2 mingarao
                 * Returns:  -
4020 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
4021 2 mingarao
                 *           string:sInput - string to filter on
4022 2 mingarao
                 *           int:iColumn - column to filter
4023 2 mingarao
                 *           bool:bRegex - treat search string as a regular expression or not
4024 2 mingarao
                 *           bool:bSmart - use smart filtering or not
4025 2 mingarao
                 */
4026 2 mingarao
                function _fnFilterColumn ( oSettings, sInput, iColumn, bRegex, bSmart )
4027 2 mingarao
                {
4028 2 mingarao
                        if ( sInput === "" )
4029 2 mingarao
                        {
4030 2 mingarao
                                return;
4031 2 mingarao
                        }
4032 2 mingarao
4033 2 mingarao
                        var iIndexCorrector = 0;
4034 2 mingarao
                        var rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart );
4035 2 mingarao
4036 2 mingarao
                        for ( var i=oSettings.aiDisplay.length-1 ; i>=0 ; i-- )
4037 2 mingarao
                        {
4038 2 mingarao
                                var sData = _fnDataToSearch( oSettings.aoData[ oSettings.aiDisplay[i] ]._aData[iColumn],
4039 2 mingarao
                                        oSettings.aoColumns[iColumn].sType );
4040 2 mingarao
                                if ( ! rpSearch.test( sData ) )
4041 2 mingarao
                                {
4042 2 mingarao
                                        oSettings.aiDisplay.splice( i, 1 );
4043 2 mingarao
                                        iIndexCorrector++;
4044 2 mingarao
                                }
4045 2 mingarao
                        }
4046 2 mingarao
                }
4047 2 mingarao
4048 2 mingarao
                /*
4049 2 mingarao
                 * Function: _fnFilter
4050 2 mingarao
                 * Purpose:  Filter the data table based on user input and draw the table
4051 2 mingarao
                 * Returns:  -
4052 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
4053 2 mingarao
                 *           string:sInput - string to filter on
4054 2 mingarao
                 *           int:iForce - optional - force a research of the master array (1) or not (undefined or 0)
4055 2 mingarao
                 *           bool:bRegex - treat as a regular expression or not
4056 2 mingarao
                 *           bool:bSmart - perform smart filtering or not
4057 2 mingarao
                 */
4058 2 mingarao
                function _fnFilter( oSettings, sInput, iForce, bRegex, bSmart )
4059 2 mingarao
                {
4060 2 mingarao
                        var i;
4061 2 mingarao
                        var rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart );
4062 2 mingarao
4063 2 mingarao
                        /* Check if we are forcing or not - optional parameter */
4064 2 mingarao
                        if ( typeof iForce == 'undefined' || iForce === null )
4065 2 mingarao
                        {
4066 2 mingarao
                                iForce = 0;
4067 2 mingarao
                        }
4068 2 mingarao
4069 2 mingarao
                        /* Need to take account of custom filtering functions - always filter */
4070 2 mingarao
                        if ( _oExt.afnFiltering.length !== 0 )
4071 2 mingarao
                        {
4072 2 mingarao
                                iForce = 1;
4073 2 mingarao
                        }
4074 2 mingarao
4075 2 mingarao
                        /*
4076 2 mingarao
                         * If the input is blank - we want the full data set
4077 2 mingarao
                         */
4078 2 mingarao
                        if ( sInput.length <= 0 )
4079 2 mingarao
                        {
4080 2 mingarao
                                oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length);
4081 2 mingarao
                                oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
4082 2 mingarao
                        }
4083 2 mingarao
                        else
4084 2 mingarao
                        {
4085 2 mingarao
                                /*
4086 2 mingarao
                                 * We are starting a new search or the new search string is smaller
4087 2 mingarao
                                 * then the old one (i.e. delete). Search from the master array
4088 2 mingarao
                                  */
4089 2 mingarao
                                if ( oSettings.aiDisplay.length == oSettings.aiDisplayMaster.length ||
4090 2 mingarao
                                           oSettings.oPreviousSearch.sSearch.length > sInput.length || iForce == 1 ||
4091 2 mingarao
                                           sInput.indexOf(oSettings.oPreviousSearch.sSearch) !== 0 )
4092 2 mingarao
                                {
4093 2 mingarao
                                        /* Nuke the old display array - we are going to rebuild it */
4094 2 mingarao
                                        oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length);
4095 2 mingarao
4096 2 mingarao
                                        /* Force a rebuild of the search array */
4097 2 mingarao
                                        _fnBuildSearchArray( oSettings, 1 );
4098 2 mingarao
4099 2 mingarao
                                        /* Search through all records to populate the search array
4100 2 mingarao
                                         * The the oSettings.aiDisplayMaster and asDataSearch arrays have 1 to 1
4101 2 mingarao
                                         * mapping
4102 2 mingarao
                                         */
4103 2 mingarao
                                        for ( i=0 ; i<oSettings.aiDisplayMaster.length ; i++ )
4104 2 mingarao
                                        {
4105 2 mingarao
                                                if ( rpSearch.test(oSettings.asDataSearch[i]) )
4106 2 mingarao
                                                {
4107 2 mingarao
                                                        oSettings.aiDisplay.push( oSettings.aiDisplayMaster[i] );
4108 2 mingarao
                                                }
4109 2 mingarao
                                        }
4110 2 mingarao
                          }
4111 2 mingarao
                          else
4112 2 mingarao
                                {
4113 2 mingarao
                                  /* Using old search array - refine it - do it this way for speed
4114 2 mingarao
                                   * Don't have to search the whole master array again
4115 2 mingarao
                                          */
4116 2 mingarao
                                  var iIndexCorrector = 0;
4117 2 mingarao
4118 2 mingarao
                                  /* Search the current results */
4119 2 mingarao
                                  for ( i=0 ; i<oSettings.asDataSearch.length ; i++ )
4120 2 mingarao
                                        {
4121 2 mingarao
                                          if ( ! rpSearch.test(oSettings.asDataSearch[i]) )
4122 2 mingarao
                                                {
4123 2 mingarao
                                                  oSettings.aiDisplay.splice( i-iIndexCorrector, 1 );
4124 2 mingarao
                                                  iIndexCorrector++;
4125 2 mingarao
                                          }
4126 2 mingarao
                                  }
4127 2 mingarao
                          }
4128 2 mingarao
                        }
4129 2 mingarao
                        oSettings.oPreviousSearch.sSearch = sInput;
4130 2 mingarao
                        oSettings.oPreviousSearch.bRegex = bRegex;
4131 2 mingarao
                        oSettings.oPreviousSearch.bSmart = bSmart;
4132 2 mingarao
                }
4133 2 mingarao
4134 2 mingarao
                /*
4135 2 mingarao
                 * Function: _fnBuildSearchArray
4136 2 mingarao
                 * Purpose:  Create an array which can be quickly search through
4137 2 mingarao
                 * Returns:  -
4138 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
4139 2 mingarao
                 *           int:iMaster - use the master data array - optional
4140 2 mingarao
                 */
4141 2 mingarao
                function _fnBuildSearchArray ( oSettings, iMaster )
4142 2 mingarao
                {
4143 2 mingarao
                        /* Clear out the old data */
4144 2 mingarao
                        oSettings.asDataSearch.splice( 0, oSettings.asDataSearch.length );
4145 2 mingarao
4146 2 mingarao
                        var aArray = (typeof iMaster != 'undefined' && iMaster == 1) ?
4147 2 mingarao
                                 oSettings.aiDisplayMaster : oSettings.aiDisplay;
4148 2 mingarao
4149 2 mingarao
                        for ( var i=0, iLen=aArray.length ; i<iLen ; i++ )
4150 2 mingarao
                        {
4151 2 mingarao
                                oSettings.asDataSearch[i] = _fnBuildSearchRow( oSettings,
4152 2 mingarao
                                        oSettings.aoData[ aArray[i] ]._aData );
4153 2 mingarao
                        }
4154 2 mingarao
                }
4155 2 mingarao
4156 2 mingarao
                /*
4157 2 mingarao
                 * Function: _fnBuildSearchRow
4158 2 mingarao
                 * Purpose:  Create a searchable string from a single data row
4159 2 mingarao
                 * Returns:  -
4160 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
4161 2 mingarao
                 *           array:aData - aoData[]._aData array to use for the data to search
4162 2 mingarao
                 */
4163 2 mingarao
                function _fnBuildSearchRow( oSettings, aData )
4164 2 mingarao
                {
4165 2 mingarao
                        var sSearch = '';
4166 2 mingarao
                        var nTmp = document.createElement('div');
4167 2 mingarao
4168 2 mingarao
                        for ( var j=0, jLen=oSettings.aoColumns.length ; j<jLen ; j++ )
4169 2 mingarao
                        {
4170 2 mingarao
                                if ( oSettings.aoColumns[j].bSearchable )
4171 2 mingarao
                                {
4172 2 mingarao
                                        var sData = aData[j];
4173 2 mingarao
                                        sSearch += _fnDataToSearch( sData, oSettings.aoColumns[j].sType )+'  ';
4174 2 mingarao
                                }
4175 2 mingarao
                        }
4176 2 mingarao
4177 2 mingarao
                        /* If it looks like there is an HTML entity in the string, attempt to decode it */
4178 2 mingarao
                        if ( sSearch.indexOf('&') !== -1 )
4179 2 mingarao
                        {
4180 2 mingarao
                                nTmp.innerHTML = sSearch;
4181 2 mingarao
                                sSearch = nTmp.textContent ? nTmp.textContent : nTmp.innerText;
4182 2 mingarao
4183 2 mingarao
                                /* IE and Opera appear to put an newline where there is a <br> tag - remove it */
4184 2 mingarao
                                sSearch = sSearch.replace(/\n/g," ").replace(/\r/g,"");
4185 2 mingarao
                        }
4186 2 mingarao
4187 2 mingarao
                        return sSearch;
4188 2 mingarao
                }
4189 2 mingarao
4190 2 mingarao
                /*
4191 2 mingarao
                 * Function: _fnFilterCreateSearch
4192 2 mingarao
                 * Purpose:  Build a regular expression object suitable for searching a table
4193 2 mingarao
                 * Returns:  RegExp: - constructed object
4194 2 mingarao
                 * Inputs:   string:sSearch - string to search for
4195 2 mingarao
                 *           bool:bRegex - treat as a regular expression or not
4196 2 mingarao
                 *           bool:bSmart - perform smart filtering or not
4197 2 mingarao
                 */
4198 2 mingarao
                function _fnFilterCreateSearch( sSearch, bRegex, bSmart )
4199 2 mingarao
                {
4200 2 mingarao
                        var asSearch, sRegExpString;
4201 2 mingarao
4202 2 mingarao
                        if ( bSmart )
4203 2 mingarao
                        {
4204 2 mingarao
                                /* Generate the regular expression to use. Something along the lines of:
4205 2 mingarao
                                 * ^(?=.*?\bone\b)(?=.*?\btwo\b)(?=.*?\bthree\b).*$
4206 2 mingarao
                                 */
4207 2 mingarao
                                asSearch = bRegex ? sSearch.split( ' ' ) : _fnEscapeRegex( sSearch ).split( ' ' );
4208 2 mingarao
                                sRegExpString = '^(?=.*?'+asSearch.join( ')(?=.*?' )+').*$';
4209 2 mingarao
                                return new RegExp( sRegExpString, "i" );
4210 2 mingarao
                        }
4211 2 mingarao
                        else
4212 2 mingarao
                        {
4213 2 mingarao
                                sSearch = bRegex ? sSearch : _fnEscapeRegex( sSearch );
4214 2 mingarao
                                return new RegExp( sSearch, "i" );
4215 2 mingarao
                        }
4216 2 mingarao
                }
4217 2 mingarao
4218 2 mingarao
                /*
4219 2 mingarao
                 * Function: _fnDataToSearch
4220 2 mingarao
                 * Purpose:  Convert raw data into something that the user can search on
4221 2 mingarao
                 * Returns:  string: - search string
4222 2 mingarao
                 * Inputs:   string:sData - data to be modified
4223 2 mingarao
                 *           string:sType - data type
4224 2 mingarao
                 */
4225 2 mingarao
                function _fnDataToSearch ( sData, sType )
4226 2 mingarao
                {
4227 2 mingarao
                        if ( typeof _oExt.ofnSearch[sType] == "function" )
4228 2 mingarao
                        {
4229 2 mingarao
                                return _oExt.ofnSearch[sType]( sData );
4230 2 mingarao
                        }
4231 2 mingarao
                        else if ( sType == "html" )
4232 2 mingarao
                        {
4233 2 mingarao
                                return sData.replace(/\n/g," ").replace( /<.*?>/g, "" );
4234 2 mingarao
                        }
4235 2 mingarao
                        else if ( typeof sData == "string" )
4236 2 mingarao
                        {
4237 2 mingarao
                                return sData.replace(/\n/g," ");
4238 2 mingarao
                        }
4239 2 mingarao
                        return sData;
4240 2 mingarao
                }
4241 2 mingarao
4242 2 mingarao
4243 2 mingarao
                /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4244 2 mingarao
                 * Section - Feature: Sorting
4245 2 mingarao
                 */
4246 2 mingarao
4247 2 mingarao
                /*
4248 2 mingarao
                  * Function: _fnSort
4249 2 mingarao
                 * Purpose:  Change the order of the table
4250 2 mingarao
                 * Returns:  -
4251 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
4252 2 mingarao
                 *           bool:bApplyClasses - optional - should we apply classes or not
4253 2 mingarao
                 * Notes:    We always sort the master array and then apply a filter again
4254 2 mingarao
                 *   if it is needed. This probably isn't optimal - but atm I can't think
4255 2 mingarao
                 *   of any other way which is (each has disadvantages). we want to sort aiDisplayMaster -
4256 2 mingarao
                 *   but according to aoData[]._aData
4257 2 mingarao
                 */
4258 2 mingarao
                function _fnSort ( oSettings, bApplyClasses )
4259 2 mingarao
                {
4260 2 mingarao
                        var aaSort = [];
4261 2 mingarao
                        var oSort = _oExt.oSort;
4262 2 mingarao
                        var aoData = oSettings.aoData;
4263 2 mingarao
                        var iDataSort;
4264 2 mingarao
                        var iDataType;
4265 2 mingarao
                        var i, j, jLen;
4266 2 mingarao
4267 2 mingarao
                        /* No sorting required if server-side or no sorting array */
4268 2 mingarao
                        if ( !oSettings.oFeatures.bServerSide &&
4269 2 mingarao
                                (oSettings.aaSorting.length !== 0 || oSettings.aaSortingFixed !== null) )
4270 2 mingarao
                        {
4271 2 mingarao
                                if ( oSettings.aaSortingFixed !== null )
4272 2 mingarao
                                {
4273 2 mingarao
                                        aaSort = oSettings.aaSortingFixed.concat( oSettings.aaSorting );
4274 2 mingarao
                                }
4275 2 mingarao
                                else
4276 2 mingarao
                                {
4277 2 mingarao
                                        aaSort = oSettings.aaSorting.slice();
4278 2 mingarao
                                }
4279 2 mingarao
4280 2 mingarao
                                /* If there is a sorting data type, and a fuction belonging to it, then we need to
4281 2 mingarao
                                 * get the data from the developer's function and apply it for this column
4282 2 mingarao
                                 */
4283 2 mingarao
                                for ( i=0 ; i<aaSort.length ; i++ )
4284 2 mingarao
                                {
4285 2 mingarao
                                        var iColumn = aaSort[i][0];
4286 2 mingarao
                                        var iVisColumn = _fnColumnIndexToVisible( oSettings, iColumn );
4287 2 mingarao
                                        var sDataType = oSettings.aoColumns[ iColumn ].sSortDataType;
4288 2 mingarao
                                        if ( typeof _oExt.afnSortData[sDataType] != 'undefined' )
4289 2 mingarao
                                        {
4290 2 mingarao
                                                var aData = _oExt.afnSortData[sDataType]( oSettings, iColumn, iVisColumn );
4291 2 mingarao
                                                for ( j=0, jLen=aoData.length ; j<jLen ; j++ )
4292 2 mingarao
                                                {
4293 2 mingarao
                                                        aoData[j]._aData[iColumn] = aData[j];
4294 2 mingarao
                                                }
4295 2 mingarao
                                        }
4296 2 mingarao
                                }
4297 2 mingarao
4298 2 mingarao
                                /* DataTables offers two different methods for doing the 2D array sorting over multiple
4299 2 mingarao
                                 * columns. The first is to construct a function dynamically, and then evaluate and run
4300 2 mingarao
                                 * the function, while the second has no need for evalulation, but is a little bit slower.
4301 2 mingarao
                                 * This is used for environments which do not allow eval() for code execuation such as AIR
4302 2 mingarao
                                 */
4303 2 mingarao
                                if ( !window.runtime )
4304 2 mingarao
                                {
4305 2 mingarao
                                        /* Dynamically created sorting function. Based on the information that we have, we can
4306 2 mingarao
                                         * create a sorting function as if it were specifically written for this sort. Here we
4307 2 mingarao
                                         * want to build a function something like (for two column sorting):
4308 2 mingarao
                                         *  fnLocalSorting = function(a,b){
4309 2 mingarao
                                         *          var iTest;
4310 2 mingarao
                                         *          iTest = oSort['string-asc']('data11', 'data12');
4311 2 mingarao
                                         *          if (iTest === 0)
4312 2 mingarao
                                         *                  iTest = oSort['numeric-desc']('data21', 'data22');
4313 2 mingarao
                                         *                  if (iTest === 0)
4314 2 mingarao
                                         *                          return oSort['numeric-desc'](1,2);
4315 2 mingarao
                                         *          return iTest;
4316 2 mingarao
                                         *  }
4317 2 mingarao
                                         * So basically we have a test for each column, and if that column matches, test the
4318 2 mingarao
                                         * next one. If all columns match, then we use a numeric sort on the position the two
4319 2 mingarao
                                         * row have in the original data array in order to provide a stable sort. In order to
4320 2 mingarao
                                         * get the position for the numeric stablisation, we need to take a clone of the current
4321 2 mingarao
                                         * display array and then get the position of the sorting value from that during the
4322 2 mingarao
                                         * sort.
4323 2 mingarao
                                         *
4324 2 mingarao
                                         * Note that for use with the Closure compiler, we need to be very careful how we deal
4325 2 mingarao
                                         * with this eval. Closure will rename all of our local variables, resutling in breakage
4326 2 mingarao
                                         * if the variables in the eval don't also reflect this. For this reason, we need to use
4327 2 mingarao
                                         * 'this' to store the variables we need in the eval, so we can control them. A little
4328 2 mingarao
                                         * nasty, but well worth it for using Closure.
4329 2 mingarao
                                         */
4330 2 mingarao
                                        this.ClosureDataTables = {
4331 2 mingarao
                                                "fn": function(){},
4332 2 mingarao
                                                "data": aoData,
4333 2 mingarao
                                                "sort": _oExt.oSort,
4334 2 mingarao
                                                "master": oSettings.aiDisplayMaster.slice()
4335 2 mingarao
                                        };
4336 2 mingarao
                                        var sDynamicSort = "this.ClosureDataTables.fn = function(a,b){"+
4337 2 mingarao
                                                "var iTest, oSort=this.ClosureDataTables.sort, "+
4338 2 mingarao
                                                "aoData=this.ClosureDataTables.data, "+
4339 2 mingarao
                                                "aiOrig=this.ClosureDataTables.master;";
4340 2 mingarao
4341 2 mingarao
                                        for ( i=0 ; i<aaSort.length-1 ; i++ )
4342 2 mingarao
                                        {
4343 2 mingarao
                                                iDataSort = oSettings.aoColumns[ aaSort[i][0] ].iDataSort;
4344 2 mingarao
                                                iDataType = oSettings.aoColumns[ iDataSort ].sType;
4345 2 mingarao
                                                sDynamicSort += "iTest = oSort['"+iDataType+"-"+aaSort[i][1]+"']"+
4346 2 mingarao
                                                        "( aoData[a]._aData["+iDataSort+"], aoData[b]._aData["+iDataSort+"] ); if ( iTest === 0 )";
4347 2 mingarao
                                        }
4348 2 mingarao
4349 2 mingarao
                                        if ( aaSort.length > 0 )
4350 2 mingarao
                                        {
4351 2 mingarao
                                                iDataSort = oSettings.aoColumns[ aaSort[aaSort.length-1][0] ].iDataSort;
4352 2 mingarao
                                                iDataType = oSettings.aoColumns[ iDataSort ].sType;
4353 2 mingarao
                                                sDynamicSort += "iTest = oSort['"+iDataType+"-"+aaSort[aaSort.length-1][1]+"']"+
4354 2 mingarao
                                                        "( aoData[a]._aData["+iDataSort+"], aoData[b]._aData["+iDataSort+"] );"+
4355 2 mingarao
                                                        "if (iTest===0) "+
4356 2 mingarao
                                                                "return oSort['numeric-asc'](jQuery.inArray(a,aiOrig), jQuery.inArray(b,aiOrig)); "+
4357 2 mingarao
                                                        "return iTest;}";
4358 2 mingarao
4359 2 mingarao
                                                /* The eval has to be done to a variable for IE */
4360 2 mingarao
                                                eval( sDynamicSort );
4361 2 mingarao
                                                oSettings.aiDisplayMaster.sort( this.ClosureDataTables.fn );
4362 2 mingarao
                                        }
4363 2 mingarao
                                        this.ClosureDataTables = undefined;
4364 2 mingarao
                                }
4365 2 mingarao
                                else
4366 2 mingarao
                                {
4367 2 mingarao
                                        /*
4368 2 mingarao
                                         * Non-eval() sorting (AIR and other environments which doesn't allow code in eval()
4369 2 mingarao
                                         * Note that for reasonable sized data sets this method is around 1.5 times slower than
4370 2 mingarao
                                         * the eval above (hence why it is not used all the time). Oddly enough, it is ever so
4371 2 mingarao
                                         * slightly faster for very small sets (presumably the eval has overhead).
4372 2 mingarao
                                         *   Single column (1083 records) - eval: 32mS   AIR: 38mS
4373 2 mingarao
                                         *   Two columns (1083 records) -   eval: 55mS   AIR: 66mS
4374 2 mingarao
                                         */
4375 2 mingarao
4376 2 mingarao
                                        /* Build a cached array so the sort doesn't have to process this stuff on every call */
4377 2 mingarao
                                        var aAirSort = [];
4378 2 mingarao
                                        var iLen = aaSort.length;
4379 2 mingarao
                                        for ( i=0 ; i<iLen ; i++ )
4380 2 mingarao
                                        {
4381 2 mingarao
                                                iDataSort = oSettings.aoColumns[ aaSort[i][0] ].iDataSort;
4382 2 mingarao
                                                aAirSort.push( [
4383 2 mingarao
                                                        iDataSort,
4384 2 mingarao
                                                        oSettings.aoColumns[ iDataSort ].sType+'-'+aaSort[i][1]
4385 2 mingarao
                                                ] );
4386 2 mingarao
                                        }
4387 2 mingarao
4388 2 mingarao
                                        oSettings.aiDisplayMaster.sort( function (a,b) {
4389 2 mingarao
                                                var iTest;
4390 2 mingarao
                                                for ( var i=0 ; i<iLen ; i++ )
4391 2 mingarao
                                                {
4392 2 mingarao
                                                        iTest = oSort[ aAirSort[i][1] ]( aoData[a]._aData[aAirSort[i][0]], aoData[b]._aData[aAirSort[i][0]] );
4393 2 mingarao
                                                        if ( iTest !== 0 )
4394 2 mingarao
                                                        {
4395 2 mingarao
                                                                return iTest;
4396 2 mingarao
                                                        }
4397 2 mingarao
                                                }
4398 2 mingarao
                                                return 0;
4399 2 mingarao
                                        } );
4400 2 mingarao
                                }
4401 2 mingarao
                        }
4402 2 mingarao
4403 2 mingarao
                        /* Alter the sorting classes to take account of the changes */
4404 2 mingarao
                        if ( typeof bApplyClasses == 'undefined' || bApplyClasses )
4405 2 mingarao
                        {
4406 2 mingarao
                                _fnSortingClasses( oSettings );
4407 2 mingarao
                        }
4408 2 mingarao
4409 2 mingarao
                        /* Tell the draw function that we have sorted the data */
4410 2 mingarao
                        oSettings.bSorted = true;
4411 2 mingarao
4412 2 mingarao
                        /* Copy the master data into the draw array and re-draw */
4413 2 mingarao
                        if ( oSettings.oFeatures.bFilter )
4414 2 mingarao
                        {
4415 2 mingarao
                                /* _fnFilter() will redraw the table for us */
4416 2 mingarao
                                _fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 );
4417 2 mingarao
                        }
4418 2 mingarao
                        else
4419 2 mingarao
                        {
4420 2 mingarao
                                oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
4421 2 mingarao
                                oSettings._iDisplayStart = 0; /* reset display back to page 0 */
4422 2 mingarao
                                _fnCalculateEnd( oSettings );
4423 2 mingarao
                                _fnDraw( oSettings );
4424 2 mingarao
                        }
4425 2 mingarao
                }
4426 2 mingarao
4427 2 mingarao
                /*
4428 2 mingarao
                 * Function: _fnSortAttachListener
4429 2 mingarao
                 * Purpose:  Attach a sort handler (click) to a node
4430 2 mingarao
                 * Returns:  -
4431 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
4432 2 mingarao
                 *           node:nNode - node to attach the handler to
4433 2 mingarao
                 *           int:iDataIndex - column sorting index
4434 2 mingarao
                 *           function:fnCallback - callback function - optional
4435 2 mingarao
                 */
4436 2 mingarao
                function _fnSortAttachListener ( oSettings, nNode, iDataIndex, fnCallback )
4437 2 mingarao
                {
4438 2 mingarao
                        $(nNode).click( function (e) {
4439 2 mingarao
                                /* If the column is not sortable - don't to anything */
4440 2 mingarao
                                if ( oSettings.aoColumns[iDataIndex].bSortable === false )
4441 2 mingarao
                                {
4442 2 mingarao
                                        return;
4443 2 mingarao
                                }
4444 2 mingarao
4445 2 mingarao
                                /*
4446 2 mingarao
                                 * This is a little bit odd I admit... I declare a temporary function inside the scope of
4447 2 mingarao
                                 * _fnDrawHead and the click handler in order that the code presented here can be used
4448 2 mingarao
                                 * twice - once for when bProcessing is enabled, and another time for when it is
4449 2 mingarao
                                 * disabled, as we need to perform slightly different actions.
4450 2 mingarao
                                 *   Basically the issue here is that the Javascript engine in modern browsers don't
4451 2 mingarao
                                 * appear to allow the rendering engine to update the display while it is still excuting
4452 2 mingarao
                                 * it's thread (well - it does but only after long intervals). This means that the
4453 2 mingarao
                                 * 'processing' display doesn't appear for a table sort. To break the js thread up a bit
4454 2 mingarao
                                 * I force an execution break by using setTimeout - but this breaks the expected
4455 2 mingarao
                                 * thread continuation for the end-developer's point of view (their code would execute
4456 2 mingarao
                                 * too early), so we on;y do it when we absolutely have to.
4457 2 mingarao
                                 */
4458 2 mingarao
                                var fnInnerSorting = function () {
4459 2 mingarao
                                        var iColumn, iNextSort;
4460 2 mingarao
4461 2 mingarao
                                        /* If the shift key is pressed then we are multipe column sorting */
4462 2 mingarao
                                        if ( e.shiftKey )
4463 2 mingarao
                                        {
4464 2 mingarao
                                                /* Are we already doing some kind of sort on this column? */
4465 2 mingarao
                                                var bFound = false;
4466 2 mingarao
                                                for ( var i=0 ; i<oSettings.aaSorting.length ; i++ )
4467 2 mingarao
                                                {
4468 2 mingarao
                                                        if ( oSettings.aaSorting[i][0] == iDataIndex )
4469 2 mingarao
                                                        {
4470 2 mingarao
                                                                bFound = true;
4471 2 mingarao
                                                                iColumn = oSettings.aaSorting[i][0];
4472 2 mingarao
                                                                iNextSort = oSettings.aaSorting[i][2]+1;
4473 2 mingarao
4474 2 mingarao
                                                                if ( typeof oSettings.aoColumns[iColumn].asSorting[iNextSort] == 'undefined' )
4475 2 mingarao
                                                                {
4476 2 mingarao
                                                                        /* Reached the end of the sorting options, remove from multi-col sort */
4477 2 mingarao
                                                                        oSettings.aaSorting.splice( i, 1 );
4478 2 mingarao
                                                                }
4479 2 mingarao
                                                                else
4480 2 mingarao
                                                                {
4481 2 mingarao
                                                                        /* Move onto next sorting direction */
4482 2 mingarao
                                                                        oSettings.aaSorting[i][1] = oSettings.aoColumns[iColumn].asSorting[iNextSort];
4483 2 mingarao
                                                                        oSettings.aaSorting[i][2] = iNextSort;
4484 2 mingarao
                                                                }
4485 2 mingarao
                                                                break;
4486 2 mingarao
                                                        }
4487 2 mingarao
                                                }
4488 2 mingarao
4489 2 mingarao
                                                /* No sort yet - add it in */
4490 2 mingarao
                                                if ( bFound === false )
4491 2 mingarao
                                                {
4492 2 mingarao
                                                        oSettings.aaSorting.push( [ iDataIndex,
4493 2 mingarao
                                                                oSettings.aoColumns[iDataIndex].asSorting[0], 0 ] );
4494 2 mingarao
                                                }
4495 2 mingarao
                                        }
4496 2 mingarao
                                        else
4497 2 mingarao
                                        {
4498 2 mingarao
                                                /* If no shift key then single column sort */
4499 2 mingarao
                                                if ( oSettings.aaSorting.length == 1 && oSettings.aaSorting[0][0] == iDataIndex )
4500 2 mingarao
                                                {
4501 2 mingarao
                                                        iColumn = oSettings.aaSorting[0][0];
4502 2 mingarao
                                                        iNextSort = oSettings.aaSorting[0][2]+1;
4503 2 mingarao
                                                        if ( typeof oSettings.aoColumns[iColumn].asSorting[iNextSort] == 'undefined' )
4504 2 mingarao
                                                        {
4505 2 mingarao
                                                                iNextSort = 0;
4506 2 mingarao
                                                        }
4507 2 mingarao
                                                        oSettings.aaSorting[0][1] = oSettings.aoColumns[iColumn].asSorting[iNextSort];
4508 2 mingarao
                                                        oSettings.aaSorting[0][2] = iNextSort;
4509 2 mingarao
                                                }
4510 2 mingarao
                                                else
4511 2 mingarao
                                                {
4512 2 mingarao
                                                        oSettings.aaSorting.splice( 0, oSettings.aaSorting.length );
4513 2 mingarao
                                                        oSettings.aaSorting.push( [ iDataIndex,
4514 2 mingarao
                                                                oSettings.aoColumns[iDataIndex].asSorting[0], 0 ] );
4515 2 mingarao
                                                }
4516 2 mingarao
                                        }
4517 2 mingarao
4518 2 mingarao
                                        /* Run the sort */
4519 2 mingarao
                                        _fnSort( oSettings );
4520 2 mingarao
                                }; /* /fnInnerSorting */
4521 2 mingarao
4522 2 mingarao
                                if ( !oSettings.oFeatures.bProcessing )
4523 2 mingarao
                                {
4524 2 mingarao
                                        fnInnerSorting();
4525 2 mingarao
                                }
4526 2 mingarao
                                else
4527 2 mingarao
                                {
4528 2 mingarao
                                        _fnProcessingDisplay( oSettings, true );
4529 2 mingarao
                                        setTimeout( function() {
4530 2 mingarao
                                                fnInnerSorting();
4531 2 mingarao
                                                if ( !oSettings.oFeatures.bServerSide )
4532 2 mingarao
                                                {
4533 2 mingarao
                                                        _fnProcessingDisplay( oSettings, false );
4534 2 mingarao
                                                }
4535 2 mingarao
                                        }, 0 );
4536 2 mingarao
                                }
4537 2 mingarao
4538 2 mingarao
                                /* Call the user specified callback function - used for async user interaction */
4539 2 mingarao
                                if ( typeof fnCallback == 'function' )
4540 2 mingarao
                                {
4541 2 mingarao
                                        fnCallback( oSettings );
4542 2 mingarao
                                }
4543 2 mingarao
                        } );
4544 2 mingarao
                }
4545 2 mingarao
4546 2 mingarao
                /*
4547 2 mingarao
                 * Function: _fnSortingClasses
4548 2 mingarao
                 * Purpose:  Set the sortting classes on the header
4549 2 mingarao
                 * Returns:  -
4550 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
4551 2 mingarao
                 * Notes:    It is safe to call this function when bSort and bSortClasses are false
4552 2 mingarao
                 */
4553 2 mingarao
                function _fnSortingClasses( oSettings )
4554 2 mingarao
                {
4555 2 mingarao
                        var i, iLen, j, jLen, iFound;
4556 2 mingarao
                        var aaSort, sClass;
4557 2 mingarao
                        var iColumns = oSettings.aoColumns.length;
4558 2 mingarao
                        var oClasses = oSettings.oClasses;
4559 2 mingarao
4560 2 mingarao
                        for ( i=0 ; i<iColumns ; i++ )
4561 2 mingarao
                        {
4562 2 mingarao
                                if ( oSettings.aoColumns[i].bSortable )
4563 2 mingarao
                                {
4564 2 mingarao
                                        $(oSettings.aoColumns[i].nTh).removeClass( oClasses.sSortAsc +" "+ oClasses.sSortDesc +
4565 2 mingarao
                                                 " "+ oSettings.aoColumns[i].sSortingClass );
4566 2 mingarao
                                }
4567 2 mingarao
                        }
4568 2 mingarao
4569 2 mingarao
                        if ( oSettings.aaSortingFixed !== null )
4570 2 mingarao
                        {
4571 2 mingarao
                                aaSort = oSettings.aaSortingFixed.concat( oSettings.aaSorting );
4572 2 mingarao
                        }
4573 2 mingarao
                        else
4574 2 mingarao
                        {
4575 2 mingarao
                                aaSort = oSettings.aaSorting.slice();
4576 2 mingarao
                        }
4577 2 mingarao
4578 2 mingarao
                        /* Apply the required classes to the header */
4579 2 mingarao
                        for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
4580 2 mingarao
                        {
4581 2 mingarao
                                if ( oSettings.aoColumns[i].bSortable )
4582 2 mingarao
                                {
4583 2 mingarao
                                        sClass = oSettings.aoColumns[i].sSortingClass;
4584 2 mingarao
                                        iFound = -1;
4585 2 mingarao
                                        for ( j=0 ; j<aaSort.length ; j++ )
4586 2 mingarao
                                        {
4587 2 mingarao
                                                if ( aaSort[j][0] == i )
4588 2 mingarao
                                                {
4589 2 mingarao
                                                        sClass = ( aaSort[j][1] == "asc" ) ?
4590 2 mingarao
                                                                oClasses.sSortAsc : oClasses.sSortDesc;
4591 2 mingarao
                                                        iFound = j;
4592 2 mingarao
                                                        break;
4593 2 mingarao
                                                }
4594 2 mingarao
                                        }
4595 2 mingarao
                                        $(oSettings.aoColumns[i].nTh).addClass( sClass );
4596 2 mingarao
4597 2 mingarao
                                        if ( oSettings.bJUI )
4598 2 mingarao
                                        {
4599 2 mingarao
                                                /* jQuery UI uses extra markup */
4600 2 mingarao
                                                var jqSpan = $("span", oSettings.aoColumns[i].nTh);
4601 2 mingarao
                                                jqSpan.removeClass(oClasses.sSortJUIAsc +" "+ oClasses.sSortJUIDesc +" "+
4602 2 mingarao
                                                        oClasses.sSortJUI +" "+ oClasses.sSortJUIAscAllowed +" "+ oClasses.sSortJUIDescAllowed );
4603 2 mingarao
4604 2 mingarao
                                                var sSpanClass;
4605 2 mingarao
                                                if ( iFound == -1 )
4606 2 mingarao
                                                {
4607 2 mingarao
                                                         sSpanClass = oSettings.aoColumns[i].sSortingClassJUI;
4608 2 mingarao
                                                }
4609 2 mingarao
                                                else if ( aaSort[iFound][1] == "asc" )
4610 2 mingarao
                                                {
4611 2 mingarao
                                                        sSpanClass = oClasses.sSortJUIAsc;
4612 2 mingarao
                                                }
4613 2 mingarao
                                                else
4614 2 mingarao
                                                {
4615 2 mingarao
                                                        sSpanClass = oClasses.sSortJUIDesc;
4616 2 mingarao
                                                }
4617 2 mingarao
4618 2 mingarao
                                                jqSpan.addClass( sSpanClass );
4619 2 mingarao
                                        }
4620 2 mingarao
                                }
4621 2 mingarao
                                else
4622 2 mingarao
                                {
4623 2 mingarao
                                        /* No sorting on this column, so add the base class. This will have been assigned by
4624 2 mingarao
                                         * _fnAddColumn
4625 2 mingarao
                                         */
4626 2 mingarao
                                        $(oSettings.aoColumns[i].nTh).addClass( oSettings.aoColumns[i].sSortingClass );
4627 2 mingarao
                                }
4628 2 mingarao
                        }
4629 2 mingarao
4630 2 mingarao
                        /*
4631 2 mingarao
                         * Apply the required classes to the table body
4632 2 mingarao
                         * Note that this is given as a feature switch since it can significantly slow down a sort
4633 2 mingarao
                         * on large data sets (adding and removing of classes is always slow at the best of times..)
4634 2 mingarao
                         * Further to this, note that this code is admitadly fairly ugly. It could be made a lot
4635 2 mingarao
                         * simpiler using jQuery selectors and add/removeClass, but that is significantly slower
4636 2 mingarao
                         * (on the order of 5 times slower) - hence the direct DOM manipulation here.
4637 2 mingarao
                         */
4638 2 mingarao
                        sClass = oClasses.sSortColumn;
4639 2 mingarao
4640 2 mingarao
                        if ( oSettings.oFeatures.bSort && oSettings.oFeatures.bSortClasses )
4641 2 mingarao
                        {
4642 2 mingarao
                                var nTds = _fnGetTdNodes( oSettings );
4643 2 mingarao
4644 2 mingarao
                                /* Remove the old classes */
4645 2 mingarao
                                if ( nTds.length >= iColumns )
4646 2 mingarao
                                {
4647 2 mingarao
                                        for ( i=0 ; i<iColumns ; i++ )
4648 2 mingarao
                                        {
4649 2 mingarao
                                                if ( nTds[i].className.indexOf(sClass+"1") != -1 )
4650 2 mingarao
                                                {
4651 2 mingarao
                                                        for ( j=0, jLen=(nTds.length/iColumns) ; j<jLen ; j++ )
4652 2 mingarao
                                                        {
4653 2 mingarao
                                                                nTds[(iColumns*j)+i].className =
4654 2 mingarao
                                                                        $.trim( nTds[(iColumns*j)+i].className.replace( sClass+"1", "" ) );
4655 2 mingarao
                                                        }
4656 2 mingarao
                                                }
4657 2 mingarao
                                                else if ( nTds[i].className.indexOf(sClass+"2") != -1 )
4658 2 mingarao
                                                {
4659 2 mingarao
                                                        for ( j=0, jLen=(nTds.length/iColumns) ; j<jLen ; j++ )
4660 2 mingarao
                                                        {
4661 2 mingarao
                                                                nTds[(iColumns*j)+i].className =
4662 2 mingarao
                                                                        $.trim( nTds[(iColumns*j)+i].className.replace( sClass+"2", "" ) );
4663 2 mingarao
                                                        }
4664 2 mingarao
                                                }
4665 2 mingarao
                                                else if ( nTds[i].className.indexOf(sClass+"3") != -1 )
4666 2 mingarao
                                                {
4667 2 mingarao
                                                        for ( j=0, jLen=(nTds.length/iColumns) ; j<jLen ; j++ )
4668 2 mingarao
                                                        {
4669 2 mingarao
                                                                nTds[(iColumns*j)+i].className =
4670 2 mingarao
                                                                        $.trim( nTds[(iColumns*j)+i].className.replace( " "+sClass+"3", "" ) );
4671 2 mingarao
                                                        }
4672 2 mingarao
                                                }
4673 2 mingarao
                                        }
4674 2 mingarao
                                }
4675 2 mingarao
4676 2 mingarao
                                /* Add the new classes to the table */
4677 2 mingarao
                                var iClass = 1, iTargetCol;
4678 2 mingarao
                                for ( i=0 ; i<aaSort.length ; i++ )
4679 2 mingarao
                                {
4680 2 mingarao
                                        iTargetCol = parseInt( aaSort[i][0], 10 );
4681 2 mingarao
                                        for ( j=0, jLen=(nTds.length/iColumns) ; j<jLen ; j++ )
4682 2 mingarao
                                        {
4683 2 mingarao
                                                nTds[(iColumns*j)+iTargetCol].className += " "+sClass+iClass;
4684 2 mingarao
                                        }
4685 2 mingarao
4686 2 mingarao
                                        if ( iClass < 3 )
4687 2 mingarao
                                        {
4688 2 mingarao
                                                iClass++;
4689 2 mingarao
                                        }
4690 2 mingarao
                                }
4691 2 mingarao
                        }
4692 2 mingarao
                }
4693 2 mingarao
4694 2 mingarao
4695 2 mingarao
                /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4696 2 mingarao
                 * Section - Feature: Pagination. Note that most of the paging logic is done in
4697 2 mingarao
                 * _oExt.oPagination
4698 2 mingarao
                 */
4699 2 mingarao
4700 2 mingarao
                /*
4701 2 mingarao
                 * Function: _fnFeatureHtmlPaginate
4702 2 mingarao
                 * Purpose:  Generate the node required for default pagination
4703 2 mingarao
                 * Returns:  node
4704 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
4705 2 mingarao
                 */
4706 2 mingarao
                function _fnFeatureHtmlPaginate ( oSettings )
4707 2 mingarao
                {
4708 2 mingarao
                        if ( oSettings.oScroll.bInfinite )
4709 2 mingarao
                        {
4710 2 mingarao
                                return null;
4711 2 mingarao
                        }
4712 2 mingarao
4713 2 mingarao
                        var nPaginate = document.createElement( 'div' );
4714 2 mingarao
                        nPaginate.className = oSettings.oClasses.sPaging+oSettings.sPaginationType;
4715 2 mingarao
4716 2 mingarao
                        _oExt.oPagination[ oSettings.sPaginationType ].fnInit( oSettings, nPaginate,
4717 2 mingarao
                                function( oSettings ) {
4718 2 mingarao
                                        _fnCalculateEnd( oSettings );
4719 2 mingarao
                                        _fnDraw( oSettings );
4720 2 mingarao
                                }
4721 2 mingarao
                        );
4722 2 mingarao
4723 2 mingarao
                        /* Add a draw callback for the pagination on first instance, to update the paging display */
4724 2 mingarao
                        if ( typeof oSettings.aanFeatures.p == "undefined" )
4725 2 mingarao
                        {
4726 2 mingarao
                                oSettings.aoDrawCallback.push( {
4727 2 mingarao
                                        "fn": function( oSettings ) {
4728 2 mingarao
                                                _oExt.oPagination[ oSettings.sPaginationType ].fnUpdate( oSettings, function( oSettings ) {
4729 2 mingarao
                                                        _fnCalculateEnd( oSettings );
4730 2 mingarao
                                                        _fnDraw( oSettings );
4731 2 mingarao
                                                } );
4732 2 mingarao
                                        },
4733 2 mingarao
                                        "sName": "pagination"
4734 2 mingarao
                                } );
4735 2 mingarao
                        }
4736 2 mingarao
                        return nPaginate;
4737 2 mingarao
                }
4738 2 mingarao
4739 2 mingarao
                /*
4740 2 mingarao
                 * Function: _fnPageChange
4741 2 mingarao
                 * Purpose:  Alter the display settings to change the page
4742 2 mingarao
                 * Returns:  bool:true - page has changed, false - no change (no effect) eg 'first' on page 1
4743 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
4744 2 mingarao
                 *           string:sAction - paging action to take: "first", "previous", "next" or "last"
4745 2 mingarao
                 */
4746 2 mingarao
                function _fnPageChange ( oSettings, sAction )
4747 2 mingarao
                {
4748 2 mingarao
                        var iOldStart = oSettings._iDisplayStart;
4749 2 mingarao
4750 2 mingarao
                        if ( sAction == "first" )
4751 2 mingarao
                        {
4752 2 mingarao
                                oSettings._iDisplayStart = 0;
4753 2 mingarao
                        }
4754 2 mingarao
                        else if ( sAction == "previous" )
4755 2 mingarao
                        {
4756 2 mingarao
                                oSettings._iDisplayStart = oSettings._iDisplayLength>=0 ?
4757 2 mingarao
                                        oSettings._iDisplayStart - oSettings._iDisplayLength :
4758 2 mingarao
                                        0;
4759 2 mingarao
4760 2 mingarao
                                /* Correct for underrun */
4761 2 mingarao
                                if ( oSettings._iDisplayStart < 0 )
4762 2 mingarao
                                {
4763 2 mingarao
                                  oSettings._iDisplayStart = 0;
4764 2 mingarao
                                }
4765 2 mingarao
                        }
4766 2 mingarao
                        else if ( sAction == "next" )
4767 2 mingarao
                        {
4768 2 mingarao
                                if ( oSettings._iDisplayLength >= 0 )
4769 2 mingarao
                                {
4770 2 mingarao
                                        /* Make sure we are not over running the display array */
4771 2 mingarao
                                        if ( oSettings._iDisplayStart + oSettings._iDisplayLength < oSettings.fnRecordsDisplay() )
4772 2 mingarao
                                        {
4773 2 mingarao
                                                oSettings._iDisplayStart += oSettings._iDisplayLength;
4774 2 mingarao
                                        }
4775 2 mingarao
                                }
4776 2 mingarao
                                else
4777 2 mingarao
                                {
4778 2 mingarao
                                        oSettings._iDisplayStart = 0;
4779 2 mingarao
                                }
4780 2 mingarao
                        }
4781 2 mingarao
                        else if ( sAction == "last" )
4782 2 mingarao
                        {
4783 2 mingarao
                                if ( oSettings._iDisplayLength >= 0 )
4784 2 mingarao
                                {
4785 2 mingarao
                                        var iPages = parseInt( (oSettings.fnRecordsDisplay()-1) / oSettings._iDisplayLength, 10 ) + 1;
4786 2 mingarao
                                        oSettings._iDisplayStart = (iPages-1) * oSettings._iDisplayLength;
4787 2 mingarao
                                }
4788 2 mingarao
                                else
4789 2 mingarao
                                {
4790 2 mingarao
                                        oSettings._iDisplayStart = 0;
4791 2 mingarao
                                }
4792 2 mingarao
                        }
4793 2 mingarao
                        else
4794 2 mingarao
                        {
4795 2 mingarao
                                _fnLog( oSettings, 0, "Unknown paging action: "+sAction );
4796 2 mingarao
                        }
4797 2 mingarao
4798 2 mingarao
                        return iOldStart != oSettings._iDisplayStart;
4799 2 mingarao
                }
4800 2 mingarao
4801 2 mingarao
4802 2 mingarao
                /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4803 2 mingarao
                 * Section - Feature: HTML info
4804 2 mingarao
                 */
4805 2 mingarao
4806 2 mingarao
                /*
4807 2 mingarao
                 * Function: _fnFeatureHtmlInfo
4808 2 mingarao
                 * Purpose:  Generate the node required for the info display
4809 2 mingarao
                 * Returns:  node
4810 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
4811 2 mingarao
                 */
4812 2 mingarao
                function _fnFeatureHtmlInfo ( oSettings )
4813 2 mingarao
                {
4814 2 mingarao
                        var nInfo = document.createElement( 'div' );
4815 2 mingarao
                        nInfo.className = oSettings.oClasses.sInfo;
4816 2 mingarao
4817 2 mingarao
                        /* Actions that are to be taken once only for this feature */
4818 2 mingarao
                        if ( typeof oSettings.aanFeatures.i == "undefined" )
4819 2 mingarao
                        {
4820 2 mingarao
                                /* Add draw callback */
4821 2 mingarao
                                oSettings.aoDrawCallback.push( {
4822 2 mingarao
                                        "fn": _fnUpdateInfo,
4823 2 mingarao
                                        "sName": "information"
4824 2 mingarao
                                } );
4825 2 mingarao
4826 2 mingarao
                                /* Add id */
4827 2 mingarao
                                if ( oSettings.sTableId !== '' )
4828 2 mingarao
                                {
4829 2 mingarao
                                        nInfo.setAttribute( 'id', oSettings.sTableId+'_info' );
4830 2 mingarao
                                }
4831 2 mingarao
                        }
4832 2 mingarao
4833 2 mingarao
                        return nInfo;
4834 2 mingarao
                }
4835 2 mingarao
4836 2 mingarao
                /*
4837 2 mingarao
                 * Function: _fnUpdateInfo
4838 2 mingarao
                 * Purpose:  Update the information elements in the display
4839 2 mingarao
                 * Returns:  -
4840 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
4841 2 mingarao
                 */
4842 2 mingarao
                function _fnUpdateInfo ( oSettings )
4843 2 mingarao
                {
4844 2 mingarao
                        /* Show information about the table */
4845 2 mingarao
                        if ( !oSettings.oFeatures.bInfo || oSettings.aanFeatures.i.length === 0 )
4846 2 mingarao
                        {
4847 2 mingarao
                                return;
4848 2 mingarao
                        }
4849 2 mingarao
4850 2 mingarao
                        var
4851 2 mingarao
                                iStart = oSettings._iDisplayStart+1, iEnd = oSettings.fnDisplayEnd(),
4852 2 mingarao
                                iMax = oSettings.fnRecordsTotal(), iTotal = oSettings.fnRecordsDisplay(),
4853 2 mingarao
                                sStart = oSettings.fnFormatNumber( iStart ), sEnd = oSettings.fnFormatNumber( iEnd ),
4854 2 mingarao
                                sMax = oSettings.fnFormatNumber( iMax ), sTotal = oSettings.fnFormatNumber( iTotal ),
4855 2 mingarao
                                sOut;
4856 2 mingarao
4857 2 mingarao
                        /* When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
4858 2 mingarao
                         * internally
4859 2 mingarao
                         */
4860 2 mingarao
                        if ( oSettings.oScroll.bInfinite )
4861 2 mingarao
                        {
4862 2 mingarao
                                sStart = oSettings.fnFormatNumber( 1 );
4863 2 mingarao
                        }
4864 2 mingarao
4865 2 mingarao
                        if ( oSettings.fnRecordsDisplay() === 0 &&
4866 2 mingarao
                                   oSettings.fnRecordsDisplay() == oSettings.fnRecordsTotal() )
4867 2 mingarao
                        {
4868 2 mingarao
                                /* Empty record set */
4869 2 mingarao
                                sOut = oSettings.oLanguage.sInfoEmpty+ oSettings.oLanguage.sInfoPostFix;
4870 2 mingarao
                        }
4871 2 mingarao
                        else if ( oSettings.fnRecordsDisplay() === 0 )
4872 2 mingarao
                        {
4873 2 mingarao
                                /* Rmpty record set after filtering */
4874 2 mingarao
                                sOut = oSettings.oLanguage.sInfoEmpty +' '+
4875 2 mingarao
                                        oSettings.oLanguage.sInfoFiltered.replace('_MAX_', sMax)+
4876 2 mingarao
                                                oSettings.oLanguage.sInfoPostFix;
4877 2 mingarao
                        }
4878 2 mingarao
                        else if ( oSettings.fnRecordsDisplay() == oSettings.fnRecordsTotal() )
4879 2 mingarao
                        {
4880 2 mingarao
                                /* Normal record set */
4881 2 mingarao
                                sOut = oSettings.oLanguage.sInfo.
4882 2 mingarao
                                                replace('_START_', sStart).
4883 2 mingarao
                                                replace('_END_',   sEnd).
4884 2 mingarao
                                                replace('_TOTAL_', sTotal)+
4885 2 mingarao
                                        oSettings.oLanguage.sInfoPostFix;
4886 2 mingarao
                        }
4887 2 mingarao
                        else
4888 2 mingarao
                        {
4889 2 mingarao
                                /* Record set after filtering */
4890 2 mingarao
                                sOut = oSettings.oLanguage.sInfo.
4891 2 mingarao
                                                replace('_START_', sStart).
4892 2 mingarao
                                                replace('_END_',   sEnd).
4893 2 mingarao
                                                replace('_TOTAL_', sTotal) +' '+
4894 2 mingarao
                                        oSettings.oLanguage.sInfoFiltered.replace('_MAX_',
4895 2 mingarao
                                                oSettings.fnFormatNumber(oSettings.fnRecordsTotal()))+
4896 2 mingarao
                                        oSettings.oLanguage.sInfoPostFix;
4897 2 mingarao
                        }
4898 2 mingarao
4899 2 mingarao
                        if ( oSettings.oLanguage.fnInfoCallback !== null )
4900 2 mingarao
                        {
4901 2 mingarao
                                sOut = oSettings.oLanguage.fnInfoCallback( oSettings, iStart, iEnd, iMax, iTotal, sOut );
4902 2 mingarao
                        }
4903 2 mingarao
4904 2 mingarao
                        var n = oSettings.aanFeatures.i;
4905 2 mingarao
                        for ( var i=0, iLen=n.length ; i<iLen ; i++ )
4906 2 mingarao
                        {
4907 2 mingarao
                                $(n[i]).html( sOut );
4908 2 mingarao
                        }
4909 2 mingarao
                }
4910 2 mingarao
4911 2 mingarao
4912 2 mingarao
                /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4913 2 mingarao
                 * Section - Feature: Length change
4914 2 mingarao
                 */
4915 2 mingarao
4916 2 mingarao
                /*
4917 2 mingarao
                 * Function: _fnFeatureHtmlLength
4918 2 mingarao
                 * Purpose:  Generate the node required for user display length changing
4919 2 mingarao
                 * Returns:  node
4920 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
4921 2 mingarao
                 */
4922 2 mingarao
                function _fnFeatureHtmlLength ( oSettings )
4923 2 mingarao
                {
4924 2 mingarao
                        if ( oSettings.oScroll.bInfinite )
4925 2 mingarao
                        {
4926 2 mingarao
                                return null;
4927 2 mingarao
                        }
4928 2 mingarao
4929 2 mingarao
                        /* This can be overruled by not using the _MENU_ var/macro in the language variable */
4930 2 mingarao
                        var sName = (oSettings.sTableId === "") ? "" : 'name="'+oSettings.sTableId+'_length"';
4931 2 mingarao
                        var sStdMenu = '<select size="1" '+sName+'>';
4932 2 mingarao
                        var i, iLen;
4933 2 mingarao
4934 2 mingarao
                        if ( oSettings.aLengthMenu.length == 2 && typeof oSettings.aLengthMenu[0] == 'object' &&
4935 2 mingarao
                                        typeof oSettings.aLengthMenu[1] == 'object' )
4936 2 mingarao
                        {
4937 2 mingarao
                                for ( i=0, iLen=oSettings.aLengthMenu[0].length ; i<iLen ; i++ )
4938 2 mingarao
                                {
4939 2 mingarao
                                        sStdMenu += '<option value="'+oSettings.aLengthMenu[0][i]+'">'+
4940 2 mingarao
                                                oSettings.aLengthMenu[1][i]+'</option>';
4941 2 mingarao
                                }
4942 2 mingarao
                        }
4943 2 mingarao
                        else
4944 2 mingarao
                        {
4945 2 mingarao
                                for ( i=0, iLen=oSettings.aLengthMenu.length ; i<iLen ; i++ )
4946 2 mingarao
                                {
4947 2 mingarao
                                        sStdMenu += '<option value="'+oSettings.aLengthMenu[i]+'">'+
4948 2 mingarao
                                                oSettings.aLengthMenu[i]+'</option>';
4949 2 mingarao
                                }
4950 2 mingarao
                        }
4951 2 mingarao
                        sStdMenu += '</select>';
4952 2 mingarao
4953 2 mingarao
                        var nLength = document.createElement( 'div' );
4954 2 mingarao
                        if ( oSettings.sTableId !== '' && typeof oSettings.aanFeatures.l == "undefined" )
4955 2 mingarao
                        {
4956 2 mingarao
                                nLength.setAttribute( 'id', oSettings.sTableId+'_length' );
4957 2 mingarao
                        }
4958 2 mingarao
                        nLength.className = oSettings.oClasses.sLength;
4959 2 mingarao
                        nLength.innerHTML = oSettings.oLanguage.sLengthMenu.replace( '_MENU_', sStdMenu );
4960 2 mingarao
4961 2 mingarao
                        /*
4962 2 mingarao
                         * Set the length to the current display length - thanks to Andrea Pavlovic for this fix,
4963 2 mingarao
                         * and Stefan Skopnik for fixing the fix!
4964 2 mingarao
                         */
4965 2 mingarao
                        $('select option[value="'+oSettings._iDisplayLength+'"]',nLength).attr("selected",true);
4966 2 mingarao
4967 2 mingarao
                        $('select', nLength).change( function(e) {
4968 2 mingarao
                                var iVal = $(this).val();
4969 2 mingarao
4970 2 mingarao
                                /* Update all other length options for the new display */
4971 2 mingarao
                                var n = oSettings.aanFeatures.l;
4972 2 mingarao
                                for ( i=0, iLen=n.length ; i<iLen ; i++ )
4973 2 mingarao
                                {
4974 2 mingarao
                                        if ( n[i] != this.parentNode )
4975 2 mingarao
                                        {
4976 2 mingarao
                                                $('select', n[i]).val( iVal );
4977 2 mingarao
                                        }
4978 2 mingarao
                                }
4979 2 mingarao
4980 2 mingarao
                                /* Redraw the table */
4981 2 mingarao
                                oSettings._iDisplayLength = parseInt(iVal, 10);
4982 2 mingarao
                                _fnCalculateEnd( oSettings );
4983 2 mingarao
4984 2 mingarao
                                /* If we have space to show extra rows (backing up from the end point - then do so */
4985 2 mingarao
                                if ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() )
4986 2 mingarao
                                {
4987 2 mingarao
                                        oSettings._iDisplayStart = oSettings.fnDisplayEnd() - oSettings._iDisplayLength;
4988 2 mingarao
                                        if ( oSettings._iDisplayStart < 0 )
4989 2 mingarao
                                        {
4990 2 mingarao
                                                oSettings._iDisplayStart = 0;
4991 2 mingarao
                                        }
4992 2 mingarao
                                }
4993 2 mingarao
4994 2 mingarao
                                if ( oSettings._iDisplayLength == -1 )
4995 2 mingarao
                                {
4996 2 mingarao
                                        oSettings._iDisplayStart = 0;
4997 2 mingarao
                                }
4998 2 mingarao
4999 2 mingarao
                                _fnDraw( oSettings );
5000 2 mingarao
                        } );
5001 2 mingarao
5002 2 mingarao
                        return nLength;
5003 2 mingarao
                }
5004 2 mingarao
5005 2 mingarao
5006 2 mingarao
                /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
5007 2 mingarao
                 * Section - Feature: Processing incidator
5008 2 mingarao
                 */
5009 2 mingarao
5010 2 mingarao
                /*
5011 2 mingarao
                 * Function: _fnFeatureHtmlProcessing
5012 2 mingarao
                 * Purpose:  Generate the node required for the processing node
5013 2 mingarao
                 * Returns:  node
5014 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
5015 2 mingarao
                 */
5016 2 mingarao
                function _fnFeatureHtmlProcessing ( oSettings )
5017 2 mingarao
                {
5018 2 mingarao
                        var nProcessing = document.createElement( 'div' );
5019 2 mingarao
5020 2 mingarao
                        if ( oSettings.sTableId !== '' && typeof oSettings.aanFeatures.r == "undefined" )
5021 2 mingarao
                        {
5022 2 mingarao
                                nProcessing.setAttribute( 'id', oSettings.sTableId+'_processing' );
5023 2 mingarao
                        }
5024 2 mingarao
                        nProcessing.innerHTML = oSettings.oLanguage.sProcessing;
5025 2 mingarao
                        nProcessing.className = oSettings.oClasses.sProcessing;
5026 2 mingarao
                        oSettings.nTable.parentNode.insertBefore( nProcessing, oSettings.nTable );
5027 2 mingarao
5028 2 mingarao
                        return nProcessing;
5029 2 mingarao
                }
5030 2 mingarao
5031 2 mingarao
                /*
5032 2 mingarao
                 * Function: _fnProcessingDisplay
5033 2 mingarao
                 * Purpose:  Display or hide the processing indicator
5034 2 mingarao
                 * Returns:  -
5035 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
5036 2 mingarao
                 *           bool:
5037 2 mingarao
                 *   true - show the processing indicator
5038 2 mingarao
                 *   false - don't show
5039 2 mingarao
                 */
5040 2 mingarao
                function _fnProcessingDisplay ( oSettings, bShow )
5041 2 mingarao
                {
5042 2 mingarao
                        if ( oSettings.oFeatures.bProcessing )
5043 2 mingarao
                        {
5044 2 mingarao
                                var an = oSettings.aanFeatures.r;
5045 2 mingarao
                                for ( var i=0, iLen=an.length ; i<iLen ; i++ )
5046 2 mingarao
                                {
5047 2 mingarao
                                        an[i].style.visibility = bShow ? "visible" : "hidden";
5048 2 mingarao
                                }
5049 2 mingarao
                        }
5050 2 mingarao
                }
5051 2 mingarao
5052 2 mingarao
5053 2 mingarao
                /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
5054 2 mingarao
                 * Section - Support functions
5055 2 mingarao
                 */
5056 2 mingarao
5057 2 mingarao
                /*
5058 2 mingarao
                 * Function: _fnVisibleToColumnIndex
5059 2 mingarao
                 * Purpose:  Covert the index of a visible column to the index in the data array (take account
5060 2 mingarao
                 *   of hidden columns)
5061 2 mingarao
                 * Returns:  int:i - the data index
5062 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
5063 2 mingarao
                 */
5064 2 mingarao
                function _fnVisibleToColumnIndex( oSettings, iMatch )
5065 2 mingarao
                {
5066 2 mingarao
                        var iColumn = -1;
5067 2 mingarao
5068 2 mingarao
                        for ( var i=0 ; i<oSettings.aoColumns.length ; i++ )
5069 2 mingarao
                        {
5070 2 mingarao
                                if ( oSettings.aoColumns[i].bVisible === true )
5071 2 mingarao
                                {
5072 2 mingarao
                                        iColumn++;
5073 2 mingarao
                                }
5074 2 mingarao
5075 2 mingarao
                                if ( iColumn == iMatch )
5076 2 mingarao
                                {
5077 2 mingarao
                                        return i;
5078 2 mingarao
                                }
5079 2 mingarao
                        }
5080 2 mingarao
5081 2 mingarao
                        return null;
5082 2 mingarao
                }
5083 2 mingarao
5084 2 mingarao
                /*
5085 2 mingarao
                 * Function: _fnColumnIndexToVisible
5086 2 mingarao
                 * Purpose:  Covert the index of an index in the data array and convert it to the visible
5087 2 mingarao
                 *   column index (take account of hidden columns)
5088 2 mingarao
                 * Returns:  int:i - the data index
5089 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
5090 2 mingarao
                 */
5091 2 mingarao
                function _fnColumnIndexToVisible( oSettings, iMatch )
5092 2 mingarao
                {
5093 2 mingarao
                        var iVisible = -1;
5094 2 mingarao
                        for ( var i=0 ; i<oSettings.aoColumns.length ; i++ )
5095 2 mingarao
                        {
5096 2 mingarao
                                if ( oSettings.aoColumns[i].bVisible === true )
5097 2 mingarao
                                {
5098 2 mingarao
                                        iVisible++;
5099 2 mingarao
                                }
5100 2 mingarao
5101 2 mingarao
                                if ( i == iMatch )
5102 2 mingarao
                                {
5103 2 mingarao
                                        return oSettings.aoColumns[i].bVisible === true ? iVisible : null;
5104 2 mingarao
                                }
5105 2 mingarao
                        }
5106 2 mingarao
5107 2 mingarao
                        return null;
5108 2 mingarao
                }
5109 2 mingarao
5110 2 mingarao
5111 2 mingarao
                /*
5112 2 mingarao
                 * Function: _fnNodeToDataIndex
5113 2 mingarao
                 * Purpose:  Take a TR element and convert it to an index in aoData
5114 2 mingarao
                 * Returns:  int:i - index if found, null if not
5115 2 mingarao
                 * Inputs:   object:s - dataTables settings object
5116 2 mingarao
                 *           node:n - the TR element to find
5117 2 mingarao
                 */
5118 2 mingarao
                function _fnNodeToDataIndex( s, n )
5119 2 mingarao
                {
5120 2 mingarao
                        var i, iLen;
5121 2 mingarao
5122 2 mingarao
                        /* Optimisation - see if the nodes which are currently visible match, since that is
5123 2 mingarao
                         * the most likely node to be asked for (a selector or event for example)
5124 2 mingarao
                         */
5125 2 mingarao
                        for ( i=s._iDisplayStart, iLen=s._iDisplayEnd ; i<iLen ; i++ )
5126 2 mingarao
                        {
5127 2 mingarao
                                if ( s.aoData[ s.aiDisplay[i] ].nTr == n )
5128 2 mingarao
                                {
5129 2 mingarao
                                        return s.aiDisplay[i];
5130 2 mingarao
                                }
5131 2 mingarao
                        }
5132 2 mingarao
5133 2 mingarao
                        /* Otherwise we are in for a slog through the whole data cache */
5134 2 mingarao
                        for ( i=0, iLen=s.aoData.length ; i<iLen ; i++ )
5135 2 mingarao
                        {
5136 2 mingarao
                                if ( s.aoData[i].nTr == n )
5137 2 mingarao
                                {
5138 2 mingarao
                                        return i;
5139 2 mingarao
                                }
5140 2 mingarao
                        }
5141 2 mingarao
                        return null;
5142 2 mingarao
                }
5143 2 mingarao
5144 2 mingarao
                /*
5145 2 mingarao
                 * Function: _fnVisbleColumns
5146 2 mingarao
                 * Purpose:  Get the number of visible columns
5147 2 mingarao
                 * Returns:  int:i - the number of visible columns
5148 2 mingarao
                 * Inputs:   object:oS - dataTables settings object
5149 2 mingarao
                 */
5150 2 mingarao
                function _fnVisbleColumns( oS )
5151 2 mingarao
                {
5152 2 mingarao
                        var iVis = 0;
5153 2 mingarao
                        for ( var i=0 ; i<oS.aoColumns.length ; i++ )
5154 2 mingarao
                        {
5155 2 mingarao
                                if ( oS.aoColumns[i].bVisible === true )
5156 2 mingarao
                                {
5157 2 mingarao
                                        iVis++;
5158 2 mingarao
                                }
5159 2 mingarao
                        }
5160 2 mingarao
                        return iVis;
5161 2 mingarao
                }
5162 2 mingarao
5163 2 mingarao
                /*
5164 2 mingarao
                 * Function: _fnCalculateEnd
5165 2 mingarao
                 * Purpose:  Rcalculate the end point based on the start point
5166 2 mingarao
                 * Returns:  -
5167 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
5168 2 mingarao
                 */
5169 2 mingarao
                function _fnCalculateEnd( oSettings )
5170 2 mingarao
                {
5171 2 mingarao
                        if ( oSettings.oFeatures.bPaginate === false )
5172 2 mingarao
                        {
5173 2 mingarao
                                oSettings._iDisplayEnd = oSettings.aiDisplay.length;
5174 2 mingarao
                        }
5175 2 mingarao
                        else
5176 2 mingarao
                        {
5177 2 mingarao
                                /* Set the end point of the display - based on how many elements there are
5178 2 mingarao
                                 * still to display
5179 2 mingarao
                                 */
5180 2 mingarao
                                if ( oSettings._iDisplayStart + oSettings._iDisplayLength > oSettings.aiDisplay.length ||
5181 2 mingarao
                                           oSettings._iDisplayLength == -1 )
5182 2 mingarao
                                {
5183 2 mingarao
                                        oSettings._iDisplayEnd = oSettings.aiDisplay.length;
5184 2 mingarao
                                }
5185 2 mingarao
                                else
5186 2 mingarao
                                {
5187 2 mingarao
                                        oSettings._iDisplayEnd = oSettings._iDisplayStart + oSettings._iDisplayLength;
5188 2 mingarao
                                }
5189 2 mingarao
                        }
5190 2 mingarao
                }
5191 2 mingarao
5192 2 mingarao
                /*
5193 2 mingarao
                 * Function: _fnConvertToWidth
5194 2 mingarao
                 * Purpose:  Convert a CSS unit width to pixels (e.g. 2em)
5195 2 mingarao
                 * Returns:  int:iWidth - width in pixels
5196 2 mingarao
                 * Inputs:   string:sWidth - width to be converted
5197 2 mingarao
                 *           node:nParent - parent to get the with for (required for
5198 2 mingarao
                 *             relative widths) - optional
5199 2 mingarao
                 */
5200 2 mingarao
                function _fnConvertToWidth ( sWidth, nParent )
5201 2 mingarao
                {
5202 2 mingarao
                        if ( !sWidth || sWidth === null || sWidth === '' )
5203 2 mingarao
                        {
5204 2 mingarao
                                return 0;
5205 2 mingarao
                        }
5206 2 mingarao
5207 2 mingarao
                        if ( typeof nParent == "undefined" )
5208 2 mingarao
                        {
5209 2 mingarao
                                nParent = document.getElementsByTagName('body')[0];
5210 2 mingarao
                        }
5211 2 mingarao
5212 2 mingarao
                        var iWidth;
5213 2 mingarao
                        var nTmp = document.createElement( "div" );
5214 2 mingarao
                        nTmp.style.width = sWidth;
5215 2 mingarao
5216 2 mingarao
                        nParent.appendChild( nTmp );
5217 2 mingarao
                        iWidth = nTmp.offsetWidth;
5218 2 mingarao
                        nParent.removeChild( nTmp );
5219 2 mingarao
5220 2 mingarao
                        return ( iWidth );
5221 2 mingarao
                }
5222 2 mingarao
5223 2 mingarao
                /*
5224 2 mingarao
                 * Function: _fnCalculateColumnWidths
5225 2 mingarao
                 * Purpose:  Calculate the width of columns for the table
5226 2 mingarao
                 * Returns:  -
5227 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
5228 2 mingarao
                 */
5229 2 mingarao
                function _fnCalculateColumnWidths ( oSettings )
5230 2 mingarao
                {
5231 2 mingarao
                        var iTableWidth = oSettings.nTable.offsetWidth;
5232 2 mingarao
                        var iUserInputs = 0;
5233 2 mingarao
                        var iTmpWidth;
5234 2 mingarao
                        var iVisibleColumns = 0;
5235 2 mingarao
                        var iColums = oSettings.aoColumns.length;
5236 2 mingarao
                        var i;
5237 2 mingarao
                        var oHeaders = $('th', oSettings.nTHead);
5238 2 mingarao
5239 2 mingarao
                        /* Convert any user input sizes into pixel sizes */
5240 2 mingarao
                        for ( i=0 ; i<iColums ; i++ )
5241 2 mingarao
                        {
5242 2 mingarao
                                if ( oSettings.aoColumns[i].bVisible )
5243 2 mingarao
                                {
5244 2 mingarao
                                        iVisibleColumns++;
5245 2 mingarao
5246 2 mingarao
                                        if ( oSettings.aoColumns[i].sWidth !== null )
5247 2 mingarao
                                        {
5248 2 mingarao
                                                iTmpWidth = _fnConvertToWidth( oSettings.aoColumns[i].sWidthOrig,
5249 2 mingarao
                                                        oSettings.nTable.parentNode );
5250 2 mingarao
                                                if ( iTmpWidth !== null )
5251 2 mingarao
                                                {
5252 2 mingarao
                                                        oSettings.aoColumns[i].sWidth = _fnStringToCss( iTmpWidth );
5253 2 mingarao
                                                }
5254 2 mingarao
5255 2 mingarao
                                                iUserInputs++;
5256 2 mingarao
                                        }
5257 2 mingarao
                                }
5258 2 mingarao
                        }
5259 2 mingarao
5260 2 mingarao
                        /* If the number of columns in the DOM equals the number that we have to process in
5261 2 mingarao
                         * DataTables, then we can use the offsets that are created by the web-browser. No custom
5262 2 mingarao
                         * sizes can be set in order for this to happen, nor scrolling used
5263 2 mingarao
                         */
5264 2 mingarao
                        if ( iColums == oHeaders.length && iUserInputs === 0 && iVisibleColumns == iColums &&
5265 2 mingarao
                                oSettings.oScroll.sX === "" && oSettings.oScroll.sY === "" )
5266 2 mingarao
                        {
5267 2 mingarao
                                for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
5268 2 mingarao
                                {
5269 2 mingarao
                                        iTmpWidth = $(oHeaders[i]).width();
5270 2 mingarao
                                        if ( iTmpWidth !== null )
5271 2 mingarao
                                        {
5272 2 mingarao
                                                oSettings.aoColumns[i].sWidth = _fnStringToCss( iTmpWidth );
5273 2 mingarao
                                        }
5274 2 mingarao
                                }
5275 2 mingarao
                        }
5276 2 mingarao
                        else
5277 2 mingarao
                        {
5278 2 mingarao
                                /* Otherwise we are going to have to do some calculations to get the width of each column.
5279 2 mingarao
                                 * Construct a 1 row table with the widest node in the data, and any user defined widths,
5280 2 mingarao
                                 * then insert it into the DOM and allow the browser to do all the hard work of
5281 2 mingarao
                                 * calculating table widths.
5282 2 mingarao
                                 */
5283 2 mingarao
                                var
5284 2 mingarao
                                        nCalcTmp = oSettings.nTable.cloneNode( false ),
5285 2 mingarao
                                        nBody = document.createElement( 'tbody' ),
5286 2 mingarao
                                        nTr = document.createElement( 'tr' ),
5287 2 mingarao
                                        nDivSizing;
5288 2 mingarao
5289 2 mingarao
                                nCalcTmp.removeAttribute( "id" );
5290 2 mingarao
                                nCalcTmp.appendChild( oSettings.nTHead.cloneNode(true) );
5291 2 mingarao
                                if ( oSettings.nTFoot !== null )
5292 2 mingarao
                                {
5293 2 mingarao
                                        nCalcTmp.appendChild( oSettings.nTFoot.cloneNode(true) );
5294 2 mingarao
                                        _fnApplyToChildren( function(n) {
5295 2 mingarao
                                                n.style.width = "";
5296 2 mingarao
                                        }, nCalcTmp.getElementsByTagName('tr') );
5297 2 mingarao
                                }
5298 2 mingarao
5299 2 mingarao
                                nCalcTmp.appendChild( nBody );
5300 2 mingarao
                                nBody.appendChild( nTr );
5301 2 mingarao
5302 2 mingarao
                                /* Remove any sizing that was previously applied by the styles */
5303 2 mingarao
                                var jqColSizing = $('thead th', nCalcTmp);
5304 2 mingarao
                                if ( jqColSizing.length === 0 )
5305 2 mingarao
                                {
5306 2 mingarao
                                        jqColSizing = $('tbody tr:eq(0)>td', nCalcTmp);
5307 2 mingarao
                                }
5308 2 mingarao
                                jqColSizing.each( function (i) {
5309 2 mingarao
                                        this.style.width = "";
5310 2 mingarao
5311 2 mingarao
                                        var iIndex = _fnVisibleToColumnIndex( oSettings, i );
5312 2 mingarao
                                        if ( iIndex !== null && oSettings.aoColumns[iIndex].sWidthOrig !== "" )
5313 2 mingarao
                                        {
5314 2 mingarao
                                                this.style.width = oSettings.aoColumns[iIndex].sWidthOrig;
5315 2 mingarao
                                        }
5316 2 mingarao
                                } );
5317 2 mingarao
5318 2 mingarao
                                /* Find the biggest td for each column and put it into the table */
5319 2 mingarao
                                for ( i=0 ; i<iColums ; i++ )
5320 2 mingarao
                                {
5321 2 mingarao
                                        if ( oSettings.aoColumns[i].bVisible )
5322 2 mingarao
                                        {
5323 2 mingarao
                                                var nTd = _fnGetWidestNode( oSettings, i );
5324 2 mingarao
                                                if ( nTd !== null )
5325 2 mingarao
                                                {
5326 2 mingarao
                                                        nTd = nTd.cloneNode(true);
5327 2 mingarao
                                                        nTr.appendChild( nTd );
5328 2 mingarao
                                                }
5329 2 mingarao
                                        }
5330 2 mingarao
                                }
5331 2 mingarao
5332 2 mingarao
                                /* Build the table and 'display' it */
5333 2 mingarao
                                var nWrapper = oSettings.nTable.parentNode;
5334 2 mingarao
                                nWrapper.appendChild( nCalcTmp );
5335 2 mingarao
5336 2 mingarao
                                /* When scrolling (X or Y) we want to set the width of the table as appropriate. However,
5337 2 mingarao
                                 * when not scrolling leave the table width as it is. This results in slightly different,
5338 2 mingarao
                                 * but I think correct behaviour
5339 2 mingarao
                                 */
5340 2 mingarao
                                if ( oSettings.oScroll.sX !== "" && oSettings.oScroll.sXInner !== "" )
5341 2 mingarao
                                {
5342 2 mingarao
                                        nCalcTmp.style.width = _fnStringToCss(oSettings.oScroll.sXInner);
5343 2 mingarao
                                }
5344 2 mingarao
                                else if ( oSettings.oScroll.sX !== "" )
5345 2 mingarao
                                {
5346 2 mingarao
                                        nCalcTmp.style.width = "";
5347 2 mingarao
                                        if ( $(nCalcTmp).width() < nWrapper.offsetWidth )
5348 2 mingarao
                                        {
5349 2 mingarao
                                                nCalcTmp.style.width = _fnStringToCss( nWrapper.offsetWidth );
5350 2 mingarao
                                        }
5351 2 mingarao
                                }
5352 2 mingarao
                                else if ( oSettings.oScroll.sY !== "" )
5353 2 mingarao
                                {
5354 2 mingarao
                                        nCalcTmp.style.width = _fnStringToCss( nWrapper.offsetWidth );
5355 2 mingarao
                                }
5356 2 mingarao
                                nCalcTmp.style.visibility = "hidden";
5357 2 mingarao
5358 2 mingarao
                                /* Scrolling considerations */
5359 2 mingarao
                                _fnScrollingWidthAdjust( oSettings, nCalcTmp );
5360 2 mingarao
5361 2 mingarao
                                /* Read the width's calculated by the browser and store them for use by the caller. We
5362 2 mingarao
                                 * first of all try to use the elements in the body, but it is possible that there are
5363 2 mingarao
                                 * no elements there, under which circumstances we use the header elements
5364 2 mingarao
                                 */
5365 2 mingarao
                                var oNodes = $("tbody tr:eq(0)>td", nCalcTmp);
5366 2 mingarao
                                if ( oNodes.length === 0 )
5367 2 mingarao
                                {
5368 2 mingarao
                                        oNodes = $("thead tr:eq(0)>th", nCalcTmp);
5369 2 mingarao
                                }
5370 2 mingarao
5371 2 mingarao
                                var iIndex, iCorrector = 0, iWidth;
5372 2 mingarao
                                for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
5373 2 mingarao
                                {
5374 2 mingarao
                                        if ( oSettings.aoColumns[i].bVisible )
5375 2 mingarao
                                        {
5376 2 mingarao
                                                iWidth = $(oNodes[iCorrector]).width();
5377 2 mingarao
                                                if ( iWidth !== null && iWidth > 0 )
5378 2 mingarao
                                                {
5379 2 mingarao
                                                        oSettings.aoColumns[i].sWidth = _fnStringToCss( iWidth );
5380 2 mingarao
                                                }
5381 2 mingarao
                                                iCorrector++;
5382 2 mingarao
                                        }
5383 2 mingarao
                                }
5384 2 mingarao
5385 2 mingarao
                                oSettings.nTable.style.width = _fnStringToCss( $(nCalcTmp).outerWidth() );
5386 2 mingarao
                                nCalcTmp.parentNode.removeChild( nCalcTmp );
5387 2 mingarao
                        }
5388 2 mingarao
                }
5389 2 mingarao
5390 2 mingarao
                /*
5391 2 mingarao
                 * Function: _fnScrollingWidthAdjust
5392 2 mingarao
                 * Purpose:  Adjust a table's width to take account of scrolling
5393 2 mingarao
                 * Returns:  -
5394 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
5395 2 mingarao
                 *           node:n - table node
5396 2 mingarao
                 */
5397 2 mingarao
                function _fnScrollingWidthAdjust ( oSettings, n )
5398 2 mingarao
                {
5399 2 mingarao
                        if ( oSettings.oScroll.sX === "" && oSettings.oScroll.sY !== "" )
5400 2 mingarao
                        {
5401 2 mingarao
                                /* When y-scrolling only, we want to remove the width of the scroll bar so the table
5402 2 mingarao
                                 * + scroll bar will fit into the area avaialble.
5403 2 mingarao
                                 */
5404 2 mingarao
                                var iOrigWidth = $(n).width();
5405 2 mingarao
                                n.style.width = _fnStringToCss( $(n).outerWidth()-oSettings.oScroll.iBarWidth );
5406 2 mingarao
                        }
5407 2 mingarao
                        else if ( oSettings.oScroll.sX !== "" )
5408 2 mingarao
                        {
5409 2 mingarao
                                /* When x-scrolling both ways, fix the table at it's current size, without adjusting */
5410 2 mingarao
                                n.style.width = _fnStringToCss( $(n).outerWidth() );
5411 2 mingarao
                        }
5412 2 mingarao
                }
5413 2 mingarao
5414 2 mingarao
                /*
5415 2 mingarao
                 * Function: _fnGetWidestNode
5416 2 mingarao
                 * Purpose:  Get the widest node
5417 2 mingarao
                 * Returns:  string: - max strlens for each column
5418 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
5419 2 mingarao
                 *           int:iCol - column of interest
5420 2 mingarao
                 *           boolean:bFast - Should we use fast (but non-accurate) calculation - optional,
5421 2 mingarao
                 *             default true
5422 2 mingarao
                 * Notes:    This operation is _expensive_ (!!!). It requires a lot of DOM interaction, but
5423 2 mingarao
                 *   this is the only way to reliably get the widest string. For example 'mmm' would be wider
5424 2 mingarao
                 *   than 'iiii' so we can't just ocunt characters. If this can be optimised it would be good
5425 2 mingarao
                 *   to do so!
5426 2 mingarao
                 */
5427 2 mingarao
                function _fnGetWidestNode( oSettings, iCol, bFast )
5428 2 mingarao
                {
5429 2 mingarao
                        /* Use fast not non-accurate calculate based on the strlen */
5430 2 mingarao
                        if ( typeof bFast == 'undefined' || bFast )
5431 2 mingarao
                        {
5432 2 mingarao
                                var iMaxLen = _fnGetMaxLenString( oSettings, iCol );
5433 2 mingarao
                                var iFastVis = _fnColumnIndexToVisible( oSettings, iCol);
5434 2 mingarao
                                if ( iMaxLen < 0 )
5435 2 mingarao
                                {
5436 2 mingarao
                                        return null;
5437 2 mingarao
                                }
5438 2 mingarao
                                return oSettings.aoData[iMaxLen].nTr.getElementsByTagName('td')[iFastVis];
5439 2 mingarao
                        }
5440 2 mingarao
5441 2 mingarao
                        /* Use the slow approach, but get high quality answers - note that this code is not actually
5442 2 mingarao
                         * used by DataTables by default. If you want to use it you can alter the call to
5443 2 mingarao
                         * _fnGetWidestNode to pass 'false' as the third argument
5444 2 mingarao
                         */
5445 2 mingarao
                        var
5446 2 mingarao
                                iMax = -1, i, iLen,
5447 2 mingarao
                                iMaxIndex = -1,
5448 2 mingarao
                                n = document.createElement('div');
5449 2 mingarao
5450 2 mingarao
                        n.style.visibility = "hidden";
5451 2 mingarao
                        n.style.position = "absolute";
5452 2 mingarao
                        document.body.appendChild( n );
5453 2 mingarao
5454 2 mingarao
                        for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
5455 2 mingarao
                        {
5456 2 mingarao
                                n.innerHTML = oSettings.aoData[i]._aData[iCol];
5457 2 mingarao
                                if ( n.offsetWidth > iMax )
5458 2 mingarao
                                {
5459 2 mingarao
                                        iMax = n.offsetWidth;
5460 2 mingarao
                                        iMaxIndex = i;
5461 2 mingarao
                                }
5462 2 mingarao
                        }
5463 2 mingarao
                        document.body.removeChild( n );
5464 2 mingarao
5465 2 mingarao
                        if ( iMaxIndex >= 0 )
5466 2 mingarao
                        {
5467 2 mingarao
                                var iVis = _fnColumnIndexToVisible( oSettings, iCol);
5468 2 mingarao
                                var nRet = oSettings.aoData[iMaxIndex].nTr.getElementsByTagName('td')[iVis];
5469 2 mingarao
                                if ( nRet )
5470 2 mingarao
                                {
5471 2 mingarao
                                        return nRet;
5472 2 mingarao
                                }
5473 2 mingarao
                        }
5474 2 mingarao
                        return null;
5475 2 mingarao
                }
5476 2 mingarao
5477 2 mingarao
                /*
5478 2 mingarao
                 * Function: _fnGetMaxLenString
5479 2 mingarao
                 * Purpose:  Get the maximum strlen for each data column
5480 2 mingarao
                 * Returns:  string: - max strlens for each column
5481 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
5482 2 mingarao
                 *           int:iCol - column of interest
5483 2 mingarao
                 */
5484 2 mingarao
                function _fnGetMaxLenString( oSettings, iCol )
5485 2 mingarao
                {
5486 2 mingarao
                        var iMax = -1;
5487 2 mingarao
                        var iMaxIndex = -1;
5488 2 mingarao
5489 2 mingarao
                        for ( var i=0 ; i<oSettings.aoData.length ; i++ )
5490 2 mingarao
                        {
5491 2 mingarao
                                var s = oSettings.aoData[i]._aData[iCol];
5492 2 mingarao
                                if ( s.length > iMax )
5493 2 mingarao
                                {
5494 2 mingarao
                                        iMax = s.length;
5495 2 mingarao
                                        iMaxIndex = i;
5496 2 mingarao
                                }
5497 2 mingarao
                        }
5498 2 mingarao
5499 2 mingarao
                        return iMaxIndex;
5500 2 mingarao
                }
5501 2 mingarao
5502 2 mingarao
                /*
5503 2 mingarao
                 * Function: _fnStringToCss
5504 2 mingarao
                 * Purpose:  Append a CSS unit (only if required) to a string
5505 2 mingarao
                 * Returns:  0 if match, 1 if length is different, 2 if no match
5506 2 mingarao
                 * Inputs:   array:aArray1 - first array
5507 2 mingarao
                 *           array:aArray2 - second array
5508 2 mingarao
                 */
5509 2 mingarao
                function _fnStringToCss( s )
5510 2 mingarao
                {
5511 2 mingarao
                        if ( s === null )
5512 2 mingarao
                        {
5513 2 mingarao
                                return "0px";
5514 2 mingarao
                        }
5515 2 mingarao
5516 2 mingarao
                        if ( typeof s == 'number' )
5517 2 mingarao
                        {
5518 2 mingarao
                                if ( s < 0 )
5519 2 mingarao
                                {
5520 2 mingarao
                                        return "0px";
5521 2 mingarao
                                }
5522 2 mingarao
                                return s+"px";
5523 2 mingarao
                        }
5524 2 mingarao
5525 2 mingarao
                        /* Check if the last character is not 0-9 */
5526 2 mingarao
                        var c = s.charCodeAt( s.length-1 );
5527 2 mingarao
                        if (c < 0x30 || c > 0x39)
5528 2 mingarao
                        {
5529 2 mingarao
                                return s;
5530 2 mingarao
                        }
5531 2 mingarao
                        return s+"px";
5532 2 mingarao
                }
5533 2 mingarao
5534 2 mingarao
                /*
5535 2 mingarao
                 * Function: _fnArrayCmp
5536 2 mingarao
                 * Purpose:  Compare two arrays
5537 2 mingarao
                 * Returns:  0 if match, 1 if length is different, 2 if no match
5538 2 mingarao
                 * Inputs:   array:aArray1 - first array
5539 2 mingarao
                 *           array:aArray2 - second array
5540 2 mingarao
                 */
5541 2 mingarao
                function _fnArrayCmp( aArray1, aArray2 )
5542 2 mingarao
                {
5543 2 mingarao
                        if ( aArray1.length != aArray2.length )
5544 2 mingarao
                        {
5545 2 mingarao
                                return 1;
5546 2 mingarao
                        }
5547 2 mingarao
5548 2 mingarao
                        for ( var i=0 ; i<aArray1.length ; i++ )
5549 2 mingarao
                        {
5550 2 mingarao
                                if ( aArray1[i] != aArray2[i] )
5551 2 mingarao
                                {
5552 2 mingarao
                                        return 2;
5553 2 mingarao
                                }
5554 2 mingarao
                        }
5555 2 mingarao
5556 2 mingarao
                        return 0;
5557 2 mingarao
                }
5558 2 mingarao
5559 2 mingarao
                /*
5560 2 mingarao
                 * Function: _fnDetectType
5561 2 mingarao
                 * Purpose:  Get the sort type based on an input string
5562 2 mingarao
                 * Returns:  string: - type (defaults to 'string' if no type can be detected)
5563 2 mingarao
                 * Inputs:   string:sData - data we wish to know the type of
5564 2 mingarao
                 * Notes:    This function makes use of the DataTables plugin objct _oExt
5565 2 mingarao
                 *   (.aTypes) such that new types can easily be added.
5566 2 mingarao
                 */
5567 2 mingarao
                function _fnDetectType( sData )
5568 2 mingarao
                {
5569 2 mingarao
                        var aTypes = _oExt.aTypes;
5570 2 mingarao
                        var iLen = aTypes.length;
5571 2 mingarao
5572 2 mingarao
                        for ( var i=0 ; i<iLen ; i++ )
5573 2 mingarao
                        {
5574 2 mingarao
                                var sType = aTypes[i]( sData );
5575 2 mingarao
                                if ( sType !== null )
5576 2 mingarao
                                {
5577 2 mingarao
                                        return sType;
5578 2 mingarao
                                }
5579 2 mingarao
                        }
5580 2 mingarao
5581 2 mingarao
                        return 'string';
5582 2 mingarao
                }
5583 2 mingarao
5584 2 mingarao
                /*
5585 2 mingarao
                 * Function: _fnSettingsFromNode
5586 2 mingarao
                 * Purpose:  Return the settings object for a particular table
5587 2 mingarao
                 * Returns:  object: Settings object - or null if not found
5588 2 mingarao
                 * Inputs:   node:nTable - table we are using as a dataTable
5589 2 mingarao
                 */
5590 2 mingarao
                function _fnSettingsFromNode ( nTable )
5591 2 mingarao
                {
5592 2 mingarao
                        for ( var i=0 ; i<_aoSettings.length ; i++ )
5593 2 mingarao
                        {
5594 2 mingarao
                                if ( _aoSettings[i].nTable == nTable )
5595 2 mingarao
                                {
5596 2 mingarao
                                        return _aoSettings[i];
5597 2 mingarao
                                }
5598 2 mingarao
                        }
5599 2 mingarao
5600 2 mingarao
                        return null;
5601 2 mingarao
                }
5602 2 mingarao
5603 2 mingarao
                /*
5604 2 mingarao
                 * Function: _fnGetDataMaster
5605 2 mingarao
                 * Purpose:  Return an array with the full table data
5606 2 mingarao
                 * Returns:  array array:aData - Master data array
5607 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
5608 2 mingarao
                 */
5609 2 mingarao
                function _fnGetDataMaster ( oSettings )
5610 2 mingarao
                {
5611 2 mingarao
                        var aData = [];
5612 2 mingarao
                        var iLen = oSettings.aoData.length;
5613 2 mingarao
                        for ( var i=0 ; i<iLen; i++ )
5614 2 mingarao
                        {
5615 2 mingarao
                                aData.push( oSettings.aoData[i]._aData );
5616 2 mingarao
                        }
5617 2 mingarao
                        return aData;
5618 2 mingarao
                }
5619 2 mingarao
5620 2 mingarao
                /*
5621 2 mingarao
                 * Function: _fnGetTrNodes
5622 2 mingarao
                 * Purpose:  Return an array with the TR nodes for the table
5623 2 mingarao
                 * Returns:  array: - TR array
5624 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
5625 2 mingarao
                 */
5626 2 mingarao
                function _fnGetTrNodes ( oSettings )
5627 2 mingarao
                {
5628 2 mingarao
                        var aNodes = [];
5629 2 mingarao
                        var iLen = oSettings.aoData.length;
5630 2 mingarao
                        for ( var i=0 ; i<iLen ; i++ )
5631 2 mingarao
                        {
5632 2 mingarao
                                aNodes.push( oSettings.aoData[i].nTr );
5633 2 mingarao
                        }
5634 2 mingarao
                        return aNodes;
5635 2 mingarao
                }
5636 2 mingarao
5637 2 mingarao
                /*
5638 2 mingarao
                 * Function: _fnGetTdNodes
5639 2 mingarao
                 * Purpose:  Return an array with the TD nodes for the table
5640 2 mingarao
                 * Returns:  array: - TD array
5641 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
5642 2 mingarao
                 */
5643 2 mingarao
                function _fnGetTdNodes ( oSettings )
5644 2 mingarao
                {
5645 2 mingarao
                        var nTrs = _fnGetTrNodes( oSettings );
5646 2 mingarao
                        var nTds = [], nTd;
5647 2 mingarao
                        var anReturn = [];
5648 2 mingarao
                        var iCorrector;
5649 2 mingarao
                        var iRow, iRows, iColumn, iColumns;
5650 2 mingarao
5651 2 mingarao
                        for ( iRow=0, iRows=nTrs.length ; iRow<iRows ; iRow++ )
5652 2 mingarao
                        {
5653 2 mingarao
                                nTds = [];
5654 2 mingarao
                                for ( iColumn=0, iColumns=nTrs[iRow].childNodes.length ; iColumn<iColumns ; iColumn++ )
5655 2 mingarao
                                {
5656 2 mingarao
                                        nTd = nTrs[iRow].childNodes[iColumn];
5657 2 mingarao
                                        if ( nTd.nodeName.toUpperCase() == "TD" )
5658 2 mingarao
                                        {
5659 2 mingarao
                                                nTds.push( nTd );
5660 2 mingarao
                                        }
5661 2 mingarao
                                }
5662 2 mingarao
5663 2 mingarao
                                iCorrector = 0;
5664 2 mingarao
                                for ( iColumn=0, iColumns=oSettings.aoColumns.length ; iColumn<iColumns ; iColumn++ )
5665 2 mingarao
                                {
5666 2 mingarao
                                        if ( oSettings.aoColumns[iColumn].bVisible )
5667 2 mingarao
                                        {
5668 2 mingarao
                                                anReturn.push( nTds[iColumn-iCorrector] );
5669 2 mingarao
                                        }
5670 2 mingarao
                                        else
5671 2 mingarao
                                        {
5672 2 mingarao
                                                anReturn.push( oSettings.aoData[iRow]._anHidden[iColumn] );
5673 2 mingarao
                                                iCorrector++;
5674 2 mingarao
                                        }
5675 2 mingarao
                                }
5676 2 mingarao
                        }
5677 2 mingarao
                        return anReturn;
5678 2 mingarao
                }
5679 2 mingarao
5680 2 mingarao
                /*
5681 2 mingarao
                 * Function: _fnEscapeRegex
5682 2 mingarao
                 * Purpose:  scape a string stuch that it can be used in a regular expression
5683 2 mingarao
                 * Returns:  string: - escaped string
5684 2 mingarao
                 * Inputs:   string:sVal - string to escape
5685 2 mingarao
                 */
5686 2 mingarao
                function _fnEscapeRegex ( sVal )
5687 2 mingarao
                {
5688 2 mingarao
                        var acEscape = [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^' ];
5689 2 mingarao
                  var reReplace = new RegExp( '(\\' + acEscape.join('|\\') + ')', 'g' );
5690 2 mingarao
                  return sVal.replace(reReplace, '\\$1');
5691 2 mingarao
                }
5692 2 mingarao
5693 2 mingarao
                /*
5694 2 mingarao
                 * Function: _fnDeleteIndex
5695 2 mingarao
                 * Purpose:  Take an array of integers (index array) and remove a target integer (value - not
5696 2 mingarao
                 *             the key!)
5697 2 mingarao
                 * Returns:  -
5698 2 mingarao
                 * Inputs:   a:array int - Index array to target
5699 2 mingarao
                 *           int:iTarget - value to find
5700 2 mingarao
                 */
5701 2 mingarao
                function _fnDeleteIndex( a, iTarget )
5702 2 mingarao
                {
5703 2 mingarao
                        var iTargetIndex = -1;
5704 2 mingarao
5705 2 mingarao
                        for ( var i=0, iLen=a.length ; i<iLen ; i++ )
5706 2 mingarao
                        {
5707 2 mingarao
                                if ( a[i] == iTarget )
5708 2 mingarao
                                {
5709 2 mingarao
                                        iTargetIndex = i;
5710 2 mingarao
                                }
5711 2 mingarao
                                else if ( a[i] > iTarget )
5712 2 mingarao
                                {
5713 2 mingarao
                                        a[i]--;
5714 2 mingarao
                                }
5715 2 mingarao
                        }
5716 2 mingarao
5717 2 mingarao
                        if ( iTargetIndex != -1 )
5718 2 mingarao
                        {
5719 2 mingarao
                                a.splice( iTargetIndex, 1 );
5720 2 mingarao
                        }
5721 2 mingarao
                }
5722 2 mingarao
5723 2 mingarao
                /*
5724 2 mingarao
                 * Function: _fnReOrderIndex
5725 2 mingarao
                 * Purpose:  Figure out how to reorder a display list
5726 2 mingarao
                 * Returns:  array int:aiReturn - index list for reordering
5727 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
5728 2 mingarao
                 */
5729 2 mingarao
                function _fnReOrderIndex ( oSettings, sColumns )
5730 2 mingarao
                {
5731 2 mingarao
                        var aColumns = sColumns.split(',');
5732 2 mingarao
                        var aiReturn = [];
5733 2 mingarao
5734 2 mingarao
                        for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
5735 2 mingarao
                        {
5736 2 mingarao
                                for ( var j=0 ; j<iLen ; j++ )
5737 2 mingarao
                                {
5738 2 mingarao
                                        if ( oSettings.aoColumns[i].sName == aColumns[j] )
5739 2 mingarao
                                        {
5740 2 mingarao
                                                aiReturn.push( j );
5741 2 mingarao
                                                break;
5742 2 mingarao
                                        }
5743 2 mingarao
                                }
5744 2 mingarao
                        }
5745 2 mingarao
5746 2 mingarao
                        return aiReturn;
5747 2 mingarao
                }
5748 2 mingarao
5749 2 mingarao
                /*
5750 2 mingarao
                 * Function: _fnColumnOrdering
5751 2 mingarao
                 * Purpose:  Get the column ordering that DataTables expects
5752 2 mingarao
                 * Returns:  string: - comma separated list of names
5753 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
5754 2 mingarao
                 */
5755 2 mingarao
                function _fnColumnOrdering ( oSettings )
5756 2 mingarao
                {
5757 2 mingarao
                        var sNames = '';
5758 2 mingarao
                        for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
5759 2 mingarao
                        {
5760 2 mingarao
                                sNames += oSettings.aoColumns[i].sName+',';
5761 2 mingarao
                        }
5762 2 mingarao
                        if ( sNames.length == iLen )
5763 2 mingarao
                        {
5764 2 mingarao
                                return "";
5765 2 mingarao
                        }
5766 2 mingarao
                        return sNames.slice(0, -1);
5767 2 mingarao
                }
5768 2 mingarao
5769 2 mingarao
                /*
5770 2 mingarao
                 * Function: _fnLog
5771 2 mingarao
                 * Purpose:  Log an error message
5772 2 mingarao
                 * Returns:  -
5773 2 mingarao
                 * Inputs:   int:iLevel - log error messages, or display them to the user
5774 2 mingarao
                 *           string:sMesg - error message
5775 2 mingarao
                 */
5776 2 mingarao
                function _fnLog( oSettings, iLevel, sMesg )
5777 2 mingarao
                {
5778 2 mingarao
                        var sAlert = oSettings.sTableId === "" ?
5779 2 mingarao
                                 "DataTables warning: " +sMesg :
5780 2 mingarao
                                 "DataTables warning (table id = '"+oSettings.sTableId+"'): " +sMesg;
5781 2 mingarao
5782 2 mingarao
                        if ( iLevel === 0 )
5783 2 mingarao
                        {
5784 2 mingarao
                                if ( _oExt.sErrMode == 'alert' )
5785 2 mingarao
                                {
5786 2 mingarao
                                        alert( sAlert );
5787 2 mingarao
                                }
5788 2 mingarao
                                else
5789 2 mingarao
                                {
5790 2 mingarao
                                        throw sAlert;
5791 2 mingarao
                                }
5792 2 mingarao
                                return;
5793 2 mingarao
                        }
5794 2 mingarao
                        else if ( typeof console != 'undefined' && typeof console.log != 'undefined' )
5795 2 mingarao
                        {
5796 2 mingarao
                                console.log( sAlert );
5797 2 mingarao
                        }
5798 2 mingarao
                }
5799 2 mingarao
5800 2 mingarao
                /*
5801 2 mingarao
                 * Function: _fnClearTable
5802 2 mingarao
                 * Purpose:  Nuke the table
5803 2 mingarao
                 * Returns:  -
5804 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
5805 2 mingarao
                 */
5806 2 mingarao
                function _fnClearTable( oSettings )
5807 2 mingarao
                {
5808 2 mingarao
                        oSettings.aoData.splice( 0, oSettings.aoData.length );
5809 2 mingarao
                        oSettings.aiDisplayMaster.splice( 0, oSettings.aiDisplayMaster.length );
5810 2 mingarao
                        oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length );
5811 2 mingarao
                        _fnCalculateEnd( oSettings );
5812 2 mingarao
                }
5813 2 mingarao
5814 2 mingarao
                /*
5815 2 mingarao
                 * Function: _fnSaveState
5816 2 mingarao
                 * Purpose:  Save the state of a table in a cookie such that the page can be reloaded
5817 2 mingarao
                 * Returns:  -
5818 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
5819 2 mingarao
                 */
5820 2 mingarao
                function _fnSaveState ( oSettings )
5821 2 mingarao
                {
5822 2 mingarao
                        if ( !oSettings.oFeatures.bStateSave || typeof oSettings.bDestroying != 'undefined' )
5823 2 mingarao
                        {
5824 2 mingarao
                                return;
5825 2 mingarao
                        }
5826 2 mingarao
5827 2 mingarao
                        /* Store the interesting variables */
5828 2 mingarao
                        var i, iLen, sTmp;
5829 2 mingarao
                        var sValue = "{";
5830 2 mingarao
                        sValue += '"iCreate":'+ new Date().getTime()+',';
5831 2 mingarao
                        sValue += '"iStart":'+ oSettings._iDisplayStart+',';
5832 2 mingarao
                        sValue += '"iEnd":'+ oSettings._iDisplayEnd+',';
5833 2 mingarao
                        sValue += '"iLength":'+ oSettings._iDisplayLength+',';
5834 2 mingarao
                        sValue += '"sFilter":"'+ encodeURIComponent(oSettings.oPreviousSearch.sSearch)+'",';
5835 2 mingarao
                        sValue += '"sFilterEsc":'+ !oSettings.oPreviousSearch.bRegex+',';
5836 2 mingarao
5837 2 mingarao
                        sValue += '"aaSorting":[ ';
5838 2 mingarao
                        for ( i=0 ; i<oSettings.aaSorting.length ; i++ )
5839 2 mingarao
                        {
5840 2 mingarao
                                sValue += '['+oSettings.aaSorting[i][0]+',"'+oSettings.aaSorting[i][1]+'"],';
5841 2 mingarao
                        }
5842 2 mingarao
                        sValue = sValue.substring(0, sValue.length-1);
5843 2 mingarao
                        sValue += "],";
5844 2 mingarao
5845 2 mingarao
                        sValue += '"aaSearchCols":[ ';
5846 2 mingarao
                        for ( i=0 ; i<oSettings.aoPreSearchCols.length ; i++ )
5847 2 mingarao
                        {
5848 2 mingarao
                                sValue += '["'+encodeURIComponent(oSettings.aoPreSearchCols[i].sSearch)+
5849 2 mingarao
                                        '",'+!oSettings.aoPreSearchCols[i].bRegex+'],';
5850 2 mingarao
                        }
5851 2 mingarao
                        sValue = sValue.substring(0, sValue.length-1);
5852 2 mingarao
                        sValue += "],";
5853 2 mingarao
5854 2 mingarao
                        sValue += '"abVisCols":[ ';
5855 2 mingarao
                        for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
5856 2 mingarao
                        {
5857 2 mingarao
                                sValue += oSettings.aoColumns[i].bVisible+",";
5858 2 mingarao
                        }
5859 2 mingarao
                        sValue = sValue.substring(0, sValue.length-1);
5860 2 mingarao
                        sValue += "]";
5861 2 mingarao
5862 2 mingarao
                        /* Save state from any plug-ins */
5863 2 mingarao
                        for ( i=0, iLen=oSettings.aoStateSave.length ; i<iLen ; i++ )
5864 2 mingarao
                        {
5865 2 mingarao
                                sTmp = oSettings.aoStateSave[i].fn( oSettings, sValue );
5866 2 mingarao
                                if ( sTmp !== "" )
5867 2 mingarao
                                {
5868 2 mingarao
                                        sValue = sTmp;
5869 2 mingarao
                                }
5870 2 mingarao
                        }
5871 2 mingarao
5872 2 mingarao
                        sValue += "}";
5873 2 mingarao
5874 2 mingarao
                        _fnCreateCookie( oSettings.sCookiePrefix+oSettings.sInstance, sValue,
5875 2 mingarao
                                oSettings.iCookieDuration, oSettings.sCookiePrefix, oSettings.fnCookieCallback );
5876 2 mingarao
                }
5877 2 mingarao
5878 2 mingarao
                /*
5879 2 mingarao
                 * Function: _fnLoadState
5880 2 mingarao
                 * Purpose:  Attempt to load a saved table state from a cookie
5881 2 mingarao
                 * Returns:  -
5882 2 mingarao
                 * Inputs:   object:oSettings - dataTables settings object
5883 2 mingarao
                 *           object:oInit - DataTables init object so we can override settings
5884 2 mingarao
                 */
5885 2 mingarao
                function _fnLoadState ( oSettings, oInit )
5886 2 mingarao
                {
5887 2 mingarao
                        if ( !oSettings.oFeatures.bStateSave )
5888 2 mingarao
                        {
5889 2 mingarao
                                return;
5890 2 mingarao
                        }
5891 2 mingarao
5892 2 mingarao
                        var oData, i, iLen;
5893 2 mingarao
                        var sData = _fnReadCookie( oSettings.sCookiePrefix+oSettings.sInstance );
5894 2 mingarao
                        if ( sData !== null && sData !== '' )
5895 2 mingarao
                        {
5896 2 mingarao
                                /* Try/catch the JSON eval - if it is bad then we ignore it - note that 1.7.0 and before
5897 2 mingarao
                                 * incorrectly used single quotes for some strings - hence the replace below
5898 2 mingarao
                                 */
5899 2 mingarao
                                try
5900 2 mingarao
                                {
5901 2 mingarao
                                        oData = (typeof $.parseJSON == 'function') ?
5902 2 mingarao
                                                $.parseJSON( sData.replace(/'/g, '"') ) : eval( '('+sData+')' );
5903 2 mingarao
                                }
5904 2 mingarao
                                catch( e )
5905 2 mingarao
                                {
5906 2 mingarao
                                        return;
5907 2 mingarao
                                }
5908 2 mingarao
5909 2 mingarao
                                /* Allow custom and plug-in manipulation functions to alter the data set which was
5910 2 mingarao
                                 * saved, and also reject any saved state by returning false
5911 2 mingarao
                                 */
5912 2 mingarao
                                for ( i=0, iLen=oSettings.aoStateLoad.length ; i<iLen ; i++ )
5913 2 mingarao
                                {
5914 2 mingarao
                                        if ( !oSettings.aoStateLoad[i].fn( oSettings, oData ) )
5915 2 mingarao
                                        {
5916 2 mingarao
                                                return;
5917 2 mingarao
                                        }
5918 2 mingarao
                                }
5919 2 mingarao
5920 2 mingarao
                                /* Store the saved state so it might be accessed at any time (particualrly a plug-in */
5921 2 mingarao
                                oSettings.oLoadedState = $.extend( true, {}, oData );
5922 2 mingarao
5923 2 mingarao
                                /* Restore key features */
5924 2 mingarao
                                oSettings._iDisplayStart = oData.iStart;
5925 2 mingarao
                                oSettings.iInitDisplayStart = oData.iStart;
5926 2 mingarao
                                oSettings._iDisplayEnd = oData.iEnd;
5927 2 mingarao
                                oSettings._iDisplayLength = oData.iLength;
5928 2 mingarao
                                oSettings.oPreviousSearch.sSearch = decodeURIComponent(oData.sFilter);
5929 2 mingarao
                                oSettings.aaSorting = oData.aaSorting.slice();
5930 2 mingarao
                                oSettings.saved_aaSorting = oData.aaSorting.slice();
5931 2 mingarao
5932 2 mingarao
                                /*
5933 2 mingarao
                                 * Search filtering - global reference added in 1.4.1
5934 2 mingarao
                                 * Note that we use a 'not' for the value of the regular expression indicator to maintain
5935 2 mingarao
                                 * compatibility with pre 1.7 versions, where this was basically inverted. Added in 1.7.0
5936 2 mingarao
                                 */
5937 2 mingarao
                                if ( typeof oData.sFilterEsc != 'undefined' )
5938 2 mingarao
                                {
5939 2 mingarao
                                        oSettings.oPreviousSearch.bRegex = !oData.sFilterEsc;
5940 2 mingarao
                                }
5941 2 mingarao
5942 2 mingarao
                                /* Column filtering - added in 1.5.0 beta 6 */
5943 2 mingarao
                                if ( typeof oData.aaSearchCols != 'undefined' )
5944 2 mingarao
                                {
5945 2 mingarao
                                        for ( i=0 ; i<oData.aaSearchCols.length ; i++ )
5946 2 mingarao
                                        {
5947 2 mingarao
                                                oSettings.aoPreSearchCols[i] = {
5948 2 mingarao
                                                        "sSearch": decodeURIComponent(oData.aaSearchCols[i][0]),
5949 2 mingarao
                                                        "bRegex": !oData.aaSearchCols[i][1]
5950 2 mingarao
                                                };
5951 2 mingarao
                                        }
5952 2 mingarao
                                }
5953 2 mingarao
5954 2 mingarao
                                /* Column visibility state - added in 1.5.0 beta 10 */
5955 2 mingarao
                                if ( typeof oData.abVisCols != 'undefined' )
5956 2 mingarao
                                {
5957 2 mingarao
                                        /* Pass back visibiliy settings to the init handler, but to do not here override
5958 2 mingarao
                                         * the init object that the user might have passed in
5959 2 mingarao
                                         */
5960 2 mingarao
                                        oInit.saved_aoColumns = [];
5961 2 mingarao
                                        for ( i=0 ; i<oData.abVisCols.length ; i++ )
5962 2 mingarao
                                        {
5963 2 mingarao
                                                oInit.saved_aoColumns[i] = {};
5964 2 mingarao
                                                oInit.saved_aoColumns[i].bVisible = oData.abVisCols[i];
5965 2 mingarao
                                        }
5966 2 mingarao
                                }
5967 2 mingarao
                        }
5968 2 mingarao
                }
5969 2 mingarao
5970 2 mingarao
                /*
5971 2 mingarao
                 * Function: _fnCreateCookie
5972 2 mingarao
                 * Purpose:  Create a new cookie with a value to store the state of a table
5973 2 mingarao
                 * Returns:  -
5974 2 mingarao
                 * Inputs:   string:sName - name of the cookie to create
5975 2 mingarao
                 *           string:sValue - the value the cookie should take
5976 2 mingarao
                 *           int:iSecs - duration of the cookie
5977 2 mingarao
                 *           string:sBaseName - sName is made up of the base + file name - this is the base
5978 2 mingarao
                 *           function:fnCallback - User definable function to modify the cookie
5979 2 mingarao
                 */
5980 2 mingarao
                function _fnCreateCookie ( sName, sValue, iSecs, sBaseName, fnCallback )
5981 2 mingarao
                {
5982 2 mingarao
                        var date = new Date();
5983 2 mingarao
                        date.setTime( date.getTime()+(iSecs*1000) );
5984 2 mingarao
5985 2 mingarao
                        /*
5986 2 mingarao
                         * Shocking but true - it would appear IE has major issues with having the path not having
5987 2 mingarao
                         * a trailing slash on it. We need the cookie to be available based on the path, so we
5988 2 mingarao
                         * have to append the file name to the cookie name. Appalling. Thanks to vex for adding the
5989 2 mingarao
                         * patch to use at least some of the path
5990 2 mingarao
                         */
5991 2 mingarao
                        var aParts = window.location.pathname.split('/');
5992 2 mingarao
                        var sNameFile = sName + '_' + aParts.pop().replace(/[\/:]/g,"").toLowerCase();
5993 2 mingarao
                        var sFullCookie, oData;
5994 2 mingarao
5995 2 mingarao
                        if ( fnCallback !== null )
5996 2 mingarao
                        {
5997 2 mingarao
                                oData = (typeof $.parseJSON == 'function') ?
5998 2 mingarao
                                        $.parseJSON( sValue ) : eval( '('+sValue+')' );
5999 2 mingarao
                                sFullCookie = fnCallback( sNameFile, oData, date.toGMTString(),
6000 2 mingarao
                                        aParts.join('/')+"/" );
6001 2 mingarao
                        }
6002 2 mingarao
                        else
6003 2 mingarao
                        {
6004 2 mingarao
                                sFullCookie = sNameFile + "=" + encodeURIComponent(sValue) +
6005 2 mingarao
                                        "; expires=" + date.toGMTString() +"; path=" + aParts.join('/')+"/";
6006 2 mingarao
                        }
6007 2 mingarao
6008 2 mingarao
                        /* Are we going to go over the cookie limit of 4KiB? If so, try to delete a cookies
6009 2 mingarao
                         * belonging to DataTables. This is FAR from bullet proof
6010 2 mingarao
                         */
6011 2 mingarao
                        var sOldName="", iOldTime=9999999999999;
6012 2 mingarao
                        var iLength = _fnReadCookie( sNameFile )!==null ? document.cookie.length :
6013 2 mingarao
                                sFullCookie.length + document.cookie.length;
6014 2 mingarao
6015 2 mingarao
                        if ( iLength+10 > 4096 ) /* Magic 10 for padding */
6016 2 mingarao
                        {
6017 2 mingarao
                                var aCookies =document.cookie.split(';');
6018 2 mingarao
                                for ( var i=0, iLen=aCookies.length ; i<iLen ; i++ )
6019 2 mingarao
                                {
6020 2 mingarao
                                        if ( aCookies[i].indexOf( sBaseName ) != -1 )
6021 2 mingarao
                                        {
6022 2 mingarao
                                                /* It's a DataTables cookie, so eval it and check the time stamp */
6023 2 mingarao
                                                var aSplitCookie = aCookies[i].split('=');
6024 2 mingarao
                                                try { oData = eval( '('+decodeURIComponent(aSplitCookie[1])+')' ); }
6025 2 mingarao
                                                catch( e ) { continue; }
6026 2 mingarao
6027 2 mingarao
                                                if ( typeof oData.iCreate != 'undefined' && oData.iCreate < iOldTime )
6028 2 mingarao
                                                {
6029 2 mingarao
                                                        sOldName = aSplitCookie[0];
6030 2 mingarao
                                                        iOldTime = oData.iCreate;
6031 2 mingarao
                                                }
6032 2 mingarao
                                        }
6033 2 mingarao
                                }
6034 2 mingarao
6035 2 mingarao
                                if ( sOldName !== "" )
6036 2 mingarao
                                {
6037 2 mingarao
                                        document.cookie = sOldName+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path="+
6038 2 mingarao
                                                aParts.join('/') + "/";
6039 2 mingarao
                                }
6040 2 mingarao
                        }
6041 2 mingarao
6042 2 mingarao
                        document.cookie = sFullCookie;
6043 2 mingarao
                }
6044 2 mingarao
6045 2 mingarao
                /*
6046 2 mingarao
                 * Function: _fnReadCookie
6047 2 mingarao
                 * Purpose:  Read an old cookie to get a cookie with an old table state
6048 2 mingarao
                 * Returns:  string: - contents of the cookie - or null if no cookie with that name found
6049 2 mingarao
                 * Inputs:   string:sName - name of the cookie to read
6050 2 mingarao
                 */
6051 2 mingarao
                function _fnReadCookie ( sName )
6052 2 mingarao
                {
6053 2 mingarao
                        var
6054 2 mingarao
                                aParts = window.location.pathname.split('/'),
6055 2 mingarao
                                sNameEQ = sName + '_' + aParts[aParts.length-1].replace(/[\/:]/g,"").toLowerCase() + '=',
6056 2 mingarao
                                 sCookieContents = document.cookie.split(';');
6057 2 mingarao
6058 2 mingarao
                        for( var i=0 ; i<sCookieContents.length ; i++ )
6059 2 mingarao
                        {
6060 2 mingarao
                                var c = sCookieContents[i];
6061 2 mingarao
6062 2 mingarao
                                while (c.charAt(0)==' ')
6063 2 mingarao
                                {
6064 2 mingarao
                                        c = c.substring(1,c.length);
6065 2 mingarao
                                }
6066 2 mingarao
6067 2 mingarao
                                if (c.indexOf(sNameEQ) === 0)
6068 2 mingarao
                                {
6069 2 mingarao
                                        return decodeURIComponent( c.substring(sNameEQ.length,c.length) );
6070 2 mingarao
                                }
6071 2 mingarao
                        }
6072 2 mingarao
                        return null;
6073 2 mingarao
                }
6074 2 mingarao
6075 2 mingarao
                /*
6076 2 mingarao
                 * Function: _fnGetUniqueThs
6077 2 mingarao
                 * Purpose:  Get an array of unique th elements, one for each column
6078 2 mingarao
                 * Returns:  array node:aReturn - list of unique ths
6079 2 mingarao
                 * Inputs:   node:nThead - The thead element for the table
6080 2 mingarao
                 */
6081 2 mingarao
                function _fnGetUniqueThs ( nThead )
6082 2 mingarao
                {
6083 2 mingarao
                        var nTrs = nThead.getElementsByTagName('tr');
6084 2 mingarao
6085 2 mingarao
                        /* Nice simple case */
6086 2 mingarao
                        if ( nTrs.length == 1 )
6087 2 mingarao
                        {
6088 2 mingarao
                                return nTrs[0].getElementsByTagName('th');
6089 2 mingarao
                        }
6090 2 mingarao
6091 2 mingarao
                        /* Otherwise we need to figure out the layout array to get the nodes */
6092 2 mingarao
                        var aLayout = [], aReturn = [];
6093 2 mingarao
                        var ROWSPAN = 2, COLSPAN = 3, TDELEM = 4;
6094 2 mingarao
                        var i, j, k, iLen, jLen, iColumnShifted;
6095 2 mingarao
                        var fnShiftCol = function ( a, i, j ) {
6096 2 mingarao
                                while ( typeof a[i][j] != 'undefined' ) {
6097 2 mingarao
                                        j++;
6098 2 mingarao
                                }
6099 2 mingarao
                                return j;
6100 2 mingarao
                        };
6101 2 mingarao
                        var fnAddRow = function ( i ) {
6102 2 mingarao
                                if ( typeof aLayout[i] == 'undefined' ) {
6103 2 mingarao
                                        aLayout[i] = [];
6104 2 mingarao
                                }
6105 2 mingarao
                        };
6106 2 mingarao
6107 2 mingarao
                        /* Calculate a layout array */
6108 2 mingarao
                        for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
6109 2 mingarao
                        {
6110 2 mingarao
                                fnAddRow( i );
6111 2 mingarao
                                var iColumn = 0;
6112 2 mingarao
                                var nTds = [];
6113 2 mingarao
6114 2 mingarao
                                for ( j=0, jLen=nTrs[i].childNodes.length ; j<jLen ; j++ )
6115 2 mingarao
                                {
6116 2 mingarao
                                        if ( nTrs[i].childNodes[j].nodeName.toUpperCase() == "TD" ||
6117 2 mingarao
                                             nTrs[i].childNodes[j].nodeName.toUpperCase() == "TH" )
6118 2 mingarao
                                        {
6119 2 mingarao
                                                nTds.push( nTrs[i].childNodes[j] );
6120 2 mingarao
                                        }
6121 2 mingarao
                                }
6122 2 mingarao
6123 2 mingarao
                                for ( j=0, jLen=nTds.length ; j<jLen ; j++ )
6124 2 mingarao
                                {
6125 2 mingarao
                                        var iColspan = nTds[j].getAttribute('colspan') * 1;
6126 2 mingarao
                                        var iRowspan = nTds[j].getAttribute('rowspan') * 1;
6127 2 mingarao
6128 2 mingarao
                                        if ( !iColspan || iColspan===0 || iColspan===1 )
6129 2 mingarao
                                        {
6130 2 mingarao
                                                iColumnShifted = fnShiftCol( aLayout, i, iColumn );
6131 2 mingarao
                                                aLayout[i][iColumnShifted] = (nTds[j].nodeName.toUpperCase()=="TD") ? TDELEM : nTds[j];
6132 2 mingarao
                                                if ( iRowspan || iRowspan===0 || iRowspan===1 )
6133 2 mingarao
                                                {
6134 2 mingarao
                                                        for ( k=1 ; k<iRowspan ; k++ )
6135 2 mingarao
                                                        {
6136 2 mingarao
                                                                fnAddRow( i+k );
6137 2 mingarao
                                                                aLayout[i+k][iColumnShifted] = ROWSPAN;
6138 2 mingarao
                                                        }
6139 2 mingarao
                                                }
6140 2 mingarao
                                                iColumn++;
6141 2 mingarao
                                        }
6142 2 mingarao
                                        else
6143 2 mingarao
                                        {
6144 2 mingarao
                                                iColumnShifted = fnShiftCol( aLayout, i, iColumn );
6145 2 mingarao
                                                for ( k=0 ; k<iColspan ; k++ )
6146 2 mingarao
                                                {
6147 2 mingarao
                                                        aLayout[i][iColumnShifted+k] = COLSPAN;
6148 2 mingarao
                                                }
6149 2 mingarao
                                                iColumn += iColspan;
6150 2 mingarao
                                        }
6151 2 mingarao
                                }
6152 2 mingarao
                        }
6153 2 mingarao
6154 2 mingarao
                        /* Convert the layout array into a node array */
6155 2 mingarao
                        for ( i=0, iLen=aLayout.length ; i<iLen ; i++ )
6156 2 mingarao
                        {
6157 2 mingarao
                                for ( j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
6158 2 mingarao
                                {
6159 2 mingarao
                                        if ( typeof aLayout[i][j] == 'object' )
6160 2 mingarao
                                        {
6161 2 mingarao
                                                aReturn[j] = aLayout[i][j];
6162 2 mingarao
                                        }
6163 2 mingarao
                                }
6164 2 mingarao
                        }
6165 2 mingarao
6166 2 mingarao
                        return aReturn;
6167 2 mingarao
                }
6168 2 mingarao
6169 2 mingarao
                /*
6170 2 mingarao
                 * Function: _fnScrollBarWidth
6171 2 mingarao
                 * Purpose:  Get the width of a scroll bar in this browser being used
6172 2 mingarao
                 * Returns:  int: - width in pixels
6173 2 mingarao
                 * Inputs:   -
6174 2 mingarao
                 * Notes:    All credit for this function belongs to Alexandre Gomes. Thanks for sharing!
6175 2 mingarao
                 *   http://www.alexandre-gomes.com/?p=115
6176 2 mingarao
                 */
6177 2 mingarao
                function _fnScrollBarWidth ()
6178 2 mingarao
                {
6179 2 mingarao
                        var inner = document.createElement('p');
6180 2 mingarao
                        var style = inner.style;
6181 2 mingarao
                        style.width = "100%";
6182 2 mingarao
                        style.height = "200px";
6183 2 mingarao
6184 2 mingarao
                        var outer = document.createElement('div');
6185 2 mingarao
                        style = outer.style;
6186 2 mingarao
                        style.position = "absolute";
6187 2 mingarao
                        style.top = "0px";
6188 2 mingarao
                        style.left = "0px";
6189 2 mingarao
                        style.visibility = "hidden";
6190 2 mingarao
                        style.width = "200px";
6191 2 mingarao
                        style.height = "150px";
6192 2 mingarao
                        style.overflow = "hidden";
6193 2 mingarao
                        outer.appendChild(inner);
6194 2 mingarao
6195 2 mingarao
                        document.body.appendChild(outer);
6196 2 mingarao
                        var w1 = inner.offsetWidth;
6197 2 mingarao
                        outer.style.overflow = 'scroll';
6198 2 mingarao
                        var w2 = inner.offsetWidth;
6199 2 mingarao
                        if ( w1 == w2 )
6200 2 mingarao
                        {
6201 2 mingarao
                                w2 = outer.clientWidth;
6202 2 mingarao
                        }
6203 2 mingarao
6204 2 mingarao
                        document.body.removeChild(outer);
6205 2 mingarao
                        return (w1 - w2);
6206 2 mingarao
                }
6207 2 mingarao
6208 2 mingarao
                /*
6209 2 mingarao
                 * Function: _fnApplyToChildren
6210 2 mingarao
                 * Purpose:  Apply a given function to the display child nodes of an element array (typically
6211 2 mingarao
                 *   TD children of TR rows
6212 2 mingarao
                 * Returns:  - (done by reference)
6213 2 mingarao
                 * Inputs:   function:fn - Method to apply to the objects
6214 2 mingarao
                 *           array nodes:an1 - List of elements to look through for display children
6215 2 mingarao
                 *           array nodes:an2 - Another list (identical structure to the first) - optional
6216 2 mingarao
                 */
6217 2 mingarao
                function _fnApplyToChildren( fn, an1, an2 )
6218 2 mingarao
                {
6219 2 mingarao
                        for ( var i=0, iLen=an1.length ; i<iLen ; i++ )
6220 2 mingarao
                        {
6221 2 mingarao
                                for ( var j=0, jLen=an1[i].childNodes.length ; j<jLen ; j++ )
6222 2 mingarao
                                {
6223 2 mingarao
                                        if ( an1[i].childNodes[j].nodeType == 1 )
6224 2 mingarao
                                        {
6225 2 mingarao
                                                if ( typeof an2 != 'undefined' )
6226 2 mingarao
                                                {
6227 2 mingarao
                                                        fn( an1[i].childNodes[j], an2[i].childNodes[j] );
6228 2 mingarao
                                                }
6229 2 mingarao
                                                else
6230 2 mingarao
                                                {
6231 2 mingarao
                                                        fn( an1[i].childNodes[j] );
6232 2 mingarao
                                                }
6233 2 mingarao
                                        }
6234 2 mingarao
                                }
6235 2 mingarao
                        }
6236 2 mingarao
                }
6237 2 mingarao
6238 2 mingarao
                /*
6239 2 mingarao
                 * Function: _fnMap
6240 2 mingarao
                 * Purpose:  See if a property is defined on one object, if so assign it to the other object
6241 2 mingarao
                 * Returns:  - (done by reference)
6242 2 mingarao
                 * Inputs:   object:oRet - target object
6243 2 mingarao
                 *           object:oSrc - source object
6244 2 mingarao
                 *           string:sName - property
6245 2 mingarao
                 *           string:sMappedName - name to map too - optional, sName used if not given
6246 2 mingarao
                 */
6247 2 mingarao
                function _fnMap( oRet, oSrc, sName, sMappedName )
6248 2 mingarao
                {
6249 2 mingarao
                        if ( typeof sMappedName == 'undefined' )
6250 2 mingarao
                        {
6251 2 mingarao
                                sMappedName = sName;
6252 2 mingarao
                        }
6253 2 mingarao
                        if ( typeof oSrc[sName] != 'undefined' )
6254 2 mingarao
                        {
6255 2 mingarao
                                oRet[sMappedName] = oSrc[sName];
6256 2 mingarao
                        }
6257 2 mingarao
                }
6258 2 mingarao
6259 2 mingarao
                /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
6260 2 mingarao
                 * Section - API
6261 2 mingarao
                 *
6262 2 mingarao
                 * I'm not overly happy with this solution - I'd much rather that there was a way of getting
6263 2 mingarao
                 * a list of all the private functions and do what we need to dynamically - but that doesn't
6264 2 mingarao
                 * appear to be possible. Bonkers. A better solution would be to provide a 'bind' type object
6265 2 mingarao
                 * To do - bind type method in DTs 2.x.
6266 2 mingarao
                 */
6267 2 mingarao
                this.oApi._fnExternApiFunc = _fnExternApiFunc;
6268 2 mingarao
                this.oApi._fnInitalise = _fnInitalise;
6269 2 mingarao
                this.oApi._fnLanguageProcess = _fnLanguageProcess;
6270 2 mingarao
                this.oApi._fnAddColumn = _fnAddColumn;
6271 2 mingarao
                this.oApi._fnColumnOptions = _fnColumnOptions;
6272 2 mingarao
                this.oApi._fnAddData = _fnAddData;
6273 2 mingarao
                this.oApi._fnGatherData = _fnGatherData;
6274 2 mingarao
                this.oApi._fnDrawHead = _fnDrawHead;
6275 2 mingarao
                this.oApi._fnDraw = _fnDraw;
6276 2 mingarao
                this.oApi._fnReDraw = _fnReDraw;
6277 2 mingarao
                this.oApi._fnAjaxUpdate = _fnAjaxUpdate;
6278 2 mingarao
                this.oApi._fnAjaxUpdateDraw = _fnAjaxUpdateDraw;
6279 2 mingarao
                this.oApi._fnAddOptionsHtml = _fnAddOptionsHtml;
6280 2 mingarao
                this.oApi._fnFeatureHtmlTable = _fnFeatureHtmlTable;
6281 2 mingarao
                this.oApi._fnScrollDraw = _fnScrollDraw;
6282 2 mingarao
                this.oApi._fnAjustColumnSizing = _fnAjustColumnSizing;
6283 2 mingarao
                this.oApi._fnFeatureHtmlFilter = _fnFeatureHtmlFilter;
6284 2 mingarao
                this.oApi._fnFilterComplete = _fnFilterComplete;
6285 2 mingarao
                this.oApi._fnFilterCustom = _fnFilterCustom;
6286 2 mingarao
                this.oApi._fnFilterColumn = _fnFilterColumn;
6287 2 mingarao
                this.oApi._fnFilter = _fnFilter;
6288 2 mingarao
                this.oApi._fnBuildSearchArray = _fnBuildSearchArray;
6289 2 mingarao
                this.oApi._fnBuildSearchRow = _fnBuildSearchRow;
6290 2 mingarao
                this.oApi._fnFilterCreateSearch = _fnFilterCreateSearch;
6291 2 mingarao
                this.oApi._fnDataToSearch = _fnDataToSearch;
6292 2 mingarao
                this.oApi._fnSort = _fnSort;
6293 2 mingarao
                this.oApi._fnSortAttachListener = _fnSortAttachListener;
6294 2 mingarao
                this.oApi._fnSortingClasses = _fnSortingClasses;
6295 2 mingarao
                this.oApi._fnFeatureHtmlPaginate = _fnFeatureHtmlPaginate;
6296 2 mingarao
                this.oApi._fnPageChange = _fnPageChange;
6297 2 mingarao
                this.oApi._fnFeatureHtmlInfo = _fnFeatureHtmlInfo;
6298 2 mingarao
                this.oApi._fnUpdateInfo = _fnUpdateInfo;
6299 2 mingarao
                this.oApi._fnFeatureHtmlLength = _fnFeatureHtmlLength;
6300 2 mingarao
                this.oApi._fnFeatureHtmlProcessing = _fnFeatureHtmlProcessing;
6301 2 mingarao
                this.oApi._fnProcessingDisplay = _fnProcessingDisplay;
6302 2 mingarao
                this.oApi._fnVisibleToColumnIndex = _fnVisibleToColumnIndex;
6303 2 mingarao
                this.oApi._fnColumnIndexToVisible = _fnColumnIndexToVisible;
6304 2 mingarao
                this.oApi._fnNodeToDataIndex = _fnNodeToDataIndex;
6305 2 mingarao
                this.oApi._fnVisbleColumns = _fnVisbleColumns;
6306 2 mingarao
                this.oApi._fnCalculateEnd = _fnCalculateEnd;
6307 2 mingarao
                this.oApi._fnConvertToWidth = _fnConvertToWidth;
6308 2 mingarao
                this.oApi._fnCalculateColumnWidths = _fnCalculateColumnWidths;
6309 2 mingarao
                this.oApi._fnScrollingWidthAdjust = _fnScrollingWidthAdjust;
6310 2 mingarao
                this.oApi._fnGetWidestNode = _fnGetWidestNode;
6311 2 mingarao
                this.oApi._fnGetMaxLenString = _fnGetMaxLenString;
6312 2 mingarao
                this.oApi._fnStringToCss = _fnStringToCss;
6313 2 mingarao
                this.oApi._fnArrayCmp = _fnArrayCmp;
6314 2 mingarao
                this.oApi._fnDetectType = _fnDetectType;
6315 2 mingarao
                this.oApi._fnSettingsFromNode = _fnSettingsFromNode;
6316 2 mingarao
                this.oApi._fnGetDataMaster = _fnGetDataMaster;
6317 2 mingarao
                this.oApi._fnGetTrNodes = _fnGetTrNodes;
6318 2 mingarao
                this.oApi._fnGetTdNodes = _fnGetTdNodes;
6319 2 mingarao
                this.oApi._fnEscapeRegex = _fnEscapeRegex;
6320 2 mingarao
                this.oApi._fnDeleteIndex = _fnDeleteIndex;
6321 2 mingarao
                this.oApi._fnReOrderIndex = _fnReOrderIndex;
6322 2 mingarao
                this.oApi._fnColumnOrdering = _fnColumnOrdering;
6323 2 mingarao
                this.oApi._fnLog = _fnLog;
6324 2 mingarao
                this.oApi._fnClearTable = _fnClearTable;
6325 2 mingarao
                this.oApi._fnSaveState = _fnSaveState;
6326 2 mingarao
                this.oApi._fnLoadState = _fnLoadState;
6327 2 mingarao
                this.oApi._fnCreateCookie = _fnCreateCookie;
6328 2 mingarao
                this.oApi._fnReadCookie = _fnReadCookie;
6329 2 mingarao
                this.oApi._fnGetUniqueThs = _fnGetUniqueThs;
6330 2 mingarao
                this.oApi._fnScrollBarWidth = _fnScrollBarWidth;
6331 2 mingarao
                this.oApi._fnApplyToChildren = _fnApplyToChildren;
6332 2 mingarao
                this.oApi._fnMap = _fnMap;
6333 2 mingarao
6334 2 mingarao
6335 2 mingarao
                /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
6336 2 mingarao
                 * Section - Constructor
6337 2 mingarao
                 */
6338 2 mingarao
6339 2 mingarao
                /* Want to be able to reference "this" inside the this.each function */
6340 2 mingarao
                var _that = this;
6341 2 mingarao
                return this.each(function()
6342 2 mingarao
                {
6343 2 mingarao
                        var i=0, iLen, j, jLen, k, kLen;
6344 2 mingarao
6345 2 mingarao
                        /* Check to see if we are re-initalising a table */
6346 2 mingarao
                        for ( i=0, iLen=_aoSettings.length ; i<iLen ; i++ )
6347 2 mingarao
                        {
6348 2 mingarao
                                /* Base check on table node */
6349 2 mingarao
                                if ( _aoSettings[i].nTable == this )
6350 2 mingarao
                                {
6351 2 mingarao
                                        if ( typeof oInit == 'undefined' ||
6352 2 mingarao
                                           ( typeof oInit.bRetrieve != 'undefined' && oInit.bRetrieve === true ) )
6353 2 mingarao
                                        {
6354 2 mingarao
                                                return _aoSettings[i].oInstance;
6355 2 mingarao
                                        }
6356 2 mingarao
                                        else if ( typeof oInit.bDestroy != 'undefined' && oInit.bDestroy === true )
6357 2 mingarao
                                        {
6358 2 mingarao
                                                _aoSettings[i].oInstance.fnDestroy();
6359 2 mingarao
                                                break;
6360 2 mingarao
                                        }
6361 2 mingarao
                                        else
6362 2 mingarao
                                        {
6363 2 mingarao
                                                _fnLog( _aoSettings[i], 0, "Cannot reinitialise DataTable.\n\n"+
6364 2 mingarao
                                                        "To retrieve the DataTables object for this table, please pass either no arguments "+
6365 2 mingarao
                                                        "to the dataTable() function, or set bRetrieve to true. Alternatively, to destory "+
6366 2 mingarao
                                                        "the old table and create a new one, set bDestroy to true (note that a lot of "+
6367 2 mingarao
                                                        "changes to the configuration can be made through the API which is usually much "+
6368 2 mingarao
                                                        "faster)." );
6369 2 mingarao
                                                return;
6370 2 mingarao
                                        }
6371 2 mingarao
                                }
6372 2 mingarao
6373 2 mingarao
                                /* If the element we are initialising has the same ID as a table which was previously
6374 2 mingarao
                                 * initialised, but the table nodes don't match (from before) then we destory the old
6375 2 mingarao
                                 * instance by simply deleting it. This is under the assumption that the table has been
6376 2 mingarao
                                 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
6377 2 mingarao
                                 */
6378 2 mingarao
                                if ( _aoSettings[i].sTableId !== "" && _aoSettings[i].sTableId == this.getAttribute('id') )
6379 2 mingarao
                                {
6380 2 mingarao
                                        _aoSettings.splice( i, 1 );
6381 2 mingarao
                                        break;
6382 2 mingarao
                                }
6383 2 mingarao
                        }
6384 2 mingarao
6385 2 mingarao
                        /* Make a complete and independent copy of the settings object */
6386 2 mingarao
                        var oSettings = new classSettings();
6387 2 mingarao
                        _aoSettings.push( oSettings );
6388 2 mingarao
6389 2 mingarao
                        var bInitHandedOff = false;
6390 2 mingarao
                        var bUsePassedData = false;
6391 2 mingarao
6392 2 mingarao
                        /* Set the id */
6393 2 mingarao
                        var sId = this.getAttribute( 'id' );
6394 2 mingarao
                        if ( sId !== null )
6395 2 mingarao
                        {
6396 2 mingarao
                                oSettings.sTableId = sId;
6397 2 mingarao
                                oSettings.sInstance = sId;
6398 2 mingarao
                        }
6399 2 mingarao
                        else
6400 2 mingarao
                        {
6401 2 mingarao
                                oSettings.sInstance = _oExt._oExternConfig.iNextUnique ++;
6402 2 mingarao
                        }
6403 2 mingarao
6404 2 mingarao
                        /* Sanity check */
6405 2 mingarao
                        if ( this.nodeName.toLowerCase() != 'table' )
6406 2 mingarao
                        {
6407 2 mingarao
                                _fnLog( oSettings, 0, "Attempted to initialise DataTables on a node which is not a "+
6408 2 mingarao
                                        "table: "+this.nodeName );
6409 2 mingarao
                                return;
6410 2 mingarao
                        }
6411 2 mingarao
6412 2 mingarao
                        /* Store 'this' in the settings object for later retrieval */
6413 2 mingarao
                        oSettings.oInstance = _that;
6414 2 mingarao
6415 2 mingarao
                        /* Set the table node */
6416 2 mingarao
                        oSettings.nTable = this;
6417 2 mingarao
6418 2 mingarao
                        /* Bind the API functions to the settings, so we can perform actions whenever oSettings is
6419 2 mingarao
                         * available
6420 2 mingarao
                         */
6421 2 mingarao
                        oSettings.oApi = _that.oApi;
6422 2 mingarao
6423 2 mingarao
                        /* State the table's width for if a destroy is called at a later time */
6424 2 mingarao
                        oSettings.sDestroyWidth = $(this).width();
6425 2 mingarao
6426 2 mingarao
                        /* Store the features that we have available */
6427 2 mingarao
                        if ( typeof oInit != 'undefined' && oInit !== null )
6428 2 mingarao
                        {
6429 2 mingarao
                                oSettings.oInit = oInit;
6430 2 mingarao
                                _fnMap( oSettings.oFeatures, oInit, "bPaginate" );
6431 2 mingarao
                                _fnMap( oSettings.oFeatures, oInit, "bLengthChange" );
6432 2 mingarao
                                _fnMap( oSettings.oFeatures, oInit, "bFilter" );
6433 2 mingarao
                                _fnMap( oSettings.oFeatures, oInit, "bSort" );
6434 2 mingarao
                                _fnMap( oSettings.oFeatures, oInit, "bInfo" );
6435 2 mingarao
                                _fnMap( oSettings.oFeatures, oInit, "bProcessing" );
6436 2 mingarao
                                _fnMap( oSettings.oFeatures, oInit, "bAutoWidth" );
6437 2 mingarao
                                _fnMap( oSettings.oFeatures, oInit, "bSortClasses" );
6438 2 mingarao
                                _fnMap( oSettings.oFeatures, oInit, "bServerSide" );
6439 2 mingarao
                                _fnMap( oSettings.oScroll, oInit, "sScrollX", "sX" );
6440 2 mingarao
                                _fnMap( oSettings.oScroll, oInit, "sScrollXInner", "sXInner" );
6441 2 mingarao
                                _fnMap( oSettings.oScroll, oInit, "sScrollY", "sY" );
6442 2 mingarao
                                _fnMap( oSettings.oScroll, oInit, "bScrollCollapse", "bCollapse" );
6443 2 mingarao
                                _fnMap( oSettings.oScroll, oInit, "bScrollInfinite", "bInfinite" );
6444 2 mingarao
                                _fnMap( oSettings.oScroll, oInit, "iScrollLoadGap", "iLoadGap" );
6445 2 mingarao
                                _fnMap( oSettings, oInit, "asStripClasses" );
6446 2 mingarao
                                _fnMap( oSettings, oInit, "fnRowCallback" );
6447 2 mingarao
                                _fnMap( oSettings, oInit, "fnHeaderCallback" );
6448 2 mingarao
                                _fnMap( oSettings, oInit, "fnFooterCallback" );
6449 2 mingarao
                                _fnMap( oSettings, oInit, "fnCookieCallback" );
6450 2 mingarao
                                _fnMap( oSettings, oInit, "fnInitComplete" );
6451 2 mingarao
                                _fnMap( oSettings, oInit, "fnServerData" );
6452 2 mingarao
                                _fnMap( oSettings, oInit, "fnFormatNumber" );
6453 2 mingarao
                                _fnMap( oSettings, oInit, "aaSorting" );
6454 2 mingarao
                                _fnMap( oSettings, oInit, "aaSortingFixed" );
6455 2 mingarao
                                _fnMap( oSettings, oInit, "aLengthMenu" );
6456 2 mingarao
                                _fnMap( oSettings, oInit, "sPaginationType" );
6457 2 mingarao
                                _fnMap( oSettings, oInit, "sAjaxSource" );
6458 2 mingarao
                                _fnMap( oSettings, oInit, "iCookieDuration" );
6459 2 mingarao
                                _fnMap( oSettings, oInit, "sCookiePrefix" );
6460 2 mingarao
                                _fnMap( oSettings, oInit, "sDom" );
6461 2 mingarao
                                _fnMap( oSettings, oInit, "oSearch", "oPreviousSearch" );
6462 2 mingarao
                                _fnMap( oSettings, oInit, "aoSearchCols", "aoPreSearchCols" );
6463 2 mingarao
                                _fnMap( oSettings, oInit, "iDisplayLength", "_iDisplayLength" );
6464 2 mingarao
                                _fnMap( oSettings, oInit, "bJQueryUI", "bJUI" );
6465 2 mingarao
                                _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
6466 2 mingarao
6467 2 mingarao
                                /* Callback functions which are array driven */
6468 2 mingarao
                                if ( typeof oInit.fnDrawCallback == 'function' )
6469 2 mingarao
                                {
6470 2 mingarao
                                        oSettings.aoDrawCallback.push( {
6471 2 mingarao
                                                "fn": oInit.fnDrawCallback,
6472 2 mingarao
                                                "sName": "user"
6473 2 mingarao
                                        } );
6474 2 mingarao
                                }
6475 2 mingarao
6476 2 mingarao
                                if ( typeof oInit.fnStateSaveCallback == 'function' )
6477 2 mingarao
                                {
6478 2 mingarao
                                        oSettings.aoStateSave.push( {
6479 2 mingarao
                                                "fn": oInit.fnStateSaveCallback,
6480 2 mingarao
                                                "sName": "user"
6481 2 mingarao
                                        } );
6482 2 mingarao
                                }
6483 2 mingarao
6484 2 mingarao
                                if ( typeof oInit.fnStateLoadCallback == 'function' )
6485 2 mingarao
                                {
6486 2 mingarao
                                        oSettings.aoStateLoad.push( {
6487 2 mingarao
                                                "fn": oInit.fnStateLoadCallback,
6488 2 mingarao
                                                "sName": "user"
6489 2 mingarao
                                        } );
6490 2 mingarao
                                }
6491 2 mingarao
6492 2 mingarao
                                if ( oSettings.oFeatures.bServerSide && oSettings.oFeatures.bSort &&
6493 2 mingarao
                                           oSettings.oFeatures.bSortClasses )
6494 2 mingarao
                                {
6495 2 mingarao
                                        /* Enable sort classes for server-side processing. Safe to do it here, since server-side
6496 2 mingarao
                                         * processing must be enabled by the developer
6497 2 mingarao
                                         */
6498 2 mingarao
                                        oSettings.aoDrawCallback.push( {
6499 2 mingarao
                                                "fn": _fnSortingClasses,
6500 2 mingarao
                                                "sName": "server_side_sort_classes"
6501 2 mingarao
                                        } );
6502 2 mingarao
                                }
6503 2 mingarao
6504 2 mingarao
                                if ( typeof oInit.bJQueryUI != 'undefined' && oInit.bJQueryUI )
6505 2 mingarao
                                {
6506 2 mingarao
                                        /* Use the JUI classes object for display. You could clone the oStdClasses object if
6507 2 mingarao
                                         * you want to have multiple tables with multiple independent classes
6508 2 mingarao
                                         */
6509 2 mingarao
                                        oSettings.oClasses = _oExt.oJUIClasses;
6510 2 mingarao
6511 2 mingarao
                                        if ( typeof oInit.sDom == 'undefined' )
6512 2 mingarao
                                        {
6513 2 mingarao
                                                /* Set the DOM to use a layout suitable for jQuery UI's theming */
6514 2 mingarao
                                                oSettings.sDom = '<"H"lfr>t<"F"ip>';
6515 2 mingarao
                                        }
6516 2 mingarao
                                }
6517 2 mingarao
6518 2 mingarao
                                /* Calculate the scroll bar width and cache it for use later on */
6519 2 mingarao
                                if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" )
6520 2 mingarao
                                {
6521 2 mingarao
                                        oSettings.oScroll.iBarWidth = _fnScrollBarWidth();
6522 2 mingarao
                                }
6523 2 mingarao
6524 2 mingarao
                                if ( typeof oInit.iDisplayStart != 'undefined' &&
6525 2 mingarao
                                     typeof oSettings.iInitDisplayStart == 'undefined' )
6526 2 mingarao
                                {
6527 2 mingarao
                                        /* Display start point, taking into account the save saving */
6528 2 mingarao
                                        oSettings.iInitDisplayStart = oInit.iDisplayStart;
6529 2 mingarao
                                        oSettings._iDisplayStart = oInit.iDisplayStart;
6530 2 mingarao
                                }
6531 2 mingarao
6532 2 mingarao
                                /* Must be done after everything which can be overridden by a cookie! */
6533 2 mingarao
                                if ( typeof oInit.bStateSave != 'undefined' )
6534 2 mingarao
                                {
6535 2 mingarao
                                        oSettings.oFeatures.bStateSave = oInit.bStateSave;
6536 2 mingarao
                                        _fnLoadState( oSettings, oInit );
6537 2 mingarao
                                        oSettings.aoDrawCallback.push( {
6538 2 mingarao
                                                "fn": _fnSaveState,
6539 2 mingarao
                                                "sName": "state_save"
6540 2 mingarao
                                        } );
6541 2 mingarao
                                }
6542 2 mingarao
6543 2 mingarao
                                if ( typeof oInit.aaData != 'undefined' )
6544 2 mingarao
                                {
6545 2 mingarao
                                        bUsePassedData = true;
6546 2 mingarao
                                }
6547 2 mingarao
6548 2 mingarao
                                /* Backwards compatability */
6549 2 mingarao
                                /* aoColumns / aoData - remove at some point... */
6550 2 mingarao
                                if ( typeof oInit != 'undefined' && typeof oInit.aoData != 'undefined' )
6551 2 mingarao
                                {
6552 2 mingarao
                                        oInit.aoColumns = oInit.aoData;
6553 2 mingarao
                                }
6554 2 mingarao
6555 2 mingarao
                                /* Language definitions */
6556 2 mingarao
                                if ( typeof oInit.oLanguage != 'undefined' )
6557 2 mingarao
                                {
6558 2 mingarao
                                        if ( typeof oInit.oLanguage.sUrl != 'undefined' && oInit.oLanguage.sUrl !== "" )
6559 2 mingarao
                                        {
6560 2 mingarao
                                                /* Get the language definitions from a file */
6561 2 mingarao
                                                oSettings.oLanguage.sUrl = oInit.oLanguage.sUrl;
6562 2 mingarao
                                                $.getJSON( oSettings.oLanguage.sUrl, null, function( json ) {
6563 2 mingarao
                                                        _fnLanguageProcess( oSettings, json, true ); } );
6564 2 mingarao
                                                bInitHandedOff = true;
6565 2 mingarao
                                        }
6566 2 mingarao
                                        else
6567 2 mingarao
                                        {
6568 2 mingarao
                                                _fnLanguageProcess( oSettings, oInit.oLanguage, false );
6569 2 mingarao
                                        }
6570 2 mingarao
                                }
6571 2 mingarao
                                /* Warning: The _fnLanguageProcess function is async to the remainder of this function due
6572 2 mingarao
                                 * to the XHR. We use _bInitialised in _fnLanguageProcess() to check this the processing
6573 2 mingarao
                                 * below is complete. The reason for spliting it like this is optimisation - we can fire
6574 2 mingarao
                                 * off the XHR (if needed) and then continue processing the data.
6575 2 mingarao
                                 */
6576 2 mingarao
                        }
6577 2 mingarao
                        else
6578 2 mingarao
                        {
6579 2 mingarao
                                /* Create a dummy object for quick manipulation later on. */
6580 2 mingarao
                                oInit = {};
6581 2 mingarao
                        }
6582 2 mingarao
6583 2 mingarao
                        /*
6584 2 mingarao
                         * Stripes
6585 2 mingarao
                         * Add the strip classes now that we know which classes to apply - unless overruled
6586 2 mingarao
                         */
6587 2 mingarao
                        if ( typeof oInit.asStripClasses == 'undefined' )
6588 2 mingarao
                        {
6589 2 mingarao
                                oSettings.asStripClasses.push( oSettings.oClasses.sStripOdd );
6590 2 mingarao
                                oSettings.asStripClasses.push( oSettings.oClasses.sStripEven );
6591 2 mingarao
                        }
6592 2 mingarao
6593 2 mingarao
                        /* Remove row stripe classes if they are already on the table row */
6594 2 mingarao
                        var bStripeRemove = false;
6595 2 mingarao
                        var anRows = $('tbody>tr', this);
6596 2 mingarao
                        for ( i=0, iLen=oSettings.asStripClasses.length ; i<iLen ; i++ )
6597 2 mingarao
                        {
6598 2 mingarao
                                if ( anRows.filter(":lt(2)").hasClass( oSettings.asStripClasses[i]) )
6599 2 mingarao
                                {
6600 2 mingarao
                                        bStripeRemove = true;
6601 2 mingarao
                                        break;
6602 2 mingarao
                                }
6603 2 mingarao
                        }
6604 2 mingarao
6605 2 mingarao
                        if ( bStripeRemove )
6606 2 mingarao
                        {
6607 2 mingarao
                                /* Store the classes which we are about to remove so they can be readded on destory */
6608 2 mingarao
                                oSettings.asDestoryStrips = [ '', '' ];
6609 2 mingarao
                                if ( $(anRows[0]).hasClass(oSettings.oClasses.sStripOdd) )
6610 2 mingarao
                                {
6611 2 mingarao
                                        oSettings.asDestoryStrips[0] += oSettings.oClasses.sStripOdd+" ";
6612 2 mingarao
                                }
6613 2 mingarao
                                if ( $(anRows[0]).hasClass(oSettings.oClasses.sStripEven) )
6614 2 mingarao
                                {
6615 2 mingarao
                                        oSettings.asDestoryStrips[0] += oSettings.oClasses.sStripEven;
6616 2 mingarao
                                }
6617 2 mingarao
                                if ( $(anRows[1]).hasClass(oSettings.oClasses.sStripOdd) )
6618 2 mingarao
                                {
6619 2 mingarao
                                        oSettings.asDestoryStrips[1] += oSettings.oClasses.sStripOdd+" ";
6620 2 mingarao
                                }
6621 2 mingarao
                                if ( $(anRows[1]).hasClass(oSettings.oClasses.sStripEven) )
6622 2 mingarao
                                {
6623 2 mingarao
                                        oSettings.asDestoryStrips[1] += oSettings.oClasses.sStripEven;
6624 2 mingarao
                                }
6625 2 mingarao
6626 2 mingarao
                                anRows.removeClass( oSettings.asStripClasses.join(' ') );
6627 2 mingarao
                        }
6628 2 mingarao
6629 2 mingarao
                        /*
6630 2 mingarao
                         * Columns
6631 2 mingarao
                         * See if we should load columns automatically or use defined ones
6632 2 mingarao
                         */
6633 2 mingarao
                        var nThead = this.getElementsByTagName('thead');
6634 2 mingarao
                        var anThs = nThead.length===0 ? [] : _fnGetUniqueThs( nThead[0] );
6635 2 mingarao
                        var aoColumnsInit;
6636 2 mingarao
6637 2 mingarao
                        /* If not given a column array, generate one with nulls */
6638 2 mingarao
                        if ( typeof oInit.aoColumns == 'undefined' )
6639 2 mingarao
                        {
6640 2 mingarao
                                aoColumnsInit = [];
6641 2 mingarao
                                for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
6642 2 mingarao
                                {
6643 2 mingarao
                                        aoColumnsInit.push( null );
6644 2 mingarao
                                }
6645 2 mingarao
                        }
6646 2 mingarao
                        else
6647 2 mingarao
                        {
6648 2 mingarao
                                aoColumnsInit = oInit.aoColumns;
6649 2 mingarao
                        }
6650 2 mingarao
6651 2 mingarao
                        /* Add the columns */
6652 2 mingarao
                        for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
6653 2 mingarao
                        {
6654 2 mingarao
                                /* Check if we have column visibilty state to restore */
6655 2 mingarao
                                if ( typeof oInit.saved_aoColumns != 'undefined' && oInit.saved_aoColumns.length == iLen )
6656 2 mingarao
                                {
6657 2 mingarao
                                        if ( aoColumnsInit[i] === null )
6658 2 mingarao
                                        {
6659 2 mingarao
                                                aoColumnsInit[i] = {};
6660 2 mingarao
                                        }
6661 2 mingarao
                                        aoColumnsInit[i].bVisible = oInit.saved_aoColumns[i].bVisible;
6662 2 mingarao
                                }
6663 2 mingarao
6664 2 mingarao
                                _fnAddColumn( oSettings, anThs ? anThs[i] : null );
6665 2 mingarao
                        }
6666 2 mingarao
6667 2 mingarao
                        /* Add options from column definations */
6668 2 mingarao
                        if ( typeof oInit.aoColumnDefs != 'undefined' )
6669 2 mingarao
                        {
6670 2 mingarao
                                /* Loop over the column defs array - loop in reverse so first instace has priority */
6671 2 mingarao
                                for ( i=oInit.aoColumnDefs.length-1 ; i>=0 ; i-- )
6672 2 mingarao
                                {
6673 2 mingarao
                                        /* Each column def can target multiple columns, as it is an array */
6674 2 mingarao
                                        var aTargets = oInit.aoColumnDefs[i].aTargets;
6675 2 mingarao
                                        if ( !$.isArray( aTargets ) )
6676 2 mingarao
                                        {
6677 2 mingarao
                                                _fnLog( oSettings, 1, 'aTargets must be an array of targets, not a '+(typeof aTargets) );
6678 2 mingarao
                                        }
6679 2 mingarao
                                        for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
6680 2 mingarao
                                        {
6681 2 mingarao
                                                if ( typeof aTargets[j] == 'number' && aTargets[j] >= 0 )
6682 2 mingarao
                                                {
6683 2 mingarao
                                                        /* 0+ integer, left to right column counting. We add columns which are unknown
6684 2 mingarao
                                                         * automatically. Is this the right behaviour for this? We should at least
6685 2 mingarao
                                                         * log it in future. We cannot do this for the negative or class targets, only here.
6686 2 mingarao
                                                         */
6687 2 mingarao
                                                        while( oSettings.aoColumns.length <= aTargets[j] )
6688 2 mingarao
                                                        {
6689 2 mingarao
                                                                _fnAddColumn( oSettings );
6690 2 mingarao
                                                        }
6691 2 mingarao
                                                        _fnColumnOptions( oSettings, aTargets[j], oInit.aoColumnDefs[i] );
6692 2 mingarao
                                                }
6693 2 mingarao
                                                else if ( typeof aTargets[j] == 'number' && aTargets[j] < 0 )
6694 2 mingarao
                                                {
6695 2 mingarao
                                                        /* Negative integer, right to left column counting */
6696 2 mingarao
                                                        _fnColumnOptions( oSettings, oSettings.aoColumns.length+aTargets[j],
6697 2 mingarao
                                                                oInit.aoColumnDefs[i] );
6698 2 mingarao
                                                }
6699 2 mingarao
                                                else if ( typeof aTargets[j] == 'string' )
6700 2 mingarao
                                                {
6701 2 mingarao
                                                        /* Class name matching on TH element */
6702 2 mingarao
                                                        for ( k=0, kLen=oSettings.aoColumns.length ; k<kLen ; k++ )
6703 2 mingarao
                                                        {
6704 2 mingarao
                                                                if ( aTargets[j] == "_all" ||
6705 2 mingarao
                                                                     oSettings.aoColumns[k].nTh.className.indexOf( aTargets[j] ) != -1 )
6706 2 mingarao
                                                                {
6707 2 mingarao
                                                                        _fnColumnOptions( oSettings, k, oInit.aoColumnDefs[i] );
6708 2 mingarao
                                                                }
6709 2 mingarao
                                                        }
6710 2 mingarao
                                                }
6711 2 mingarao
                                        }
6712 2 mingarao
                                }
6713 2 mingarao
                        }
6714 2 mingarao
6715 2 mingarao
                        /* Add options from column array - after the defs array so this has priority */
6716 2 mingarao
                        if ( typeof aoColumnsInit != 'undefined' )
6717 2 mingarao
                        {
6718 2 mingarao
                                for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
6719 2 mingarao
                                {
6720 2 mingarao
                                        _fnColumnOptions( oSettings, i, aoColumnsInit[i] );
6721 2 mingarao
                                }
6722 2 mingarao
                        }
6723 2 mingarao
6724 2 mingarao
                        /*
6725 2 mingarao
                         * Sorting
6726 2 mingarao
                         * Check the aaSorting array
6727 2 mingarao
                         */
6728 2 mingarao
                        for ( i=0, iLen=oSettings.aaSorting.length ; i<iLen ; i++ )
6729 2 mingarao
                        {
6730 2 mingarao
                                if ( oSettings.aaSorting[i][0] >= oSettings.aoColumns.length )
6731 2 mingarao
                                {
6732 2 mingarao
                                        oSettings.aaSorting[i][0] = 0;
6733 2 mingarao
                                }
6734 2 mingarao
                                var oColumn = oSettings.aoColumns[ oSettings.aaSorting[i][0] ];
6735 2 mingarao
6736 2 mingarao
                                /* Add a default sorting index */
6737 2 mingarao
                                if ( typeof oSettings.aaSorting[i][2] == 'undefined' )
6738 2 mingarao
                                {
6739 2 mingarao
                                        oSettings.aaSorting[i][2] = 0;
6740 2 mingarao
                                }
6741 2 mingarao
6742 2 mingarao
                                /* If aaSorting is not defined, then we use the first indicator in asSorting */
6743 2 mingarao
                                if ( typeof oInit.aaSorting == "undefined" &&
6744 2 mingarao
                                                 typeof oSettings.saved_aaSorting == "undefined" )
6745 2 mingarao
                                {
6746 2 mingarao
                                        oSettings.aaSorting[i][1] = oColumn.asSorting[0];
6747 2 mingarao
                                }
6748 2 mingarao
6749 2 mingarao
                                /* Set the current sorting index based on aoColumns.asSorting */
6750 2 mingarao
                                for ( j=0, jLen=oColumn.asSorting.length ; j<jLen ; j++ )
6751 2 mingarao
                                {
6752 2 mingarao
                                        if ( oSettings.aaSorting[i][1] == oColumn.asSorting[j] )
6753 2 mingarao
                                        {
6754 2 mingarao
                                                oSettings.aaSorting[i][2] = j;
6755 2 mingarao
                                                break;
6756 2 mingarao
                                        }
6757 2 mingarao
                                }
6758 2 mingarao
                        }
6759 2 mingarao
6760 2 mingarao
                        /* Do a first pass on the sorting classes (allows any size changes to be taken into
6761 2 mingarao
                         * account, and also will apply sorting disabled classes if disabled
6762 2 mingarao
                         */
6763 2 mingarao
                        _fnSortingClasses( oSettings );
6764 2 mingarao
6765 2 mingarao
                        /*
6766 2 mingarao
                         * Final init
6767 2 mingarao
                         * Sanity check that there is a thead and tbody. If not let's just create them
6768 2 mingarao
                         */
6769 2 mingarao
                        if ( this.getElementsByTagName('thead').length === 0 )
6770 2 mingarao
                        {
6771 2 mingarao
                                this.appendChild( document.createElement( 'thead' ) );
6772 2 mingarao
                        }
6773 2 mingarao
6774 2 mingarao
                        if ( this.getElementsByTagName('tbody').length === 0 )
6775 2 mingarao
                        {
6776 2 mingarao
                                this.appendChild( document.createElement( 'tbody' ) );
6777 2 mingarao
                        }
6778 2 mingarao
6779 2 mingarao
                        oSettings.nTHead = this.getElementsByTagName('thead')[0];
6780 2 mingarao
                        oSettings.nTBody = this.getElementsByTagName('tbody')[0];
6781 2 mingarao
                        if ( this.getElementsByTagName('tfoot').length > 0 )
6782 2 mingarao
                        {
6783 2 mingarao
                                oSettings.nTFoot = this.getElementsByTagName('tfoot')[0];
6784 2 mingarao
                        }
6785 2 mingarao
6786 2 mingarao
                        /* Check if there is data passing into the constructor */
6787 2 mingarao
                        if ( bUsePassedData )
6788 2 mingarao
                        {
6789 2 mingarao
                                for ( i=0 ; i<oInit.aaData.length ; i++ )
6790 2 mingarao
                                {
6791 2 mingarao
                                        _fnAddData( oSettings, oInit.aaData[ i ] );
6792 2 mingarao
                                }
6793 2 mingarao
                        }
6794 2 mingarao
                        else
6795 2 mingarao
                        {
6796 2 mingarao
                                /* Grab the data from the page */
6797 2 mingarao
                                _fnGatherData( oSettings );
6798 2 mingarao
                        }
6799 2 mingarao
6800 2 mingarao
                        /* Copy the data index array */
6801 2 mingarao
                        oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
6802 2 mingarao
6803 2 mingarao
                        /* Initialisation complete - table can be drawn */
6804 2 mingarao
                        oSettings.bInitialised = true;
6805 2 mingarao
6806 2 mingarao
                        /* Check if we need to initialise the table (it might not have been handed off to the
6807 2 mingarao
                         * language processor)
6808 2 mingarao
                         */
6809 2 mingarao
                        if ( bInitHandedOff === false )
6810 2 mingarao
                        {
6811 2 mingarao
                                _fnInitalise( oSettings );
6812 2 mingarao
                        }
6813 2 mingarao
                });
6814 2 mingarao
        };
6815 2 mingarao
})(jQuery, window, document);