WP Google Maps - Version 2.2

Version Description

  • Added a "permission" check to see if the plugin will be able to work and return a warning message instead of leaving users in the dark as to why the plugin might not work on some hosts. The plugin's directory needs permission settings on 755 in order to work. The warnin message displays this note, along with a link on how you could fix it.
Download this release

Release Info

Developer WPGMaps
Plugin Icon 128x128 WP Google Maps
Version 2.2
Comparing to
See all releases

Code changes from version 5.01 to 2.2

css/data_table.css DELETED
@@ -1,575 +0,0 @@
1
- /*
2
- * File: demo_table.css
3
- * CVS: $Id$
4
- * Description: CSS descriptions for DataTables demo pages
5
- * Author: Allan Jardine
6
- * Created: Tue May 12 06:47:22 BST 2009
7
- * Modified: $Date$ by $Author$
8
- * Language: CSS
9
- * Project: DataTables
10
- *
11
- * Copyright 2009 Allan Jardine. All Rights Reserved.
12
- *
13
- * ***************************************************************************
14
- * DESCRIPTION
15
- *
16
- * The styles given here are suitable for the demos that are used with the standard DataTables
17
- * distribution (see www.datatables.net). You will most likely wish to modify these styles to
18
- * meet the layout requirements of your site.
19
- *
20
- * Common issues:
21
- * 'full_numbers' pagination - I use an extra selector on the body tag to ensure that there is
22
- * no conflict between the two pagination types. If you want to use full_numbers pagination
23
- * ensure that you either have "example_alt_pagination" as a body class name, or better yet,
24
- * modify that selector.
25
- * Note that the path used for Images is relative. All images are by default located in
26
- * ../images/ - relative to this CSS file.
27
- */
28
-
29
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
30
- * DataTables features
31
- */
32
-
33
- .dataTables_wrapper {
34
- position: relative;
35
- clear: both;
36
- zoom: 1; /* Feeling sorry for IE */
37
- }
38
-
39
- .dataTables_processing {
40
- position: absolute;
41
- top: 50%;
42
- left: 50%;
43
- width: 250px;
44
- height: 30px;
45
- margin-left: -125px;
46
- margin-top: -15px;
47
- padding: 14px 0 2px 0;
48
- border: 1px solid #ddd;
49
- text-align: center;
50
- color: #999;
51
- font-size: 14px;
52
- background-color: white;
53
- }
54
-
55
- .dataTables_length {
56
- width: 40%;
57
- float: left;
58
- }
59
-
60
- .dataTables_filter {
61
- width: 50%;
62
- float: right;
63
- text-align: right;
64
- }
65
-
66
- .dataTables_info {
67
- width: 60%;
68
- float: left;
69
- }
70
-
71
- .dataTables_paginate {
72
- float: right;
73
- text-align: right;
74
- }
75
-
76
- /* Pagination nested */
77
- .paginate_disabled_previous, .paginate_enabled_previous,
78
- .paginate_disabled_next, .paginate_enabled_next {
79
- height: 19px;
80
- float: left;
81
- cursor: pointer;
82
- *cursor: hand;
83
- color: #111 !important;
84
- }
85
- .paginate_disabled_previous:hover, .paginate_enabled_previous:hover,
86
- .paginate_disabled_next:hover, .paginate_enabled_next:hover {
87
- text-decoration: none !important;
88
- }
89
- .paginate_disabled_previous:active, .paginate_enabled_previous:active,
90
- .paginate_disabled_next:active, .paginate_enabled_next:active {
91
- outline: none;
92
- }
93
-
94
- .paginate_disabled_previous,
95
- .paginate_disabled_next {
96
- color: #666 !important;
97
- }
98
- .paginate_disabled_previous, .paginate_enabled_previous {
99
- padding-left: 23px;
100
- }
101
- .paginate_disabled_next, .paginate_enabled_next {
102
- padding-right: 23px;
103
- margin-left: 10px;
104
- }
105
-
106
- .paginate_disabled_previous {
107
- background: url('../images/back_disabled.png') no-repeat top left;
108
- }
109
-
110
- .paginate_enabled_previous {
111
- background: url('../images/back_enabled.png') no-repeat top left;
112
- }
113
- .paginate_enabled_previous:hover {
114
- background: url('../images/back_enabled_hover.png') no-repeat top left;
115
- }
116
-
117
- .paginate_disabled_next {
118
- background: url('../images/forward_disabled.png') no-repeat top right;
119
- }
120
-
121
- .paginate_enabled_next {
122
- background: url('../images/forward_enabled.png') no-repeat top right;
123
- }
124
- .paginate_enabled_next:hover {
125
- background: url('../images/forward_enabled_hover.png') no-repeat top right;
126
- }
127
-
128
-
129
-
130
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
131
- * DataTables display
132
- */
133
- table.display {
134
- margin: 0 auto;
135
- clear: both;
136
- width: 100%;
137
-
138
- /* Note Firefox 3.5 and before have a bug with border-collapse
139
- * ( https://bugzilla.mozilla.org/show%5Fbug.cgi?id=155955 )
140
- * border-spacing: 0; is one possible option. Conditional-css.com is
141
- * useful for this kind of thing
142
- *
143
- * Further note IE 6/7 has problems when calculating widths with border width.
144
- * It subtracts one px relative to the other browsers from the first column, and
145
- * adds one to the end...
146
- *
147
- * If you want that effect I'd suggest setting a border-top/left on th/td's and
148
- * then filling in the gaps with other borders.
149
- */
150
- }
151
-
152
- table.display thead th {
153
- padding: 3px 18px 3px 10px;
154
- border-bottom: 1px solid black;
155
- font-weight: bold;
156
- cursor: pointer;
157
- * cursor: hand;
158
- }
159
-
160
- table.display tfoot th {
161
- padding: 3px 18px 3px 10px;
162
- border-top: 1px solid black;
163
- font-weight: bold;
164
- }
165
-
166
- table.display tr.heading2 td {
167
- border-bottom: 1px solid #aaa;
168
- }
169
-
170
- table.display td {
171
- padding: 3px 10px;
172
- }
173
-
174
- table.display td.center {
175
- text-align: center;
176
- }
177
-
178
-
179
-
180
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
181
- * DataTables sorting
182
- */
183
-
184
- .sorting_asc {
185
- background: url('../images/sort_asc.png') no-repeat center right;
186
- }
187
-
188
- .sorting_desc {
189
- background: url('../images/sort_desc.png') no-repeat center right;
190
- }
191
-
192
- .sorting {
193
- background: url('../images/sort_both.png') no-repeat center right;
194
- }
195
-
196
- .sorting_asc_disabled {
197
- background: url('../images/sort_asc_disabled.png') no-repeat center right;
198
- }
199
-
200
- .sorting_desc_disabled {
201
- background: url('../images/sort_desc_disabled.png') no-repeat center right;
202
- }
203
-
204
- th:active {
205
- outline: none;
206
- }
207
-
208
-
209
-
210
-
211
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
212
- * DataTables row classes
213
- */
214
- table.display tr.odd.gradeA {
215
- background-color: #ddffdd;
216
- }
217
-
218
- table.display tr.even.gradeA {
219
- background-color: #eeffee;
220
- }
221
-
222
- table.display tr.odd.gradeC {
223
- background-color: #ddddff;
224
- }
225
-
226
- table.display tr.even.gradeC {
227
- background-color: #eeeeff;
228
- }
229
-
230
- table.display tr.odd.gradeX {
231
- background-color: #ffdddd;
232
- }
233
-
234
- table.display tr.even.gradeX {
235
- background-color: #ffeeee;
236
- }
237
-
238
- table.display tr.odd.gradeU {
239
- background-color: #ddd;
240
- }
241
-
242
- table.display tr.even.gradeU {
243
- background-color: #eee;
244
- }
245
-
246
-
247
- tr.odd {
248
- background-color: #E2E4FF;
249
- }
250
-
251
- tr.even {
252
- background-color: white;
253
- }
254
-
255
-
256
-
257
-
258
-
259
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
260
- * Misc
261
- */
262
- .dataTables_scroll {
263
- clear: both;
264
- }
265
-
266
- .dataTables_scrollBody {
267
- *margin-top: -1px;
268
- }
269
-
270
- .top, .bottom {
271
- padding: 15px;
272
- background-color: #F5F5F5;
273
- border: 1px solid #CCCCCC;
274
- }
275
-
276
- .top .dataTables_info {
277
- float: none;
278
- }
279
-
280
- .clear {
281
- clear: both;
282
- }
283
-
284
- .dataTables_empty {
285
- text-align: center;
286
- }
287
-
288
- tfoot input {
289
- margin: 0.5em 0;
290
- width: 100%;
291
- color: #444;
292
- }
293
-
294
- tfoot input.search_init {
295
- color: #999;
296
- }
297
-
298
- td.group {
299
- background-color: #d1cfd0;
300
- border-bottom: 2px solid #A19B9E;
301
- border-top: 2px solid #A19B9E;
302
- }
303
-
304
- td.details {
305
- background-color: #d1cfd0;
306
- border: 2px solid #A19B9E;
307
- }
308
-
309
-
310
- .example_alt_pagination div.dataTables_info {
311
- width: 40%;
312
- }
313
-
314
- .paging_full_numbers {
315
- width: 400px;
316
- height: 22px;
317
- line-height: 22px;
318
- }
319
-
320
- .paging_full_numbers a:active {
321
- outline: none
322
- }
323
-
324
- .paging_full_numbers a:hover {
325
- text-decoration: none;
326
- }
327
-
328
- .paging_full_numbers a.paginate_button,
329
- .paging_full_numbers a.paginate_active {
330
- border: 1px solid #aaa;
331
- -webkit-border-radius: 5px;
332
- -moz-border-radius: 5px;
333
- padding: 2px 5px;
334
- margin: 0 3px;
335
- cursor: pointer;
336
- *cursor: hand;
337
- color: #333 !important;
338
- }
339
-
340
- .paging_full_numbers a.paginate_button {
341
- background-color: #ddd;
342
- }
343
-
344
- .paging_full_numbers a.paginate_button:hover {
345
- background-color: #ccc;
346
- text-decoration: none !important;
347
- }
348
-
349
- .paging_full_numbers a.paginate_active {
350
- background-color: #99B3FF;
351
- }
352
-
353
- table.display tr.even.row_selected td {
354
- background-color: #B0BED9;
355
- }
356
-
357
- table.display tr.odd.row_selected td {
358
- background-color: #9FAFD1;
359
- }
360
-
361
-
362
- /*
363
- * Sorting classes for columns
364
- */
365
- /* For the standard odd/even */
366
- tr.odd td.sorting_1 {
367
- background-color: #D3D6FF;
368
- }
369
-
370
- tr.odd td.sorting_2 {
371
- background-color: #DADCFF;
372
- }
373
-
374
- tr.odd td.sorting_3 {
375
- background-color: #E0E2FF;
376
- }
377
-
378
- tr.even td.sorting_1 {
379
- background-color: #EAEBFF;
380
- }
381
-
382
- tr.even td.sorting_2 {
383
- background-color: #F2F3FF;
384
- }
385
-
386
- tr.even td.sorting_3 {
387
- background-color: #F9F9FF;
388
- }
389
-
390
-
391
- /* For the Conditional-CSS grading rows */
392
- /*
393
- Colour calculations (based off the main row colours)
394
- Level 1:
395
- dd > c4
396
- ee > d5
397
- Level 2:
398
- dd > d1
399
- ee > e2
400
- */
401
- tr.odd.gradeA td.sorting_1 {
402
- background-color: #c4ffc4;
403
- }
404
-
405
- tr.odd.gradeA td.sorting_2 {
406
- background-color: #d1ffd1;
407
- }
408
-
409
- tr.odd.gradeA td.sorting_3 {
410
- background-color: #d1ffd1;
411
- }
412
-
413
- tr.even.gradeA td.sorting_1 {
414
- background-color: #d5ffd5;
415
- }
416
-
417
- tr.even.gradeA td.sorting_2 {
418
- background-color: #e2ffe2;
419
- }
420
-
421
- tr.even.gradeA td.sorting_3 {
422
- background-color: #e2ffe2;
423
- }
424
-
425
- tr.odd.gradeC td.sorting_1 {
426
- background-color: #c4c4ff;
427
- }
428
-
429
- tr.odd.gradeC td.sorting_2 {
430
- background-color: #d1d1ff;
431
- }
432
-
433
- tr.odd.gradeC td.sorting_3 {
434
- background-color: #d1d1ff;
435
- }
436
-
437
- tr.even.gradeC td.sorting_1 {
438
- background-color: #d5d5ff;
439
- }
440
-
441
- tr.even.gradeC td.sorting_2 {
442
- background-color: #e2e2ff;
443
- }
444
-
445
- tr.even.gradeC td.sorting_3 {
446
- background-color: #e2e2ff;
447
- }
448
-
449
- tr.odd.gradeX td.sorting_1 {
450
- background-color: #ffc4c4;
451
- }
452
-
453
- tr.odd.gradeX td.sorting_2 {
454
- background-color: #ffd1d1;
455
- }
456
-
457
- tr.odd.gradeX td.sorting_3 {
458
- background-color: #ffd1d1;
459
- }
460
-
461
- tr.even.gradeX td.sorting_1 {
462
- background-color: #ffd5d5;
463
- }
464
-
465
- tr.even.gradeX td.sorting_2 {
466
- background-color: #ffe2e2;
467
- }
468
-
469
- tr.even.gradeX td.sorting_3 {
470
- background-color: #ffe2e2;
471
- }
472
-
473
- tr.odd.gradeU td.sorting_1 {
474
- background-color: #c4c4c4;
475
- }
476
-
477
- tr.odd.gradeU td.sorting_2 {
478
- background-color: #d1d1d1;
479
- }
480
-
481
- tr.odd.gradeU td.sorting_3 {
482
- background-color: #d1d1d1;
483
- }
484
-
485
- tr.even.gradeU td.sorting_1 {
486
- background-color: #d5d5d5;
487
- }
488
-
489
- tr.even.gradeU td.sorting_2 {
490
- background-color: #e2e2e2;
491
- }
492
-
493
- tr.even.gradeU td.sorting_3 {
494
- background-color: #e2e2e2;
495
- }
496
-
497
-
498
- /*
499
- * Row highlighting example
500
- */
501
- .ex_highlight #example tbody tr.even:hover, #example tbody tr.even td.highlighted {
502
- background-color: #ECFFB3;
503
- }
504
-
505
- .ex_highlight #example tbody tr.odd:hover, #example tbody tr.odd td.highlighted {
506
- background-color: #E6FF99;
507
- }
508
-
509
- .ex_highlight_row #example tr.even:hover {
510
- background-color: #ECFFB3;
511
- }
512
-
513
- .ex_highlight_row #example tr.even:hover td.sorting_1 {
514
- background-color: #DDFF75;
515
- }
516
-
517
- .ex_highlight_row #example tr.even:hover td.sorting_2 {
518
- background-color: #E7FF9E;
519
- }
520
-
521
- .ex_highlight_row #example tr.even:hover td.sorting_3 {
522
- background-color: #E2FF89;
523
- }
524
-
525
- .ex_highlight_row #example tr.odd:hover {
526
- background-color: #E6FF99;
527
- }
528
-
529
- .ex_highlight_row #example tr.odd:hover td.sorting_1 {
530
- background-color: #D6FF5C;
531
- }
532
-
533
- .ex_highlight_row #example tr.odd:hover td.sorting_2 {
534
- background-color: #E0FF84;
535
- }
536
-
537
- .ex_highlight_row #example tr.odd:hover td.sorting_3 {
538
- background-color: #DBFF70;
539
- }
540
-
541
-
542
- /*
543
- * KeyTable
544
- */
545
- table.KeyTable td {
546
- border: 3px solid transparent;
547
- }
548
-
549
- table.KeyTable td.focus {
550
- border: 3px solid #3366FF;
551
- }
552
-
553
- table.display tr.gradeA {
554
- background-color: #eeffee;
555
- }
556
-
557
- table.display tr.gradeC {
558
- background-color: #ddddff;
559
- }
560
-
561
- table.display tr.gradeX {
562
- background-color: #ffdddd;
563
- }
564
-
565
- table.display tr.gradeU {
566
- background-color: #ddd;
567
- }
568
-
569
- div.box {
570
- height: 100px;
571
- padding: 10px;
572
- overflow: auto;
573
- border: 1px solid #8080FF;
574
- background-color: #E5E5FF;
575
- }
css/wpgmza_style.css DELETED
@@ -1,50 +0,0 @@
1
- .wpgmza_map {
2
- border:0;
3
- margin:5px !important;
4
- }
5
- #wpgmza_map img {
6
- border: none !important;
7
- background-color:transparent !important;
8
- }
9
- .wpgmza_map img {
10
- border: none !important;
11
- background-color:transparent !important;
12
- padding:0 !important;
13
- margin:0 !important;
14
- }
15
- #wpgmaps_directions_edit {
16
- padding-top:20px;
17
- }
18
- .wpgmza_markerbox {
19
- color:#000 !important;
20
- }
21
- .wpgmza_markerbox a {
22
- color:#1982D1 !important;
23
- }
24
- .wpgmaps_mlist_table {
25
- width:42px;
26
- }
27
-
28
- .wpgmaps_mlist_marker {
29
- width:32px;
30
- height:32px;
31
- vertical-align:top;
32
- padding:0 !important;
33
- }
34
-
35
- .wpgmaps_mlist_info {
36
- text-align:left;
37
- padding:0 !important;
38
-
39
- }
40
- .wpgmaps_mlist_row:hover {
41
- background-color: #EEEEEE;
42
- }
43
- .wpgmaps_directions_outer_div {
44
- padding-top:30px;
45
- padding-bottom:5px;
46
- }
47
-
48
- .wpgmaps_directions_outer_div table, wpgmza_marker_list_class {
49
- margin-bottom:0px !important;
50
- }
csv.php CHANGED
@@ -3,9 +3,7 @@
3
require('../../../wp-load.php' );
4
5
6
-
7
- global $wpdb;
8
- $fileName = $wpdb->prefix.'wpgmza.csv';
9
10
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
11
header('Content-Description: File Transfer');
@@ -16,7 +14,7 @@ header("Pragma: public");
16
17
$fh = @fopen( 'php://output', 'w' );
18
19
-
20
$query = "SELECT * FROM `{$wpdb->prefix}wpgmza`";
21
$results = $wpdb->get_results( $query, ARRAY_A );
22
3
require('../../../wp-load.php' );
4
5
6
+ $fileName = 'wpgmza_export'.time().'.csv';
7
8
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
9
header('Content-Description: File Transfer');
14
15
$fh = @fopen( 'php://output', 'w' );
16
17
+ global $wpdb;
18
$query = "SELECT * FROM `{$wpdb->prefix}wpgmza`";
19
$results = $wpdb->get_results( $query, ARRAY_A );
20
images/back_disabled.png DELETED
Binary file
images/back_enabled.png DELETED
Binary file
images/back_enabled_hover.png DELETED
Binary file
images/custom_marker_icons.jpg DELETED
Binary file
images/forward_disabled.png DELETED
Binary file
images/forward_enabled.png DELETED
Binary file
images/forward_enabled_hover.png DELETED
Binary file
images/get_directions.jpg DELETED
Binary file
images/marker.png DELETED
Binary file
images/sort_asc.png DELETED
Binary file
images/sort_asc_disabled.png DELETED
Binary file
images/sort_both.png DELETED
Binary file
images/sort_desc.png DELETED
Binary file
images/sort_desc_disabled.png DELETED
Binary file
js/jquery.dataTables.js DELETED
@@ -1,11612 +0,0 @@
1
- /**
2
- * @summary DataTables
3
- * @description Paginate, search and sort HTML tables
4
- * @version 1.9.0
5
- * @file jquery.dataTables.js
6
- * @author Allan Jardine (www.sprymedia.co.uk)
7
- * @contact www.sprymedia.co.uk/contact
8
- *
9
- * @copyright Copyright 2008-2012 Allan Jardine, all rights reserved.
10
- *
11
- * This source file is free software, under either the GPL v2 license or a
12
- * BSD style license, available at:
13
- * http://datatables.net/license_gpl2
14
- * http://datatables.net/license_bsd
15
- *
16
- * This source file is distributed in the hope that it will be useful, but
17
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18
- * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
19
- *
20
- * For details please refer to: http://www.datatables.net
21
- */
22
-
23
- /*jslint evil: true, undef: true, browser: true */
24
- /*globals $, jQuery,_fnExternApiFunc,_fnInitialise,_fnInitComplete,_fnLanguageCompat,_fnAddColumn,_fnColumnOptions,_fnAddData,_fnCreateTr,_fnGatherData,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnServerParams,_fnAddOptionsHtml,_fnFeatureHtmlTable,_fnScrollDraw,_fnAdjustColumnSizing,_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,_fnDetectType,_fnSettingsFromNode,_fnGetDataMaster,_fnGetTrNodes,_fnGetTdNodes,_fnEscapeRegex,_fnDeleteIndex,_fnReOrderIndex,_fnColumnOrdering,_fnLog,_fnClearTable,_fnSaveState,_fnLoadState,_fnCreateCookie,_fnReadCookie,_fnDetectHeader,_fnGetUniqueThs,_fnScrollBarWidth,_fnApplyToChildren,_fnMap,_fnGetRowData,_fnGetCellData,_fnSetCellData,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnApplyColumnDefs,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnJsonString,_fnRender,_fnNodeToColumnIndex*/
25
-
26
- (/** @lends <global> */function($, window, document, undefined) {
27
- /**
28
- * DataTables is a plug-in for the jQuery Javascript library. It is a
29
- * highly flexible tool, based upon the foundations of progressive
30
- * enhancement, which will add advanced interaction controls to any
31
- * HTML table. For a full list of features please refer to
32
- * <a href="http://datatables.net">DataTables.net</a>.
33
- *
34
- * Note that the <i>DataTable</i> object is not a global variable but is
35
- * aliased to <i>jQuery.fn.DataTable</i> and <i>jQuery.fn.dataTable</i> through which
36
- * it may be accessed.
37
- *
38
- * @class
39
- * @param {object} [oInit={}] Configuration object for DataTables. Options
40
- * are defined by {@link DataTable.defaults}
41
- * @requires jQuery 1.3+
42
- *
43
- * @example
44
- * // Basic initialisation
45
- * $(document).ready( function {
46
- * $('#example').dataTable();
47
- * } );
48
- *
49
- * @example
50
- * // Initialisation with configuration options - in this case, disable
51
- * // pagination and sorting.
52
- * $(document).ready( function {
53
- * $('#example').dataTable( {
54
- * "bPaginate": false,
55
- * "bSort": false
56
- * } );
57
- * } );
58
- */
59
- var DataTable = function( oInit )
60
- {
61
-
62
-
63
- /**
64
- * Add a column to the list used for the table with default values
65
- * @param {object} oSettings dataTables settings object
66
- * @param {node} nTh The th element for this column
67
- * @memberof DataTable#oApi
68
- */
69
- function _fnAddColumn( oSettings, nTh )
70
- {
71
- var oDefaults = DataTable.defaults.columns;
72
- var iCol = oSettings.aoColumns.length;
73
- var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
74
- "sSortingClass": oSettings.oClasses.sSortable,
75
- "sSortingClassJUI": oSettings.oClasses.sSortJUI,
76
- "nTh": nTh ? nTh : document.createElement('th'),
77
- "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '',
78
- "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
79
- "mDataProp": oDefaults.mDataProp ? oDefaults.oDefaults : iCol
80
- } );
81
- oSettings.aoColumns.push( oCol );
82
-
83
- /* Add a column specific filter */
84
- if ( oSettings.aoPreSearchCols[ iCol ] === undefined || oSettings.aoPreSearchCols[ iCol ] === null )
85
- {
86
- oSettings.aoPreSearchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch );
87
- }
88
- else
89
- {
90
- var oPre = oSettings.aoPreSearchCols[ iCol ];
91
-
92
- /* Don't require that the user must specify bRegex, bSmart or bCaseInsensitive */
93
- if ( oPre.bRegex === undefined )
94
- {
95
- oPre.bRegex = true;
96
- }
97
-
98
- if ( oPre.bSmart === undefined )
99
- {
100
- oPre.bSmart = true;
101
- }
102
-
103
- if ( oPre.bCaseInsensitive === undefined )
104
- {
105
- oPre.bCaseInsensitive = true;
106
- }
107
- }
108
-
109
- /* Use the column options function to initialise classes etc */
110
- _fnColumnOptions( oSettings, iCol, null );
111
- }
112
-
113
-
114
- /**
115
- * Apply options for a column
116
- * @param {object} oSettings dataTables settings object
117
- * @param {int} iCol column index to consider
118
- * @param {object} oOptions object with sType, bVisible and bSearchable
119
- * @memberof DataTable#oApi
120
- */
121
- function _fnColumnOptions( oSettings, iCol, oOptions )
122
- {
123
- var oCol = oSettings.aoColumns[ iCol ];
124
-
125
- /* User specified column options */
126
- if ( oOptions !== undefined && oOptions !== null )
127
- {
128
- if ( oOptions.sType !== undefined )
129
- {
130
- oCol.sType = oOptions.sType;
131
- oCol._bAutoType = false;
132
- }
133
-
134
- $.extend( oCol, oOptions );
135
- _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
136
-
137
- /* iDataSort to be applied (backwards compatibility), but aDataSort will take
138
- * priority if defined
139
- */
140
- if ( oOptions.iDataSort !== undefined )
141
- {
142
- oCol.aDataSort = [ oOptions.iDataSort ];
143
- }
144
- _fnMap( oCol, oOptions, "aDataSort" );
145
- }
146
-
147
- /* Cache the data get and set functions for speed */
148
- oCol.fnGetData = _fnGetObjectDataFn( oCol.mDataProp );
149
- oCol.fnSetData = _fnSetObjectDataFn( oCol.mDataProp );
150
-
151
- /* Feature sorting overrides column specific when off */
152
- if ( !oSettings.oFeatures.bSort )
153
- {
154
- oCol.bSortable = false;
155
- }
156
-
157
- /* Check that the class assignment is correct for sorting */
158
- if ( !oCol.bSortable ||
159
- ($.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1) )
160
- {
161
- oCol.sSortingClass = oSettings.oClasses.sSortableNone;
162
- oCol.sSortingClassJUI = "";
163
- }
164
- else if ( oCol.bSortable ||
165
- ($.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1) )
166
- {
167
- oCol.sSortingClass = oSettings.oClasses.sSortable;
168
- oCol.sSortingClassJUI = oSettings.oClasses.sSortJUI;
169
- }
170
- else if ( $.inArray('asc', oCol.asSorting) != -1 && $.inArray('desc', oCol.asSorting) == -1 )
171
- {
172
- oCol.sSortingClass = oSettings.oClasses.sSortableAsc;
173
- oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIAscAllowed;
174
- }
175
- else if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) != -1 )
176
- {
177
- oCol.sSortingClass = oSettings.oClasses.sSortableDesc;
178
- oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIDescAllowed;
179
- }
180
- }
181
-
182
-
183
- /**
184
- * Adjust the table column widths for new data. Note: you would probably want to
185
- * do a redraw after calling this function!
186
- * @param {object} oSettings dataTables settings object
187
- * @memberof DataTable#oApi
188
- */
189
- function _fnAdjustColumnSizing ( oSettings )
190
- {
191
- /* Not interested in doing column width calculation if autowidth is disabled */
192
- if ( oSettings.oFeatures.bAutoWidth === false )
193
- {
194
- return false;
195
- }
196
-
197
- _fnCalculateColumnWidths( oSettings );
198
- for ( var i=0 , iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
199
- {
200
- oSettings.aoColumns[i].nTh.style.width = oSettings.aoColumns[i].sWidth;
201
- }
202
- }
203
-
204
-
205
- /**
206
- * Covert the index of a visible column to the index in the data array (take account
207
- * of hidden columns)
208
- * @param {object} oSettings dataTables settings object
209
- * @param {int} iMatch Visible column index to lookup
210
- * @returns {int} i the data index
211
- * @memberof DataTable#oApi
212
- */
213
- function _fnVisibleToColumnIndex( oSettings, iMatch )
214
- {
215
- var iColumn = -1;
216
-
217
- for ( var i=0 ; i<oSettings.aoColumns.length ; i++ )
218
- {
219
- if ( oSettings.aoColumns[i].bVisible === true )
220
- {
221
- iColumn++;
222
- }
223
-
224
- if ( iColumn == iMatch )
225
- {
226
- return i;
227
- }
228
- }
229
-
230
- return null;
231
- }
232
-
233
-
234
- /**
235
- * Covert the index of an index in the data array and convert it to the visible
236
- * column index (take account of hidden columns)
237
- * @param {int} iMatch Column index to lookup
238
- * @param {object} oSettings dataTables settings object
239
- * @returns {int} i the data index
240
- * @memberof DataTable#oApi
241
- */
242
- function _fnColumnIndexToVisible( oSettings, iMatch )
243
- {
244
- var iVisible = -1;
245
- for ( var i=0 ; i<oSettings.aoColumns.length ; i++ )
246
- {
247
- if ( oSettings.aoColumns[i].bVisible === true )
248
- {
249
- iVisible++;
250
- }
251
-
252
- if ( i == iMatch )
253
- {
254
- return oSettings.aoColumns[i].bVisible === true ? iVisible : null;
255
- }
256
- }
257
-
258
- return null;
259
- }
260
-
261
-
262
- /**
263
- * Get the number of visible columns
264
- * @returns {int} i the number of visible columns
265
- * @param {object} oS dataTables settings object
266
- * @memberof DataTable#oApi
267
- */
268
- function _fnVisbleColumns( oS )
269
- {
270
- var iVis = 0;
271
- for ( var i=0 ; i<oS.aoColumns.length ; i++ )
272
- {
273
- if ( oS.aoColumns[i].bVisible === true )
274
- {
275
- iVis++;
276
- }
277
- }
278
- return iVis;
279
- }
280
-
281
-
282
- /**
283
- * Get the sort type based on an input string
284
- * @param {string} sData data we wish to know the type of
285
- * @returns {string} type (defaults to 'string' if no type can be detected)
286
- * @memberof DataTable#oApi
287
- */
288
- function _fnDetectType( sData )
289
- {
290
- var aTypes = DataTable.ext.aTypes;
291
- var iLen = aTypes.length;
292
-
293
- for ( var i=0 ; i<iLen ; i++ )
294
- {
295
- var sType = aTypes[i]( sData );
296
- if ( sType !== null )
297
- {
298
- return sType;
299
- }
300
- }
301
-
302
- return 'string';
303
- }
304
-
305
-
306
- /**
307
- * Figure out how to reorder a display list
308
- * @param {object} oSettings dataTables settings object
309
- * @returns array {int} aiReturn index list for reordering
310
- * @memberof DataTable#oApi
311
- */
312
- function _fnReOrderIndex ( oSettings, sColumns )
313
- {
314
- var aColumns = sColumns.split(',');
315
- var aiReturn = [];
316
-
317
- for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
318
- {
319
- for ( var j=0 ; j<iLen ; j++ )
320
- {
321
- if ( oSettings.aoColumns[i].sName == aColumns[j] )
322
- {
323
- aiReturn.push( j );
324
- break;
325
- }
326
- }
327
- }
328
-
329
- return aiReturn;
330
- }
331
-
332
-
333
- /**
334
- * Get the column ordering that DataTables expects
335
- * @param {object} oSettings dataTables settings object
336
- * @returns {string} comma separated list of names
337
- * @memberof DataTable#oApi
338
- */
339
- function _fnColumnOrdering ( oSettings )
340
- {
341
- var sNames = '';
342
- for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
343
- {
344
- sNames += oSettings.aoColumns[i].sName+',';
345
- }
346
- if ( sNames.length == iLen )
347
- {
348
- return "";
349
- }
350
- return sNames.slice(0, -1);
351
- }
352
-
353
-
354
- /**
355
- * Take the column definitions and static columns arrays and calculate how
356
- * they relate to column indexes. The callback function will then apply the
357
- * definition found for a column to a suitable configuration object.
358
- * @param {object} oSettings dataTables settings object
359
- * @param {array} aoColDefs The aoColumnDefs array that is to be applied
360
- * @param {array} aoCols The aoColumns array that defines columns individually
361
- * @param {function} fn Callback function - takes two parameters, the calculated
362
- * column index and the definition for that column.
363
- * @memberof DataTable#oApi
364
- */
365
- function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
366
- {
367
- var i, iLen, j, jLen, k, kLen;
368
-
369
- // Column definitions with aTargets
370
- if ( aoColDefs )
371
- {
372
- /* Loop over the definitions array - loop in reverse so first instance has priority */
373
- for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
374
- {
375
- /* Each definition can target multiple columns, as it is an array */
376
- var aTargets = aoColDefs[i].aTargets;
377
- if ( !$.isArray( aTargets ) )
378
- {
379
- _fnLog( oSettings, 1, 'aTargets must be an array of targets, not a '+(typeof aTargets) );
380
- }
381
-
382
- for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
383
- {
384
- if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
385
- {
386
- /* Add columns that we don't yet know about */
387
- while( oSettings.aoColumns.length <= aTargets[j] )
388
- {
389
- _fnAddColumn( oSettings );
390
- }
391
-
392
- /* Integer, basic index */
393
- fn( aTargets[j], aoColDefs[i] );
394
- }
395
- else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
396
- {
397
- /* Negative integer, right to left column counting */
398
- fn( oSettings.aoColumns.length+aTargets[j], aoColDefs[i] );
399
- }
400
- else if ( typeof aTargets[j] === 'string' )
401
- {
402
- /* Class name matching on TH element */
403
- for ( k=0, kLen=oSettings.aoColumns.length ; k<kLen ; k++ )
404
- {
405
- if ( aTargets[j] == "_all" ||
406
- $(oSettings.aoColumns[k].nTh).hasClass( aTargets[j] ) )
407
- {
408
- fn( k, aoColDefs[i] );
409
- }
410
- }
411
- }
412
- }
413
- }
414
- }
415
-
416
- // Statically defined columns array
417
- if ( aoCols )
418
- {
419
- for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
420
- {
421
- fn( i, aoCols[i] );
422
- }
423
- }
424
- }
425
-
426
-
427
-
428
- /**
429
- * Add a data array to the table, creating DOM node etc. This is the parallel to
430
- * _fnGatherData, but for adding rows from a Javascript source, rather than a
431
- * DOM source.
432
- * @param {object} oSettings dataTables settings object
433
- * @param {array} aData data array to be added
434
- * @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
435
- * @memberof DataTable#oApi
436
- */
437
- function _fnAddData ( oSettings, aDataSupplied )
438
- {
439
- var oCol;
440
-
441
- /* Take an independent copy of the data source so we can bash it about as we wish */
442
- var aDataIn = ($.isArray(aDataSupplied)) ?
443
- aDataSupplied.slice() :
444
- $.extend( true, {}, aDataSupplied );
445
-
446
- /* Create the object for storing information about this new row */
447
- var iRow = oSettings.aoData.length;
448
- var oData = $.extend( true, {}, DataTable.models.oRow, {
449
- "_aData": aDataIn
450
- } );
451
- oSettings.aoData.push( oData );
452
-
453
- /* Create the cells */
454
- var nTd, sThisType;
455
- for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
456
- {
457
- oCol = oSettings.aoColumns[i];
458
-
459
- /* Use rendered data for filtering/sorting */
460
- if ( typeof oCol.fnRender === 'function' && oCol.bUseRendered && oCol.mDataProp !== null )
461
- {
462
- _fnSetCellData( oSettings, iRow, i, _fnRender(oSettings, iRow, i) );
463
- }
464
-
465
- /* See if we should auto-detect the column type */
466
- if ( oCol._bAutoType && oCol.sType != 'string' )
467
- {
468
- /* Attempt to auto detect the type - same as _fnGatherData() */
469
- var sVarType = _fnGetCellData( oSettings, iRow, i, 'type' );
470
- if ( sVarType !== null && sVarType !== '' )
471
- {
472
- sThisType = _fnDetectType( sVarType );
473
- if ( oCol.sType === null )
474
- {
475
- oCol.sType = sThisType;
476
- }
477
- else if ( oCol.sType != sThisType && oCol.sType != "html" )
478
- {
479
- /* String is always the 'fallback' option */
480
- oCol.sType = 'string';
481
- }
482
- }
483
- }
484
- }
485
-
486
- /* Add to the display array */
487
- oSettings.aiDisplayMaster.push( iRow );
488
-
489
- /* Create the DOM imformation */
490
- if ( !oSettings.oFeatures.bDeferRender )
491
- {
492
- _fnCreateTr( oSettings, iRow );
493
- }
494
-
495
- return iRow;
496
- }
497
-
498
-
499
- /**
500
- * Read in the data from the target table from the DOM
501
- * @param {object} oSettings dataTables settings object
502
- * @memberof DataTable#oApi
503
- */
504
- function _fnGatherData( oSettings )
505
- {
506
- var iLoop, i, iLen, j, jLen, jInner,
507
- nTds, nTrs, nTd, aLocalData, iThisIndex,
508
- iRow, iRows, iColumn, iColumns, sNodeName,
509
- oCol, oData;
510
-
511
- /*
512
- * Process by row first
513
- * Add the data object for the whole table - storing the tr node. Note - no point in getting
514
- * DOM based data if we are going to go and replace it with Ajax source data.
515
- */
516
- if ( oSettings.bDeferLoading || oSettings.sAjaxSource === null )
517
- {
518
- nTrs = oSettings.nTBody.childNodes;
519
- for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
520
- {
521
- if ( nTrs[i].nodeName.toUpperCase() == "TR" )
522
- {
523
- iThisIndex = oSettings.aoData.length;
524
- nTrs[i]._DT_RowIndex = iThisIndex;
525
- oSettings.aoData.push( $.extend( true, {}, DataTable.models.oRow, {
526
- "nTr": nTrs[i]
527
- } ) );
528
-
529
- oSettings.aiDisplayMaster.push( iThisIndex );
530
- nTds = nTrs[i].childNodes;
531
- jInner = 0;
532
-
533
- for ( j=0, jLen=nTds.length ; j<jLen ; j++ )
534
- {
535
- sNodeName = nTds[j].nodeName.toUpperCase();
536
- if ( sNodeName == "TD" || sNodeName == "TH" )
537
- {
538
- _fnSetCellData( oSettings, iThisIndex, jInner, $.trim(nTds[j].innerHTML) );
539
- jInner++;
540
- }
541
- }
542
- }
543
- }
544
- }
545
-
546
- /* Gather in the TD elements of the Table - note that this is basically the same as
547
- * fnGetTdNodes, but that function takes account of hidden columns, which we haven't yet
548
- * setup!
549
- */
550
- nTrs = _fnGetTrNodes( oSettings );
551
- nTds = [];
552
- for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
553
- {
554
- for ( j=0, jLen=nTrs[i].childNodes.length ; j<jLen ; j++ )
555
- {
556
- nTd = nTrs[i].childNodes[j];
557
- sNodeName = nTd.nodeName.toUpperCase();
558
- if ( sNodeName == "TD" || sNodeName == "TH" )
559
- {
560
- nTds.push( nTd );
561
- }
562
- }
563
- }
564
-
565
- /* Now process by column */
566
- for ( iColumn=0, iColumns=oSettings.aoColumns.length ; iColumn<iColumns ; iColumn++ )
567
- {
568
- oCol = oSettings.aoColumns[iColumn];
569
-
570
- /* Get the title of the column - unless there is a user set one */
571
- if ( oCol.sTitle === null )
572
- {
573
- oCol.sTitle = oCol.nTh.innerHTML;
574
- }
575
-
576
- var
577
- bAutoType = oCol._bAutoType,
578
- bRender = typeof oCol.fnRender === 'function',
579
- bClass = oCol.sClass !== null,
580
- bVisible = oCol.bVisible,
581
- nCell, sThisType, sRendered, sValType;
582
-
583
- /* A single loop to rule them all (and be more efficient) */
584
- if ( bAutoType || bRender || bClass || !bVisible )
585
- {
586
- for ( iRow=0, iRows=oSettings.aoData.length ; iRow<iRows ; iRow++ )
587
- {
588
- oData = oSettings.aoData[iRow];
589
- nCell = nTds[ (iRow*iColumns) + iColumn ];
590
-
591
- /* Type detection */
592
- if ( bAutoType && oCol.sType != 'string' )
593
- {
594
- sValType = _fnGetCellData( oSettings, iRow, iColumn, 'type' );
595
- if ( sValType !== '' )
596
- {
597
- sThisType = _fnDetectType( sValType );
598
- if ( oCol.sType === null )
599
- {
600
- oCol.sType = sThisType;
601
- }
602
- else if ( oCol.sType != sThisType &&
603
- oCol.sType != "html" )
604
- {
605
- /* String is always the 'fallback' option */
606
- oCol.sType = 'string';
607
- }
608
- }
609
- }
610
-
611
- if ( typeof oCol.mDataProp === 'function' )
612
- {
613
- nCell.innerHTML = _fnGetCellData( oSettings, iRow, iColumn, 'display' );
614
- }
615
-
616
- /* Rendering */
617
- if ( bRender )
618
- {
619
- sRendered = _fnRender( oSettings, iRow, iColumn );
620
- nCell.innerHTML = sRendered;
621
- if ( oCol.bUseRendered )
622
- {
623
- /* Use the rendered data for filtering/sorting */
624
- _fnSetCellData( oSettings, iRow, iColumn, sRendered );
625
- }
626
- }
627
-
628
- /* Classes */
629
- if ( bClass )
630
- {
631
- nCell.className += ' '+oCol.sClass;
632
- }
633
-
634
- /* Column visability */
635
- if ( !bVisible )
636
- {
637
- oData._anHidden[iColumn] = nCell;
638
- nCell.parentNode.removeChild( nCell );
639
- }
640
- else
641
- {
642
- oData._anHidden[iColumn] = null;
643
- }
644
-
645
- if ( oCol.fnCreatedCell )
646
- {
647
- oCol.fnCreatedCell.call( oSettings.oInstance,
648
- nCell, _fnGetCellData( oSettings, iRow, iColumn, 'display' ), oData._aData, iRow, iColumn
649
- );
650
- }
651
- }
652
- }
653
- }
654
-
655
- /* Row created callbacks */
656
- if ( oSettings.aoRowCreatedCallback.length !== 0 )
657
- {
658
- for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
659
- {
660
- oData = oSettings.aoData[i];
661
- _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, i] );
662
- }
663
- }
664
- }
665
-
666
-
667
- /**
668
- * Take a TR element and convert it to an index in aoData
669
- * @param {object} oSettings dataTables settings object
670
- * @param {node} n the TR element to find
671
- * @returns {int} index if the node is found, null if not
672
- * @memberof DataTable#oApi
673
- */
674
- function _fnNodeToDataIndex( oSettings, n )
675
- {
676
- return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
677
- }
678
-
679
-
680
- /**
681
- * Take a TD element and convert it into a column data index (not the visible index)
682
- * @param {object} oSettings dataTables settings object
683
- * @param {int} iRow The row number the TD/TH can be found in
684
- * @param {node} n The TD/TH element to find
685
- * @returns {int} index if the node is found, -1 if not
686
- * @memberof DataTable#oApi
687
- */
688
- function _fnNodeToColumnIndex( oSettings, iRow, n )
689
- {
690
- var anCells = _fnGetTdNodes( oSettings, iRow );
691
-
692
- for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
693
- {
694
- if ( anCells[i] === n )
695
- {
696
- return i;
697
- }
698
- }
699
- return -1;
700
- }
701
-
702
-
703
- /**
704
- * Get an array of data for a given row from the internal data cache
705
- * @param {object} oSettings dataTables settings object
706
- * @param {int} iRow aoData row id
707
- * @param {string} sSpecific data get type ('type' 'filter' 'sort')
708
- * @returns {array} Data array
709
- * @memberof DataTable#oApi
710
- */
711
- function _fnGetRowData( oSettings, iRow, sSpecific )
712
- {
713
- var out = [];
714
- for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
715
- {
716
- out.push( _fnGetCellData( oSettings, iRow, i, sSpecific ) );
717
- }
718
- return out;
719
- }
720
-
721
-
722
- /**
723
- * Get the data for a given cell from the internal cache, taking into account data mapping
724
- * @param {object} oSettings dataTables settings object
725
- * @param {int} iRow aoData row id
726
- * @param {int} iCol Column index
727
- * @param {string} sSpecific data get type ('display', 'type' 'filter' 'sort')
728
- * @returns {*} Cell data
729
- * @memberof DataTable#oApi
730
- */
731
- function _fnGetCellData( oSettings, iRow, iCol, sSpecific )
732
- {
733
- var sData;
734
- var oCol = oSettings.aoColumns[iCol];
735
- var oData = oSettings.aoData[iRow]._aData;
736
-
737
- if ( (sData=oCol.fnGetData( oData, sSpecific )) === undefined )
738
- {
739
- if ( oSettings.iDrawError != oSettings.iDraw && oCol.sDefaultContent === null )
740
- {
741
- _fnLog( oSettings, 0, "Requested unknown parameter '"+oCol.mDataProp+
742
- "' from the data source for row "+iRow );
743
- oSettings.iDrawError = oSettings.iDraw;
744
- }
745
- return oCol.sDefaultContent;
746
- }
747
-
748
- /* When the data source is null, we can use default column data */
749
- if ( sData === null && oCol.sDefaultContent !== null )
750
- {
751
- sData = oCol.sDefaultContent;
752
- }
753
- else if ( typeof sData === 'function' )
754
- {
755
- /* If the data source is a function, then we run it and use the return */
756
- return sData();
757
- }
758
-
759
- if ( sSpecific == 'display' && sData === null )
760
- {
761
- return '';
762
- }
763
- return sData;
764
- }
765
-
766
-
767
- /**
768
- * Set the value for a specific cell, into the internal data cache
769
- * @param {object} oSettings dataTables settings object
770
- * @param {int} iRow aoData row id
771
- * @param {int} iCol Column index
772
- * @param {*} val Value to set
773
- * @memberof DataTable#oApi
774
- */
775
- function _fnSetCellData( oSettings, iRow, iCol, val )
776
- {
777
- var oCol = oSettings.aoColumns[iCol];
778
- var oData = oSettings.aoData[iRow]._aData;
779
-
780
- oCol.fnSetData( oData, val );
781
- }
782
-
783
-
784
- /**
785
- * Return a function that can be used to get data from a source object, taking
786
- * into account the ability to use nested objects as a source
787
- * @param {string|int|function} mSource The data source for the object
788
- * @returns {function} Data get function
789
- * @memberof DataTable#oApi
790
- */
791
- function _fnGetObjectDataFn( mSource )
792
- {
793
- if ( mSource === null )
794
- {
795
- /* Give an empty string for rendering / sorting etc */
796
- return function (data, type) {
797
- return null;
798
- };
799
- }
800
- else if ( typeof mSource === 'function' )
801
- {
802
- return function (data, type) {
803
- return mSource( data, type );
804
- };
805
- }
806
- else if ( typeof mSource === 'string' && mSource.indexOf('.') != -1 )
807
- {
808
- /* If there is a . in the source string then the data source is in a
809
- * nested object so we loop over the data for each level to get the next
810
- * level down. On each loop we test for undefined, and if found immediatly
811
- * return. This allows entire objects to be missing and sDefaultContent to
812
- * be used if defined, rather than throwing an error
813
- */
814
- var a = mSource.split('.');
815
- return function (data, type) {
816
- for ( var i=0, iLen=a.length ; i<iLen ; i++ )
817
- {
818
- data = data[ a[i] ];
819
- if ( data === undefined )
820
- {
821
- return undefined;
822
- }
823
- }
824
- return data;
825
- };
826
- }
827
- else
828
- {
829
- /* Array or flat object mapping */
830
- return function (data, type) {
831
- return data[mSource];
832
- };
833
- }
834
- }
835
-
836
-
837
- /**
838
- * Return a function that can be used to set data from a source object, taking
839
- * into account the ability to use nested objects as a source
840
- * @param {string|int|function} mSource The data source for the object
841
- * @returns {function} Data set function
842
- * @memberof DataTable#oApi
843
- */
844
- function _fnSetObjectDataFn( mSource )
845
- {
846
- if ( mSource === null )
847
- {
848
- /* Nothing to do when the data source is null */
849
- return function (data, val) {};
850
- }
851
- else if ( typeof mSource === 'function' )
852
- {
853
- return function (data, val) {
854
- mSource( data, 'set', val );
855
- };
856
- }
857
- else if ( typeof mSource === 'string' && mSource.indexOf('.') != -1 )
858
- {
859
- /* Like the get, we need to get data from a nested object. */
860
- var a = mSource.split('.');
861
- return function (data, val) {
862
- for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
863
- {
864
- data = data[ a[i] ];
865
- }
866
- data[ a[a.length-1] ] = val;
867
- };
868
- }
869
- else
870
- {
871
- /* Array or flat object mapping */
872
- return function (data, val) {
873
- data[mSource] = val;
874
- };
875
- }
876
- }
877
-
878
-
879
- /**
880
- * Return an array with the full table data
881
- * @param {object} oSettings dataTables settings object
882
- * @returns array {array} aData Master data array
883
- * @memberof DataTable#oApi
884
- */
885
- function _fnGetDataMaster ( oSettings )
886
- {
887
- var aData = [];
888
- var iLen = oSettings.aoData.length;
889
- for ( var i=0 ; i<iLen; i++ )
890
- {
891
- aData.push( oSettings.aoData[i]._aData );
892
- }
893
- return aData;
894
- }
895
-
896
-
897
- /**
898
- * Nuke the table
899
- * @param {object} oSettings dataTables settings object
900
- * @memberof DataTable#oApi
901
- */
902
- function _fnClearTable( oSettings )
903
- {
904
- oSettings.aoData.splice( 0, oSettings.aoData.length );
905
- oSettings.aiDisplayMaster.splice( 0, oSettings.aiDisplayMaster.length );
906
- oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length );
907
- _fnCalculateEnd( oSettings );
908
- }
909
-
910
-
911
- /**
912
- * Take an array of integers (index array) and remove a target integer (value - not
913
- * the key!)
914
- * @param {array} a Index array to target
915
- * @param {int} iTarget value to find
916
- * @memberof DataTable#oApi
917
- */
918
- function _fnDeleteIndex( a, iTarget )
919
- {
920
- var iTargetIndex = -1;
921
-
922
- for ( var i=0, iLen=a.length ; i<iLen ; i++ )
923
- {
924
- if ( a[i] == iTarget )
925
- {
926
- iTargetIndex = i;
927
- }
928
- else if ( a[i] > iTarget )
929
- {
930
- a[i]--;
931
- }
932
- }
933
-
934
- if ( iTargetIndex != -1 )
935
- {
936
- a.splice( iTargetIndex, 1 );
937
- }
938
- }
939
-
940
-
941
- /**
942
- * Call the developer defined fnRender function for a given cell (row/column) with
943
- * the required parameters and return the result.
944
- * @param {object} oSettings dataTables settings object
945
- * @param {int} iRow aoData index for the row
946
- * @param {int} iCol aoColumns index for the column
947
- * @returns {*} Return of the developer's fnRender function
948
- * @memberof DataTable#oApi
949
- */
950
- function _fnRender( oSettings, iRow, iCol )
951
- {
952
- var oCol = oSettings.aoColumns[iCol];
953
-
954
- return oCol.fnRender( {
955
- "iDataRow": iRow,
956
- "iDataColumn": iCol,
957
- "oSettings": oSettings,
958
- "aData": oSettings.aoData[iRow]._aData,
959
- "mDataProp": oCol.mDataProp
960
- }, _fnGetCellData(oSettings, iRow, iCol, 'display') );
961
- }
962
-
963
-
964
- /**
965
- * Create a new TR element (and it's TD children) for a row
966
- * @param {object} oSettings dataTables settings object
967
- * @param {int} iRow Row to consider
968
- * @memberof DataTable#oApi
969
- */
970
- function _fnCreateTr ( oSettings, iRow )
971
- {
972
- var oData = oSettings.aoData[iRow];
973
- var nTd;
974
-
975
- if ( oData.nTr === null )
976
- {
977
- oData.nTr = document.createElement('tr');
978
-
979
- /* Use a private property on the node to allow reserve mapping from the node
980
- * to the aoData array for fast look up
981
- */
982
- oData.nTr._DT_RowIndex = iRow;
983
-
984
- /* Special parameters can be given by the data source to be used on the row */
985
- if ( oData._aData.DT_RowId )
986
- {
987
- oData.nTr.id = oData._aData.DT_RowId;
988
- }
989
-
990
- if ( oData._aData.DT_RowClass )
991
- {
992
- $(oData.nTr).addClass( oData._aData.DT_RowClass );
993
- }
994
-
995
- /* Process each column */
996
- for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
997
- {
998
- var oCol = oSettings.aoColumns[i];
999
- nTd = document.createElement('td');
1000
-
1001
- /* Render if needed - if bUseRendered is true then we already have the rendered
1002
- * value in the data source - so can just use that
1003
- */
1004
- nTd.innerHTML = (typeof oCol.fnRender === 'function' && (!oCol.bUseRendered || oCol.mDataProp === null)) ?
1005
- _fnRender( oSettings, iRow, i ) :
1006
- _fnGetCellData( oSettings, iRow, i, 'display' );
1007
-
1008
- /* Add user defined class */
1009
- if ( oCol.sClass !== null )
1010
- {
1011
- nTd.className = oCol.sClass;
1012
- }
1013
-
1014
- if ( oCol.bVisible )
1015
- {
1016
- oData.nTr.appendChild( nTd );
1017
- oData._anHidden[i] = null;
1018
- }
1019
- else
1020
- {
1021
- oData._anHidden[i] = nTd;
1022
- }
1023
-
1024
- if ( oCol.fnCreatedCell )
1025
- {
1026
- oCol.fnCreatedCell.call( oSettings.oInstance,
1027
- nTd, _fnGetCellData( oSettings, iRow, i, 'display' ), oData._aData, iRow, i
1028
- );
1029
- }
1030
- }
1031
-
1032
- _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, iRow] );
1033
- }
1034
- }
1035
-
1036
-
1037
- /**
1038
- * Create the HTML header for the table
1039
- * @param {object} oSettings dataTables settings object
1040
- * @memberof DataTable#oApi
1041
- */
1042
- function _fnBuildHead( oSettings )
1043
- {
1044
- var i, nTh, iLen, j, jLen;
1045
- var iThs = oSettings.nTHead.getElementsByTagName('th').length;
1046
- var iCorrector = 0;
1047
- var jqChildren;
1048
-
1049
- /* If there is a header in place - then use it - otherwise it's going to get nuked... */
1050
- if ( iThs !== 0 )
1051
- {
1052
- /* We've got a thead from the DOM, so remove hidden columns and apply width to vis cols */
1053
- for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
1054
- {
1055
- nTh = oSettings.aoColumns[i].nTh;
1056
- nTh.setAttribute('role', 'columnheader');
1057
- if ( oSettings.aoColumns[i].bSortable )
1058
- {
1059
- nTh.setAttribute('tabindex', oSettings.iTabIndex);
1060
- nTh.setAttribute('aria-controls', oSettings.sTableId);
1061
- }
1062
-
1063
- if ( oSettings.aoColumns[i].sClass !== null )
1064
- {
1065
- $(nTh).addClass( oSettings.aoColumns[i].sClass );
1066
- }
1067
-
1068
- /* Set the title of the column if it is user defined (not what was auto detected) */
1069
- if ( oSettings.aoColumns[i].sTitle != nTh.innerHTML )
1070
- {
1071
- nTh.innerHTML = oSettings.aoColumns[i].sTitle;
1072
- }
1073
- }
1074
- }
1075
- else
1076
- {
1077
- /* We don't have a header in the DOM - so we are going to have to create one */
1078
- var nTr = document.createElement( "tr" );
1079
-
1080
- for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
1081
- {
1082
- nTh = oSettings.aoColumns[i].nTh;
1083
- nTh.innerHTML = oSettings.aoColumns[i].sTitle;
1084
- nTh.setAttribute('tabindex', '0');
1085
-
1086
- if ( oSettings.aoColumns[i].sClass !== null )
1087
- {
1088
- $(nTh).addClass( oSettings.aoColumns[i].sClass );
1089
- }
1090
-
1091
- nTr.appendChild( nTh );
1092
- }
1093
- $(oSettings.nTHead).html( '' )[0].appendChild( nTr );
1094
- _fnDetectHeader( oSettings.aoHeader, oSettings.nTHead );
1095
- }
1096
-
1097
- /* ARIA role for the rows */
1098
- $(oSettings.nTHead).children('tr').attr('role', 'row');
1099
-
1100
- /* Add the extra markup needed by jQuery UI's themes */
1101
- if ( oSettings.bJUI )
1102
- {
1103
- for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
1104
- {
1105
- nTh = oSettings.aoColumns[i].nTh;
1106
-
1107
- var nDiv = document.createElement('div');
1108
- nDiv.className = oSettings.oClasses.sSortJUIWrapper;
1109
- $(nTh).contents().appendTo(nDiv);
1110
-
1111
- var nSpan = document.createElement('span');
1112
- nSpan.className = oSettings.oClasses.sSortIcon;
1113
- nDiv.appendChild( nSpan );
1114
- nTh.appendChild( nDiv );
1115
- }
1116
- }
1117
-
1118
- if ( oSettings.oFeatures.bSort )
1119
- {
1120
- for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
1121
- {
1122
- if ( oSettings.aoColumns[i].bSortable !== false )
1123
- {
1124
- _fnSortAttachListener( oSettings, oSettings.aoColumns[i].nTh, i );
1125
- }
1126
- else
1127
- {
1128
- $(oSettings.aoColumns[i].nTh).addClass( oSettings.oClasses.sSortableNone );
1129
- }
1130
- }
1131
- }
1132
-
1133
- /* Deal with the footer - add classes if required */
1134
- if ( oSettings.oClasses.sFooterTH !== "" )
1135
- {
1136
- $(oSettings.nTFoot).children('tr').children('th').addClass( oSettings.oClasses.sFooterTH );
1137
- }
1138
-
1139
- /* Cache the footer elements */
1140
- if ( oSettings.nTFoot !== null )
1141
- {
1142
- var anCells = _fnGetUniqueThs( oSettings, null, oSettings.aoFooter );
1143
- for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
1144
- {
1145
- if ( anCells[i] )
1146
- {
1147
- oSettings.aoColumns[i].nTf = anCells[i];
1148
- if ( oSettings.aoColumns[i].sClass )
1149
- {
1150
- $(anCells[i]).addClass( oSettings.aoColumns[i].sClass );
1151
- }
1152
- }
1153
- }
1154
- }
1155
- }
1156
-
1157
-
1158
- /**
1159
- * Draw the header (or footer) element based on the column visibility states. The
1160
- * methodology here is to use the layout array from _fnDetectHeader, modified for
1161
- * the instantaneous column visibility, to construct the new layout. The grid is
1162
- * traversed over cell at a time in a rows x columns grid fashion, although each
1163
- * cell insert can cover multiple elements in the grid - which is tracks using the
1164
- * aApplied array. Cell inserts in the grid will only occur where there isn't
1165
- * already a cell in that position.
1166
- * @param {object} oSettings dataTables settings object
1167
- * @param array {objects} aoSource Layout array from _fnDetectHeader
1168
- * @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
1169
- * @memberof DataTable#oApi
1170
- */
1171
- function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
1172
- {
1173
- var i, iLen, j, jLen, k, kLen, n, nLocalTr;
1174
- var aoLocal = [];
1175
- var aApplied = [];
1176
- var iColumns = oSettings.aoColumns.length;
1177
- var iRowspan, iColspan;
1178
-
1179
- if ( bIncludeHidden === undefined )
1180
- {
1181
- bIncludeHidden = false;
1182
- }
1183
-
1184
- /* Make a copy of the master layout array, but without the visible columns in it */
1185
- for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
1186
- {
1187
- aoLocal[i] = aoSource[i].slice();
1188
- aoLocal[i].nTr = aoSource[i].nTr;
1189
-
1190
- /* Remove any columns which are currently hidden */
1191
- for ( j=iColumns-1 ; j>=0 ; j-- )
1192
- {
1193
- if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
1194
- {
1195
- aoLocal[i].splice( j, 1 );
1196
- }
1197
- }
1198
-
1199
- /* Prep the applied array - it needs an element for each row */
1200
- aApplied.push( [] );
1201
- }
1202
-
1203
- for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
1204
- {
1205
- nLocalTr = aoLocal[i].nTr;
1206
-
1207
- /* All cells are going to be replaced, so empty out the row */
1208
- if ( nLocalTr )
1209
- {
1210
- while( (n = nLocalTr.firstChild) )
1211
- {
1212
- nLocalTr.removeChild( n );
1213
- }
1214
- }
1215
-
1216
- for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
1217
- {
1218
- iRowspan = 1;
1219
- iColspan = 1;
1220
-
1221
- /* Check to see if there is already a cell (row/colspan) covering our target
1222
- * insert point. If there is, then there is nothing to do.
1223
- */
1224
- if ( aApplied[i][j] === undefined )
1225
- {
1226
- nLocalTr.appendChild( aoLocal[i][j].cell );
1227
- aApplied[i][j] = 1;
1228
-
1229
- /* Expand the cell to cover as many rows as needed */
1230
- while ( aoLocal[i+iRowspan] !== undefined &&
1231
- aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
1232
- {
1233
- aApplied[i+iRowspan][j] = 1;
1234
- iRowspan++;
1235
- }
1236
-
1237
- /* Expand the cell to cover as many columns as needed */
1238
- while ( aoLocal[i][j+iColspan] !== undefined &&
1239
- aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
1240
- {
1241
- /* Must update the applied array over the rows for the columns */
1242
- for ( k=0 ; k<iRowspan ; k++ )
1243
- {
1244
- aApplied[i+k][j+iColspan] = 1;
1245
- }
1246
- iColspan++;
1247
- }
1248
-
1249
- /* Do the actual expansion in the DOM */
1250
- aoLocal[i][j].cell.rowSpan = iRowspan;
1251
- aoLocal[i][j].cell.colSpan = iColspan;
1252
- }
1253
- }
1254
- }
1255
- }
1256
-
1257
-
1258
- /**
1259
- * Insert the required TR nodes into the table for display
1260
- * @param {object} oSettings dataTables settings object
1261
- * @memberof DataTable#oApi
1262
- */
1263
- function _fnDraw( oSettings )
1264
- {
1265
- var i, iLen, n;
1266
- var anRows = [];
1267
- var iRowCount = 0;
1268
- var iStripes = oSettings.asStripeClasses.length;
1269
- var iOpenRows = oSettings.aoOpenRows.length;
1270
-
1271
- /* Provide a pre-callback function which can be used to cancel the draw is false is returned */
1272
- var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
1273
- if ( $.inArray( false, aPreDraw ) !== -1 )
1274
- {
1275
- return;
1276
- }
1277
-
1278
- oSettings.bDrawing = true;
1279
-
1280
- /* Check and see if we have an initial draw position from state saving */
1281
- if ( oSettings.iInitDisplayStart !== undefined && oSettings.iInitDisplayStart != -1 )
1282
- {
1283
- if ( oSettings.oFeatures.bServerSide )
1284
- {
1285
- oSettings._iDisplayStart = oSettings.iInitDisplayStart;
1286
- }
1287
- else
1288
- {
1289
- oSettings._iDisplayStart = (oSettings.iInitDisplayStart >= oSettings.fnRecordsDisplay()) ?
1290
- 0 : oSettings.iInitDisplayStart;
1291
- }
1292
- oSettings.iInitDisplayStart = -1;
1293
- _fnCalculateEnd( oSettings );
1294
- }
1295
-
1296
- /* Server-side processing draw intercept */
1297
- if ( oSettings.bDeferLoading )
1298
- {
1299
- oSettings.bDeferLoading = false;
1300
- oSettings.iDraw++;
1301
- }
1302
- else if ( !oSettings.oFeatures.bServerSide )
1303
- {
1304
- oSettings.iDraw++;
1305
- }
1306
- else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
1307
- {
1308
- return;
1309
- }
1310
-
1311
- if ( oSettings.aiDisplay.length !== 0 )
1312
- {
1313
- var iStart = oSettings._iDisplayStart;
1314
- var iEnd = oSettings._iDisplayEnd;
1315
-
1316
- if ( oSettings.oFeatures.bServerSide )
1317
- {
1318
- iStart = 0;
1319
- iEnd = oSettings.aoData.length;
1320
- }
1321
-
1322
- for ( var j=iStart ; j<iEnd ; j++ )
1323
- {
1324
- var aoData = oSettings.aoData[ oSettings.aiDisplay[j] ];
1325
- if ( aoData.nTr === null )
1326
- {
1327
- _fnCreateTr( oSettings, oSettings.aiDisplay[j] );
1328
- }
1329
-
1330
- var nRow = aoData.nTr;
1331
-
1332
- /* Remove the old striping classes and then add the new one */
1333
- if ( iStripes !== 0 )
1334
- {
1335
- var sStripe = oSettings.asStripeClasses[ iRowCount % iStripes ];
1336
- if ( aoData._sRowStripe != sStripe )
1337
- {
1338
- $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
1339
- aoData._sRowStripe = sStripe;
1340
- }
1341
- }
1342
-
1343
- /* Row callback functions - might want to manipule the row */
1344
- _fnCallbackFire( oSettings, 'aoRowCallback', null,
1345
- [nRow, oSettings.aoData[ oSettings.aiDisplay[j] ]._aData, iRowCount, j] );
1346
-
1347
- anRows.push( nRow );
1348
- iRowCount++;
1349
-
1350
- /* If there is an open row - and it is attached to this parent - attach it on redraw */
1351
- if ( iOpenRows !== 0 )
1352
- {
1353
- for ( var k=0 ; k<iOpenRows ; k++ )
1354
- {
1355
- if ( nRow == oSettings.aoOpenRows[k].nParent )
1356
- {
1357
- anRows.push( oSettings.aoOpenRows[k].nTr );
1358
- break;
1359
- }
1360
- }
1361
- }
1362
- }
1363
- }
1364
- else
1365
- {
1366
- /* Table is empty - create a row with an empty message in it */
1367
- anRows[ 0 ] = document.createElement( 'tr' );
1368
-
1369
- if ( oSettings.asStripeClasses[0] )
1370
- {
1371
- anRows[ 0 ].className = oSettings.asStripeClasses[0];
1372
- }
1373
-
1374
- var sZero = oSettings.oLanguage.sZeroRecords.replace(
1375
- '_MAX_', oSettings.fnFormatNumber(oSettings.fnRecordsTotal()) );
1376
- if ( oSettings.iDraw == 1 && oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide )
1377
- {
1378
- sZero = oSettings.oLanguage.sLoadingRecords;
1379
- }
1380
- else if ( oSettings.oLanguage.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
1381
- {
1382
- sZero = oSettings.oLanguage.sEmptyTable;
1383
- }
1384
-
1385
- var nTd = document.createElement( 'td' );
1386
- nTd.setAttribute( 'valign', "top" );
1387
- nTd.colSpan = _fnVisbleColumns( oSettings );
1388
- nTd.className = oSettings.oClasses.sRowEmpty;
1389
- nTd.innerHTML = sZero;
1390
-
1391
- anRows[ iRowCount ].appendChild( nTd );
1392
- }
1393
-
1394
- /* Header and footer callbacks */
1395
- _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
1396
- _fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ] );
1397
-
1398
- _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
1399
- _fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ] );
1400
-
1401
- /*
1402
- * Need to remove any old row from the display - note we can't just empty the tbody using
1403
- * $().html('') since this will unbind the jQuery event handlers (even although the node
1404
- * still exists!) - equally we can't use innerHTML, since IE throws an exception.
1405
- */
1406
- var
1407
- nAddFrag = document.createDocumentFragment(),
1408
- nRemoveFrag = document.createDocumentFragment(),
1409
- nBodyPar, nTrs;
1410
-
1411
- if ( oSettings.nTBody )
1412
- {
1413
- nBodyPar = oSettings.nTBody.parentNode;
1414
- nRemoveFrag.appendChild( oSettings.nTBody );
1415
-
1416
- /* When doing infinite scrolling, only remove child rows when sorting, filtering or start
1417
- * up. When not infinite scroll, always do it.
1418
- */
1419
- if ( !oSettings.oScroll.bInfinite || !oSettings._bInitComplete ||
1420
- oSettings.bSorted || oSettings.bFiltered )
1421
- {
1422
- while( (n = oSettings.nTBody.firstChild) )
1423
- {
1424
- oSettings.nTBody.removeChild( n );
1425
- }
1426
- }
1427
-
1428
- /* Put the draw table into the dom */
1429
- for ( i=0, iLen=anRows.length ; i<iLen ; i++ )
1430
- {
1431
- nAddFrag.appendChild( anRows[i] );
1432
- }
1433
-
1434
- oSettings.nTBody.appendChild( nAddFrag );
1435
- if ( nBodyPar !== null )
1436
- {
1437
- nBodyPar.appendChild( oSettings.nTBody );
1438
- }
1439
- }
1440
-
1441
- /* Call all required callback functions for the end of a draw */
1442
- _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
1443
-
1444
- /* Draw is complete, sorting and filtering must be as well */
1445
- oSettings.bSorted = false;
1446
- oSettings.bFiltered = false;
1447
- oSettings.bDrawing = false;
1448
-
1449
- if ( oSettings.oFeatures.bServerSide )
1450
- {
1451
- _fnProcessingDisplay( oSettings, false );
1452
- if ( !oSettings._bInitComplete )
1453
- {
1454
- _fnInitComplete( oSettings );
1455
- }
1456
- }
1457
- }
1458
-
1459
-
1460
- /**
1461
- * Redraw the table - taking account of the various features which are enabled
1462
- * @param {object} oSettings dataTables settings object
1463
- * @memberof DataTable#oApi
1464
- */
1465
- function _fnReDraw( oSettings )
1466
- {
1467
- if ( oSettings.oFeatures.bSort )
1468
- {
1469
- /* Sorting will refilter and draw for us */
1470
- _fnSort( oSettings, oSettings.oPreviousSearch );
1471
- }
1472
- else if ( oSettings.oFeatures.bFilter )
1473
- {
1474
- /* Filtering will redraw for us */
1475
- _fnFilterComplete( oSettings, oSettings.oPreviousSearch );
1476
- }
1477
- else
1478
- {
1479
- _fnCalculateEnd( oSettings );
1480
- _fnDraw( oSettings );
1481
- }
1482
- }
1483
-
1484
-
1485
- /**
1486
- * Add the options to the page HTML for the table
1487
- * @param {object} oSettings dataTables settings object
1488
- * @memberof DataTable#oApi
1489
- */
1490
- function _fnAddOptionsHtml ( oSettings )
1491
- {
1492
- /*
1493
- * Create a temporary, empty, div which we can later on replace with what we have generated
1494
- * we do it this way to rendering the 'options' html offline - speed :-)
1495
- */
1496
- var nHolding = $('<div></div>')[0];
1497
- oSettings.nTable.parentNode.insertBefore( nHolding, oSettings.nTable );
1498
-
1499
- /*
1500
- * All DataTables are wrapped in a div
1501
- */
1502
- oSettings.nTableWrapper = $('<div id="'+oSettings.sTableId+'_wrapper" class="'+oSettings.oClasses.sWrapper+'" role="grid"></div>')[0];
1503
- oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
1504
-
1505
- /* Track where we want to insert the option */
1506
- var nInsertNode = oSettings.nTableWrapper;
1507
-
1508
- /* Loop over the user set positioning and place the elements as needed */
1509
- var aDom = oSettings.sDom.split('');
1510
- var nTmp, iPushFeature, cOption, nNewNode, cNext, sAttr, j;
1511
- for ( var i=0 ; i<aDom.length ; i++ )
1512
- {
1513
- iPushFeature = 0;
1514
- cOption = aDom[i];
1515
-
1516
- if ( cOption == '<' )
1517
- {
1518
- /* New container div */
1519
- nNewNode = $('<div></div>')[0];
1520
-
1521
- /* Check to see if we should append an id and/or a class name to the container */
1522
- cNext = aDom[i+1];
1523
- if ( cNext == "'" || cNext == '"' )
1524
- {
1525
- sAttr = "";
1526
- j = 2;
1527
- while ( aDom[i+j] != cNext )
1528
- {
1529
- sAttr += aDom[i+j];
1530
- j++;
1531
- }
1532
-
1533
- /* Replace jQuery UI constants */
1534
- if ( sAttr == "H" )
1535
- {
1536
- sAttr = "fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix";
1537
- }
1538
- else if ( sAttr == "F" )
1539
- {
1540
- sAttr = "fg-toolbar ui-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix";
1541
- }
1542
-
1543
- /* The attribute can be in the format of "#id.class", "#id" or "class" This logic
1544
- * breaks the string into parts and applies them as needed
1545
- */
1546
- if ( sAttr.indexOf('.') != -1 )
1547
- {
1548
- var aSplit = sAttr.split('.');
1549
- nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
1550
- nNewNode.className = aSplit[1];
1551
- }
1552
- else if ( sAttr.charAt(0) == "#" )
1553
- {
1554
- nNewNode.id = sAttr.substr(1, sAttr.length-1);
1555
- }
1556
- else
1557
- {
1558
- nNewNode.className = sAttr;
1559
- }
1560
-
1561
- i += j; /* Move along the position array */
1562
- }
1563
-
1564
- nInsertNode.appendChild( nNewNode );
1565
- nInsertNode = nNewNode;
1566
- }
1567
- else if ( cOption == '>' )
1568
- {
1569
- /* End container div */
1570
- nInsertNode = nInsertNode.parentNode;
1571
- }
1572
- else if ( cOption == 'l' && oSettings.oFeatures.bPaginate && oSettings.oFeatures.bLengthChange )
1573
- {
1574
- /* Length */
1575
- nTmp = _fnFeatureHtmlLength( oSettings );
1576
- iPushFeature = 1;
1577
- }
1578
- else if ( cOption == 'f' && oSettings.oFeatures.bFilter )
1579
- {
1580
- /* Filter */
1581
- nTmp = _fnFeatureHtmlFilter( oSettings );
1582
- iPushFeature = 1;
1583
- }
1584
- else if ( cOption == 'r' && oSettings.oFeatures.bProcessing )
1585
- {
1586
- /* pRocessing */
1587
- nTmp = _fnFeatureHtmlProcessing( oSettings );
1588
- iPushFeature = 1;
1589
- }
1590
- else if ( cOption == 't' )
1591
- {
1592
- /* Table */
1593
- nTmp = _fnFeatureHtmlTable( oSettings );
1594
- iPushFeature = 1;
1595
- }
1596
- else if ( cOption == 'i' && oSettings.oFeatures.bInfo )
1597
- {
1598
- /* Info */
1599
- nTmp = _fnFeatureHtmlInfo( oSettings );
1600
- iPushFeature = 1;
1601
- }
1602
- else if ( cOption == 'p' && oSettings.oFeatures.bPaginate )
1603
- {
1604
- /* Pagination */
1605
- nTmp = _fnFeatureHtmlPaginate( oSettings );
1606
- iPushFeature = 1;
1607
- }
1608
- else if ( DataTable.ext.aoFeatures.length !== 0 )
1609
- {
1610
- /* Plug-in features */
1611
- var aoFeatures = DataTable.ext.aoFeatures;
1612
- for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
1613
- {
1614
- if ( cOption == aoFeatures[k].cFeature )
1615
- {
1616
- nTmp = aoFeatures[k].fnInit( oSettings );
1617
- if ( nTmp )
1618
- {
1619
- iPushFeature = 1;
1620
- }
1621
- break;
1622
- }
1623
- }
1624
- }
1625
-
1626
- /* Add to the 2D features array */
1627
- if ( iPushFeature == 1 && nTmp !== null )
1628
- {
1629
- if ( typeof oSettings.aanFeatures[cOption] !== 'object' )
1630
- {
1631
- oSettings.aanFeatures[cOption] = [];
1632
- }
1633
- oSettings.aanFeatures[cOption].push( nTmp );
1634
- nInsertNode.appendChild( nTmp );
1635
- }
1636
- }
1637
-
1638
- /* Built our DOM structure - replace the holding div with what we want */
1639
- nHolding.parentNode.replaceChild( oSettings.nTableWrapper, nHolding );
1640
- }
1641
-
1642
-
1643
- /**
1644
- * Use the DOM source to create up an array of header cells. The idea here is to
1645
- * create a layout grid (array) of rows x columns, which contains a reference
1646
- * to the cell that that point in the grid (regardless of col/rowspan), such that
1647
- * any column / row could be removed and the new grid constructed
1648
- * @param array {object} aLayout Array to store the calculated layout in
1649
- * @param {node} nThead The header/footer element for the table
1650
- * @memberof DataTable#oApi
1651
- */
1652
- function _fnDetectHeader ( aLayout, nThead )
1653
- {
1654
- var nTrs = $(nThead).children('tr');
1655
- var nCell;
1656
- var i, j, k, l, iLen, jLen, iColShifted;
1657
- var fnShiftCol = function ( a, i, j ) {
1658
- while ( a[i][j] ) {
1659
- j++;
1660
- }
1661
- return j;
1662
- };
1663
-
1664
- aLayout.splice( 0, aLayout.length );
1665
-
1666
- /* We know how many rows there are in the layout - so prep it */
1667
- for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
1668
- {
1669
- aLayout.push( [] );
1670
- }
1671
-
1672
- /* Calculate a layout array */
1673
- for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
1674
- {
1675
- var iColumn = 0;
1676
-
1677
- /* For every cell in the row... */
1678
- for ( j=0, jLen=nTrs[i].childNodes.length ; j<jLen ; j++ )
1679
- {
1680
- nCell = nTrs[i].childNodes[j];
1681
-
1682
- if ( nCell.nodeName.toUpperCase() == "TD" ||
1683
- nCell.nodeName.toUpperCase() == "TH" )
1684
- {
1685
- /* Get the col and rowspan attributes from the DOM and sanitise them */
1686
- var iColspan = nCell.getAttribute('colspan') * 1;
1687
- var iRowspan = nCell.getAttribute('rowspan') * 1;
1688
- iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
1689
- iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
1690
-
1691
- /* There might be colspan cells already in this row, so shift our target
1692
- * accordingly
1693
- */
1694
- iColShifted = fnShiftCol( aLayout, i, iColumn );
1695
-
1696
- /* If there is col / rowspan, copy the information into the layout grid */
1697
- for ( l=0 ; l<iColspan ; l++ )
1698
- {
1699
- for ( k=0 ; k<iRowspan ; k++ )
1700
- {
1701
- aLayout[i+k][iColShifted+l] = {
1702
- "cell": nCell,
1703
- "unique": iColspan == 1 ? true : false
1704
- };
1705
- aLayout[i+k].nTr = nTrs[i];
1706
- }
1707
- }
1708
- }
1709
- }
1710
- }
1711
- }
1712
-
1713
-
1714
- /**
1715
- * Get an array of unique th elements, one for each column
1716
- * @param {object} oSettings dataTables settings object
1717
- * @param {node} nHeader automatically detect the layout from this node - optional
1718
- * @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
1719
- * @returns array {node} aReturn list of unique ths
1720
- * @memberof DataTable#oApi
1721
- */
1722
- function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
1723
- {
1724
- var aReturn = [];
1725
- if ( !aLayout )
1726
- {
1727
- aLayout = oSettings.aoHeader;
1728
- if ( nHeader )
1729
- {
1730
- aLayout = [];
1731
- _fnDetectHeader( aLayout, nHeader );
1732
- }
1733
- }
1734
-
1735
- for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
1736
- {
1737
- for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
1738
- {
1739
- if ( aLayout[i][j].unique &&
1740
- (!aReturn[j] || !oSettings.bSortCellsTop) )
1741
- {
1742
- aReturn[j] = aLayout[i][j].cell;
1743
- }
1744
- }
1745
- }
1746
-
1747
- return aReturn;
1748
- }
1749
-
1750
-
1751
-
1752
- /**
1753
- * Update the table using an Ajax call
1754
- * @param {object} oSettings dataTables settings object
1755
- * @returns {boolean} Block the table drawing or not
1756
- * @memberof DataTable#oApi
1757
- */
1758
- function _fnAjaxUpdate( oSettings )
1759
- {
1760
- if ( oSettings.bAjaxDataGet )
1761
- {
1762
- oSettings.iDraw++;
1763
- _fnProcessingDisplay( oSettings, true );
1764
- var iColumns = oSettings.aoColumns.length;
1765
- var aoData = _fnAjaxParameters( oSettings );
1766
- _fnServerParams( oSettings, aoData );
1767
-
1768
- oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aoData,
1769
- function(json) {
1770
- _fnAjaxUpdateDraw( oSettings, json );
1771
- }, oSettings );
1772
- return false;
1773
- }
1774
- else
1775
- {
1776
- return true;
1777
- }
1778
- }
1779
-
1780
-
1781
- /**
1782
- * Build up the parameters in an object needed for a server-side processing request
1783
- * @param {object} oSettings dataTables settings object
1784
- * @returns {bool} block the table drawing or not
1785
- * @memberof DataTable#oApi
1786
- */
1787
- function _fnAjaxParameters( oSettings )
1788
- {
1789
- var iColumns = oSettings.aoColumns.length;
1790
- var aoData = [], mDataProp;
1791
- var i;
1792
-
1793
- aoData.push( { "name": "sEcho", "value": oSettings.iDraw } );
1794
- aoData.push( { "name": "iColumns", "value": iColumns } );
1795
- aoData.push( { "name": "sColumns", "value": _fnColumnOrdering(oSettings) } );
1796
- aoData.push( { "name": "iDisplayStart", "value": oSettings._iDisplayStart } );
1797
- aoData.push( { "name": "iDisplayLength", "value": oSettings.oFeatures.bPaginate !== false ?
1798
- oSettings._iDisplayLength : -1 } );
1799
-
1800
- for ( i=0 ; i<iColumns ; i++ )
1801
- {
1802
- mDataProp = oSettings.aoColumns[i].mDataProp;
1803
- aoData.push( { "name": "mDataProp_"+i, "value": typeof(mDataProp)==="function" ? 'function' : mDataProp } );
1804
- }
1805
-
1806
- /* Filtering */
1807
- if ( oSettings.oFeatures.bFilter !== false )
1808
- {
1809
- aoData.push( { "name": "sSearch", "value": oSettings.oPreviousSearch.sSearch } );
1810
- aoData.push( { "name": "bRegex", "value": oSettings.oPreviousSearch.bRegex } );
1811
- for ( i=0 ; i<iColumns ; i++ )
1812
- {
1813
- aoData.push( { "name": "sSearch_"+i, "value": oSettings.aoPreSearchCols[i].sSearch } );
1814
- aoData.push( { "name": "bRegex_"+i, "value": oSettings.aoPreSearchCols[i].bRegex } );
1815
- aoData.push( { "name": "bSearchable_"+i, "value": oSettings.aoColumns[i].bSearchable } );
1816
- }
1817
- }
1818
-
1819
- /* Sorting */
1820
- if ( oSettings.oFeatures.bSort !== false )
1821
- {
1822
- var iFixed = oSettings.aaSortingFixed !== null ? oSettings.aaSortingFixed.length : 0;
1823
- var iUser = oSettings.aaSorting.length;
1824
- aoData.push( { "name": "iSortingCols", "value": iFixed+iUser } );
1825
- for ( i=0 ; i<iFixed ; i++ )
1826
- {
1827
- aoData.push( { "name": "iSortCol_"+i, "value": oSettings.aaSortingFixed[i][0] } );
1828
- aoData.push( { "name": "sSortDir_"+i, "value": oSettings.aaSortingFixed[i][1] } );
1829
- }
1830
-
1831
- for ( i=0 ; i<iUser ; i++ )
1832
- {
1833
- aoData.push( { "name": "iSortCol_"+(i+iFixed), "value": oSettings.aaSorting[i][0] } );
1834
- aoData.push( { "name": "sSortDir_"+(i+iFixed), "value": oSettings.aaSorting[i][1] } );
1835
- }
1836
-
1837
- for ( i=0 ; i<iColumns ; i++ )
1838
- {
1839
- aoData.push( { "name": "bSortable_"+i, "value": oSettings.aoColumns[i].bSortable } );
1840
- }
1841
- }
1842
-
1843
- return aoData;
1844
- }
1845
-
1846
-
1847
- /**
1848
- * Add Ajax parameters from plugins
1849
- * @param {object} oSettings dataTables settings object
1850
- * @param array {objects} aoData name/value pairs to send to the server
1851
- * @memberof DataTable#oApi
1852
- */
1853
- function _fnServerParams( oSettings, aoData )
1854
- {
1855
- _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [aoData] );
1856
- }
1857
-
1858
-
1859
- /**
1860
- * Data the data from the server (nuking the old) and redraw the table
1861
- * @param {object} oSettings dataTables settings object
1862
- * @param {object} json json data return from the server.
1863
- * @param {string} json.sEcho Tracking flag for DataTables to match requests
1864
- * @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
1865
- * @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
1866
- * @param {array} json.aaData The data to display on this page
1867
- * @param {string} [json.sColumns] Column ordering (sName, comma separated)
1868
- * @memberof DataTable#oApi
1869
- */
1870
- function _fnAjaxUpdateDraw ( oSettings, json )
1871
- {
1872
- if ( json.sEcho !== undefined )
1873
- {
1874
- /* Protect against old returns over-writing a new one. Possible when you get
1875
- * very fast interaction, and later queires are completed much faster
1876
- */
1877
- if ( json.sEcho*1 < oSettings.iDraw )
1878
- {
1879
- return;
1880
- }
1881
- else
1882
- {
1883
- oSettings.iDraw = json.sEcho * 1;
1884
- }
1885
- }
1886
-
1887
- if ( !oSettings.oScroll.bInfinite ||
1888
- (oSettings.oScroll.bInfinite && (oSettings.bSorted || oSettings.bFiltered)) )
1889
- {
1890
- _fnClearTable( oSettings );
1891
- }
1892
- oSettings._iRecordsTotal = parseInt(json.iTotalRecords, 10);
1893
- oSettings._iRecordsDisplay = parseInt(json.iTotalDisplayRecords, 10);
1894
-
1895
- /* Determine if reordering is required */
1896
- var sOrdering = _fnColumnOrdering(oSettings);
1897
- var bReOrder = (json.sColumns !== undefined && sOrdering !== "" && json.sColumns != sOrdering );
1898
- var aiIndex;
1899
- if ( bReOrder )
1900
- {
1901
- aiIndex = _fnReOrderIndex( oSettings, json.sColumns );
1902
- }
1903
-
1904
- var aData = _fnGetObjectDataFn( oSettings.sAjaxDataProp )( json );
1905
- for ( var i=0, iLen=aData.length ; i<iLen ; i++ )
1906
- {
1907
- if ( bReOrder )
1908
- {
1909
- /* If we need to re-order, then create a new array with the correct order and add it */
1910
- var aDataSorted = [];
1911
- for ( var j=0, jLen=oSettings.aoColumns.length ; j<jLen ; j++ )
1912
- {
1913
- aDataSorted.push( aData[i][ aiIndex[j] ] );
1914
- }