jquery-datatables 1.10.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +27 -0
  5. data/README.md +118 -0
  6. data/Rakefile +166 -0
  7. data/app/assets/images/datatables/sort_asc.png +0 -0
  8. data/app/assets/images/datatables/sort_asc_disabled.png +0 -0
  9. data/app/assets/images/datatables/sort_both.png +0 -0
  10. data/app/assets/images/datatables/sort_desc.png +0 -0
  11. data/app/assets/images/datatables/sort_desc_disabled.png +0 -0
  12. data/app/assets/javascripts/datatables/dataTables.bootstrap.js +182 -0
  13. data/app/assets/javascripts/datatables/dataTables.bootstrap4.js +184 -0
  14. data/app/assets/javascripts/datatables/dataTables.foundation.js +174 -0
  15. data/app/assets/javascripts/datatables/dataTables.jqueryui.js +164 -0
  16. data/app/assets/javascripts/datatables/dataTables.material.js +191 -0
  17. data/app/assets/javascripts/datatables/dataTables.semanticui.js +208 -0
  18. data/app/assets/javascripts/datatables/dataTables.uikit.js +176 -0
  19. data/app/assets/javascripts/datatables/extensions/AutoFill/autoFill.bootstrap.js +43 -0
  20. data/app/assets/javascripts/datatables/extensions/AutoFill/autoFill.bootstrap4.js +43 -0
  21. data/app/assets/javascripts/datatables/extensions/AutoFill/autoFill.foundation.js +43 -0
  22. data/app/assets/javascripts/datatables/extensions/AutoFill/autoFill.jqueryui.js +43 -0
  23. data/app/assets/javascripts/datatables/extensions/AutoFill/autoFill.semanticui.js +43 -0
  24. data/app/assets/javascripts/datatables/extensions/AutoFill/dataTables.autoFill.js +1036 -0
  25. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.bootstrap.js +68 -0
  26. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.bootstrap4.js +60 -0
  27. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.colVis.js +199 -0
  28. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.flash.js +1325 -0
  29. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.foundation.js +85 -0
  30. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.html5.js +1322 -0
  31. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.jqueryui.js +62 -0
  32. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.print.js +172 -0
  33. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.semanticui.js +57 -0
  34. data/app/assets/javascripts/datatables/extensions/Buttons/dataTables.buttons.js +1634 -0
  35. data/app/assets/javascripts/datatables/extensions/ColReorder/dataTables.colReorder.js +1335 -0
  36. data/app/assets/javascripts/datatables/extensions/FixedColumns/dataTables.fixedColumns.js +1623 -0
  37. data/app/assets/javascripts/datatables/extensions/FixedHeader/dataTables.fixedHeader.js +672 -0
  38. data/app/assets/javascripts/datatables/extensions/KeyTable/dataTables.keyTable.js +883 -0
  39. data/app/assets/javascripts/datatables/extensions/Responsive/dataTables.responsive.js +1232 -0
  40. data/app/assets/javascripts/datatables/extensions/Responsive/responsive.bootstrap.js +81 -0
  41. data/app/assets/javascripts/datatables/extensions/Responsive/responsive.bootstrap4.js +81 -0
  42. data/app/assets/javascripts/datatables/extensions/Responsive/responsive.foundation.js +62 -0
  43. data/app/assets/javascripts/datatables/extensions/Responsive/responsive.jqueryui.js +63 -0
  44. data/app/assets/javascripts/datatables/extensions/Responsive/responsive.semanticui.js +77 -0
  45. data/app/assets/javascripts/datatables/extensions/RowReorder/dataTables.rowReorder.js +709 -0
  46. data/app/assets/javascripts/datatables/extensions/Scroller/dataTables.scroller.js +1349 -0
  47. data/app/assets/javascripts/datatables/extensions/Select/dataTables.select.js +1109 -0
  48. data/app/assets/javascripts/datatables/jquery.dataTables.js +15278 -0
  49. data/app/assets/media/swf/flashExport.swf +0 -0
  50. data/app/assets/stylesheets/datatables/dataTables.bootstrap.css +185 -0
  51. data/app/assets/stylesheets/datatables/dataTables.bootstrap4.css +193 -0
  52. data/app/assets/stylesheets/datatables/dataTables.foundation.css +116 -0
  53. data/app/assets/stylesheets/datatables/dataTables.jqueryui.css +481 -0
  54. data/app/assets/stylesheets/datatables/dataTables.material.css +87 -0
  55. data/app/assets/stylesheets/datatables/dataTables.semanticui.css +103 -0
  56. data/app/assets/stylesheets/datatables/dataTables.uikit.css +146 -0
  57. data/app/assets/stylesheets/datatables/extensions/AutoFill/autoFill.bootstrap.css +81 -0
  58. data/app/assets/stylesheets/datatables/extensions/AutoFill/autoFill.bootstrap4.css +81 -0
  59. data/app/assets/stylesheets/datatables/extensions/AutoFill/autoFill.dataTables.css +92 -0
  60. data/app/assets/stylesheets/datatables/extensions/AutoFill/autoFill.foundation.css +85 -0
  61. data/app/assets/stylesheets/datatables/extensions/AutoFill/autoFill.jqueryui.css +85 -0
  62. data/app/assets/stylesheets/datatables/extensions/AutoFill/autoFill.semanticui.css +81 -0
  63. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.bootstrap.css +102 -0
  64. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.bootstrap4.css +163 -0
  65. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.dataTables.css +298 -0
  66. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.foundation.css +129 -0
  67. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.jqueryui.css +162 -0
  68. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.semanticui.css +114 -0
  69. data/app/assets/stylesheets/datatables/extensions/Buttons/common.scss +27 -0
  70. data/app/assets/stylesheets/datatables/extensions/Buttons/mixins.scss +89 -0
  71. data/app/assets/stylesheets/datatables/extensions/ColReorder/colReorder.bootstrap.css +11 -0
  72. data/app/assets/stylesheets/datatables/extensions/ColReorder/colReorder.bootstrap4.css +11 -0
  73. data/app/assets/stylesheets/datatables/extensions/ColReorder/colReorder.dataTables.css +11 -0
  74. data/app/assets/stylesheets/datatables/extensions/ColReorder/colReorder.foundation.css +11 -0
  75. data/app/assets/stylesheets/datatables/extensions/ColReorder/colReorder.jqueryui.css +11 -0
  76. data/app/assets/stylesheets/datatables/extensions/ColReorder/colReorder.semanticui.css +11 -0
  77. data/app/assets/stylesheets/datatables/extensions/FixedColumns/fixedColumns.bootstrap.css +44 -0
  78. data/app/assets/stylesheets/datatables/extensions/FixedColumns/fixedColumns.bootstrap4.css +44 -0
  79. data/app/assets/stylesheets/datatables/extensions/FixedColumns/fixedColumns.dataTables.css +18 -0
  80. data/app/assets/stylesheets/datatables/extensions/FixedColumns/fixedColumns.foundation.css +27 -0
  81. data/app/assets/stylesheets/datatables/extensions/FixedColumns/fixedColumns.jqueryui.css +8 -0
  82. data/app/assets/stylesheets/datatables/extensions/FixedColumns/fixedColumns.semanticui.css +16 -0
  83. data/app/assets/stylesheets/datatables/extensions/FixedHeader/fixedHeader.bootstrap.css +20 -0
  84. data/app/assets/stylesheets/datatables/extensions/FixedHeader/fixedHeader.bootstrap4.css +20 -0
  85. data/app/assets/stylesheets/datatables/extensions/FixedHeader/fixedHeader.dataTables.css +19 -0
  86. data/app/assets/stylesheets/datatables/extensions/FixedHeader/fixedHeader.foundation.css +20 -0
  87. data/app/assets/stylesheets/datatables/extensions/FixedHeader/fixedHeader.jqueryui.css +15 -0
  88. data/app/assets/stylesheets/datatables/extensions/FixedHeader/fixedHeader.semanticui.css +14 -0
  89. data/app/assets/stylesheets/datatables/extensions/KeyTable/keyTable.bootstrap.css +5 -0
  90. data/app/assets/stylesheets/datatables/extensions/KeyTable/keyTable.bootstrap4.css +5 -0
  91. data/app/assets/stylesheets/datatables/extensions/KeyTable/keyTable.dataTables.css +5 -0
  92. data/app/assets/stylesheets/datatables/extensions/KeyTable/keyTable.foundation.css +5 -0
  93. data/app/assets/stylesheets/datatables/extensions/KeyTable/keyTable.jqueryui.css +5 -0
  94. data/app/assets/stylesheets/datatables/extensions/KeyTable/keyTable.semanticui.css +5 -0
  95. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.bootstrap.css +181 -0
  96. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.bootstrap4.css +181 -0
  97. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.dataTables.css +178 -0
  98. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.foundation.css +181 -0
  99. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.jqueryui.css +178 -0
  100. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.semanticui.css +181 -0
  101. data/app/assets/stylesheets/datatables/extensions/RowReorder/rowReorder.bootstrap.css +22 -0
  102. data/app/assets/stylesheets/datatables/extensions/RowReorder/rowReorder.bootstrap4.css +22 -0
  103. data/app/assets/stylesheets/datatables/extensions/RowReorder/rowReorder.dataTables.css +22 -0
  104. data/app/assets/stylesheets/datatables/extensions/RowReorder/rowReorder.foundation.css +22 -0
  105. data/app/assets/stylesheets/datatables/extensions/RowReorder/rowReorder.jqueryui.css +22 -0
  106. data/app/assets/stylesheets/datatables/extensions/RowReorder/rowReorder.semanticui.css +22 -0
  107. data/app/assets/stylesheets/datatables/extensions/RowReorder/semanticui.scss +5 -0
  108. data/app/assets/stylesheets/datatables/extensions/Scroller/scroller.bootstrap.css +24 -0
  109. data/app/assets/stylesheets/datatables/extensions/Scroller/scroller.bootstrap4.css +24 -0
  110. data/app/assets/stylesheets/datatables/extensions/Scroller/scroller.dataTables.css +20 -0
  111. data/app/assets/stylesheets/datatables/extensions/Scroller/scroller.foundation.css +17 -0
  112. data/app/assets/stylesheets/datatables/extensions/Scroller/scroller.jqueryui.css +20 -0
  113. data/app/assets/stylesheets/datatables/extensions/Scroller/scroller.semanticui.css +20 -0
  114. data/app/assets/stylesheets/datatables/extensions/Select/select.bootstrap.css +110 -0
  115. data/app/assets/stylesheets/datatables/extensions/Select/select.bootstrap4.css +110 -0
  116. data/app/assets/stylesheets/datatables/extensions/Select/select.dataTables.css +100 -0
  117. data/app/assets/stylesheets/datatables/extensions/Select/select.foundation.css +112 -0
  118. data/app/assets/stylesheets/datatables/extensions/Select/select.jqueryui.css +100 -0
  119. data/app/assets/stylesheets/datatables/extensions/Select/select.semanticui.css +105 -0
  120. data/app/assets/stylesheets/datatables/jquery.dataTables.css +452 -0
  121. data/app/assets/stylesheets/datatables/jquery.dataTables_themeroller.css +416 -0
  122. data/jquery-datatables.gemspec +27 -0
  123. data/lib/generators/jquery/datatables/install_generator.rb +63 -0
  124. data/lib/generators/jquery/datatables/templates/bootstrap.css.tt +15 -0
  125. data/lib/generators/jquery/datatables/templates/bootstrap.js.tt +22 -0
  126. data/lib/generators/jquery/datatables/templates/bootstrap4.css.tt +15 -0
  127. data/lib/generators/jquery/datatables/templates/bootstrap4.js.tt +22 -0
  128. data/lib/generators/jquery/datatables/templates/foundation.css.tt +15 -0
  129. data/lib/generators/jquery/datatables/templates/foundation.js.tt +24 -0
  130. data/lib/generators/jquery/datatables/templates/jqueryui.css.tt +15 -0
  131. data/lib/generators/jquery/datatables/templates/jqueryui.js.tt +18 -0
  132. data/lib/generators/jquery/datatables/templates/material.css.tt +15 -0
  133. data/lib/generators/jquery/datatables/templates/material.js.tt +19 -0
  134. data/lib/generators/jquery/datatables/templates/regular.css.tt +15 -0
  135. data/lib/generators/jquery/datatables/templates/regular.js.tt +18 -0
  136. data/lib/generators/jquery/datatables/templates/semanticui.css.tt +16 -0
  137. data/lib/generators/jquery/datatables/templates/semanticui.js.tt +22 -0
  138. data/lib/generators/jquery/datatables/templates/uikit.css.tt +15 -0
  139. data/lib/generators/jquery/datatables/templates/uikit.js.tt +19 -0
  140. data/lib/jquery-datatables.rb +26 -0
  141. data/lib/jquery-datatables/engine.rb +11 -0
  142. data/lib/jquery-datatables/version.rb +6 -0
  143. metadata +269 -0
@@ -0,0 +1,1623 @@
1
+ /*! FixedColumns 3.2.2
2
+ * ©2010-2016 SpryMedia Ltd - datatables.net/license
3
+ */
4
+
5
+ /**
6
+ * @summary FixedColumns
7
+ * @description Freeze columns in place on a scrolling DataTable
8
+ * @version 3.2.2
9
+ * @file dataTables.fixedColumns.js
10
+ * @author SpryMedia Ltd (www.sprymedia.co.uk)
11
+ * @contact www.sprymedia.co.uk/contact
12
+ * @copyright Copyright 2010-2016 SpryMedia Ltd.
13
+ *
14
+ * This source file is free software, available under the following license:
15
+ * MIT license - http://datatables.net/license/mit
16
+ *
17
+ * This source file is distributed in the hope that it will be useful, but
18
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
20
+ *
21
+ * For details please refer to: http://www.datatables.net
22
+ */
23
+ (function( factory ){
24
+ if ( typeof define === 'function' && define.amd ) {
25
+ // AMD
26
+ define( ['jquery', 'datatables.net'], function ( $ ) {
27
+ return factory( $, window, document );
28
+ } );
29
+ }
30
+ else if ( typeof exports === 'object' ) {
31
+ // CommonJS
32
+ module.exports = function (root, $) {
33
+ if ( ! root ) {
34
+ root = window;
35
+ }
36
+
37
+ if ( ! $ || ! $.fn.dataTable ) {
38
+ $ = require('datatables.net')(root, $).$;
39
+ }
40
+
41
+ return factory( $, root, root.document );
42
+ };
43
+ }
44
+ else {
45
+ // Browser
46
+ factory( jQuery, window, document );
47
+ }
48
+ }(function( $, window, document, undefined ) {
49
+ 'use strict';
50
+ var DataTable = $.fn.dataTable;
51
+ var _firefoxScroll;
52
+
53
+ /**
54
+ * When making use of DataTables' x-axis scrolling feature, you may wish to
55
+ * fix the left most column in place. This plug-in for DataTables provides
56
+ * exactly this option (note for non-scrolling tables, please use the
57
+ * FixedHeader plug-in, which can fix headers, footers and columns). Key
58
+ * features include:
59
+ *
60
+ * * Freezes the left or right most columns to the side of the table
61
+ * * Option to freeze two or more columns
62
+ * * Full integration with DataTables' scrolling options
63
+ * * Speed - FixedColumns is fast in its operation
64
+ *
65
+ * @class
66
+ * @constructor
67
+ * @global
68
+ * @param {object} dt DataTables instance. With DataTables 1.10 this can also
69
+ * be a jQuery collection, a jQuery selector, DataTables API instance or
70
+ * settings object.
71
+ * @param {object} [init={}] Configuration object for FixedColumns. Options are
72
+ * defined by {@link FixedColumns.defaults}
73
+ *
74
+ * @requires jQuery 1.7+
75
+ * @requires DataTables 1.8.0+
76
+ *
77
+ * @example
78
+ * var table = $('#example').dataTable( {
79
+ * "scrollX": "100%"
80
+ * } );
81
+ * new $.fn.dataTable.fixedColumns( table );
82
+ */
83
+ var FixedColumns = function ( dt, init ) {
84
+ var that = this;
85
+
86
+ /* Sanity check - you just know it will happen */
87
+ if ( ! ( this instanceof FixedColumns ) ) {
88
+ alert( "FixedColumns warning: FixedColumns must be initialised with the 'new' keyword." );
89
+ return;
90
+ }
91
+
92
+ if ( init === undefined || init === true ) {
93
+ init = {};
94
+ }
95
+
96
+ // Use the DataTables Hungarian notation mapping method, if it exists to
97
+ // provide forwards compatibility for camel case variables
98
+ var camelToHungarian = $.fn.dataTable.camelToHungarian;
99
+ if ( camelToHungarian ) {
100
+ camelToHungarian( FixedColumns.defaults, FixedColumns.defaults, true );
101
+ camelToHungarian( FixedColumns.defaults, init );
102
+ }
103
+
104
+ // v1.10 allows the settings object to be got form a number of sources
105
+ var dtSettings = new $.fn.dataTable.Api( dt ).settings()[0];
106
+
107
+ /**
108
+ * Settings object which contains customisable information for FixedColumns instance
109
+ * @namespace
110
+ * @extends FixedColumns.defaults
111
+ * @private
112
+ */
113
+ this.s = {
114
+ /**
115
+ * DataTables settings objects
116
+ * @type object
117
+ * @default Obtained from DataTables instance
118
+ */
119
+ "dt": dtSettings,
120
+
121
+ /**
122
+ * Number of columns in the DataTable - stored for quick access
123
+ * @type int
124
+ * @default Obtained from DataTables instance
125
+ */
126
+ "iTableColumns": dtSettings.aoColumns.length,
127
+
128
+ /**
129
+ * Original outer widths of the columns as rendered by DataTables - used to calculate
130
+ * the FixedColumns grid bounding box
131
+ * @type array.<int>
132
+ * @default []
133
+ */
134
+ "aiOuterWidths": [],
135
+
136
+ /**
137
+ * Original inner widths of the columns as rendered by DataTables - used to apply widths
138
+ * to the columns
139
+ * @type array.<int>
140
+ * @default []
141
+ */
142
+ "aiInnerWidths": [],
143
+
144
+
145
+ /**
146
+ * Is the document layout right-to-left
147
+ * @type boolean
148
+ */
149
+ rtl: $(dtSettings.nTable).css('direction') === 'rtl'
150
+ };
151
+
152
+
153
+ /**
154
+ * DOM elements used by the class instance
155
+ * @namespace
156
+ * @private
157
+ *
158
+ */
159
+ this.dom = {
160
+ /**
161
+ * DataTables scrolling element
162
+ * @type node
163
+ * @default null
164
+ */
165
+ "scroller": null,
166
+
167
+ /**
168
+ * DataTables header table
169
+ * @type node
170
+ * @default null
171
+ */
172
+ "header": null,
173
+
174
+ /**
175
+ * DataTables body table
176
+ * @type node
177
+ * @default null
178
+ */
179
+ "body": null,
180
+
181
+ /**
182
+ * DataTables footer table
183
+ * @type node
184
+ * @default null
185
+ */
186
+ "footer": null,
187
+
188
+ /**
189
+ * Display grid elements
190
+ * @namespace
191
+ */
192
+ "grid": {
193
+ /**
194
+ * Grid wrapper. This is the container element for the 3x3 grid
195
+ * @type node
196
+ * @default null
197
+ */
198
+ "wrapper": null,
199
+
200
+ /**
201
+ * DataTables scrolling element. This element is the DataTables
202
+ * component in the display grid (making up the main table - i.e.
203
+ * not the fixed columns).
204
+ * @type node
205
+ * @default null
206
+ */
207
+ "dt": null,
208
+
209
+ /**
210
+ * Left fixed column grid components
211
+ * @namespace
212
+ */
213
+ "left": {
214
+ "wrapper": null,
215
+ "head": null,
216
+ "body": null,
217
+ "foot": null
218
+ },
219
+
220
+ /**
221
+ * Right fixed column grid components
222
+ * @namespace
223
+ */
224
+ "right": {
225
+ "wrapper": null,
226
+ "head": null,
227
+ "body": null,
228
+ "foot": null
229
+ }
230
+ },
231
+
232
+ /**
233
+ * Cloned table nodes
234
+ * @namespace
235
+ */
236
+ "clone": {
237
+ /**
238
+ * Left column cloned table nodes
239
+ * @namespace
240
+ */
241
+ "left": {
242
+ /**
243
+ * Cloned header table
244
+ * @type node
245
+ * @default null
246
+ */
247
+ "header": null,
248
+
249
+ /**
250
+ * Cloned body table
251
+ * @type node
252
+ * @default null
253
+ */
254
+ "body": null,
255
+
256
+ /**
257
+ * Cloned footer table
258
+ * @type node
259
+ * @default null
260
+ */
261
+ "footer": null
262
+ },
263
+
264
+ /**
265
+ * Right column cloned table nodes
266
+ * @namespace
267
+ */
268
+ "right": {
269
+ /**
270
+ * Cloned header table
271
+ * @type node
272
+ * @default null
273
+ */
274
+ "header": null,
275
+
276
+ /**
277
+ * Cloned body table
278
+ * @type node
279
+ * @default null
280
+ */
281
+ "body": null,
282
+
283
+ /**
284
+ * Cloned footer table
285
+ * @type node
286
+ * @default null
287
+ */
288
+ "footer": null
289
+ }
290
+ }
291
+ };
292
+
293
+ if ( dtSettings._oFixedColumns ) {
294
+ throw 'FixedColumns already initialised on this table';
295
+ }
296
+
297
+ /* Attach the instance to the DataTables instance so it can be accessed easily */
298
+ dtSettings._oFixedColumns = this;
299
+
300
+ /* Let's do it */
301
+ if ( ! dtSettings._bInitComplete )
302
+ {
303
+ dtSettings.oApi._fnCallbackReg( dtSettings, 'aoInitComplete', function () {
304
+ that._fnConstruct( init );
305
+ }, 'FixedColumns' );
306
+ }
307
+ else
308
+ {
309
+ this._fnConstruct( init );
310
+ }
311
+ };
312
+
313
+
314
+
315
+ $.extend( FixedColumns.prototype , {
316
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
317
+ * Public methods
318
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
319
+
320
+ /**
321
+ * Update the fixed columns - including headers and footers. Note that FixedColumns will
322
+ * automatically update the display whenever the host DataTable redraws.
323
+ * @returns {void}
324
+ * @example
325
+ * var table = $('#example').dataTable( {
326
+ * "scrollX": "100%"
327
+ * } );
328
+ * var fc = new $.fn.dataTable.fixedColumns( table );
329
+ *
330
+ * // at some later point when the table has been manipulated....
331
+ * fc.fnUpdate();
332
+ */
333
+ "fnUpdate": function ()
334
+ {
335
+ this._fnDraw( true );
336
+ },
337
+
338
+
339
+ /**
340
+ * Recalculate the resizes of the 3x3 grid that FixedColumns uses for display of the table.
341
+ * This is useful if you update the width of the table container. Note that FixedColumns will
342
+ * perform this function automatically when the window.resize event is fired.
343
+ * @returns {void}
344
+ * @example
345
+ * var table = $('#example').dataTable( {
346
+ * "scrollX": "100%"
347
+ * } );
348
+ * var fc = new $.fn.dataTable.fixedColumns( table );
349
+ *
350
+ * // Resize the table container and then have FixedColumns adjust its layout....
351
+ * $('#content').width( 1200 );
352
+ * fc.fnRedrawLayout();
353
+ */
354
+ "fnRedrawLayout": function ()
355
+ {
356
+ this._fnColCalc();
357
+ this._fnGridLayout();
358
+ this.fnUpdate();
359
+ },
360
+
361
+
362
+ /**
363
+ * Mark a row such that it's height should be recalculated when using 'semiauto' row
364
+ * height matching. This function will have no effect when 'none' or 'auto' row height
365
+ * matching is used.
366
+ * @param {Node} nTr TR element that should have it's height recalculated
367
+ * @returns {void}
368
+ * @example
369
+ * var table = $('#example').dataTable( {
370
+ * "scrollX": "100%"
371
+ * } );
372
+ * var fc = new $.fn.dataTable.fixedColumns( table );
373
+ *
374
+ * // manipulate the table - mark the row as needing an update then update the table
375
+ * // this allows the redraw performed by DataTables fnUpdate to recalculate the row
376
+ * // height
377
+ * fc.fnRecalculateHeight();
378
+ * table.fnUpdate( $('#example tbody tr:eq(0)')[0], ["insert date", 1, 2, 3 ... ]);
379
+ */
380
+ "fnRecalculateHeight": function ( nTr )
381
+ {
382
+ delete nTr._DTTC_iHeight;
383
+ nTr.style.height = 'auto';
384
+ },
385
+
386
+
387
+ /**
388
+ * Set the height of a given row - provides cross browser compatibility
389
+ * @param {Node} nTarget TR element that should have it's height recalculated
390
+ * @param {int} iHeight Height in pixels to set
391
+ * @returns {void}
392
+ * @example
393
+ * var table = $('#example').dataTable( {
394
+ * "scrollX": "100%"
395
+ * } );
396
+ * var fc = new $.fn.dataTable.fixedColumns( table );
397
+ *
398
+ * // You may want to do this after manipulating a row in the fixed column
399
+ * fc.fnSetRowHeight( $('#example tbody tr:eq(0)')[0], 50 );
400
+ */
401
+ "fnSetRowHeight": function ( nTarget, iHeight )
402
+ {
403
+ nTarget.style.height = iHeight+"px";
404
+ },
405
+
406
+
407
+ /**
408
+ * Get data index information about a row or cell in the table body.
409
+ * This function is functionally identical to fnGetPosition in DataTables,
410
+ * taking the same parameter (TH, TD or TR node) and returning exactly the
411
+ * the same information (data index information). THe difference between
412
+ * the two is that this method takes into account the fixed columns in the
413
+ * table, so you can pass in nodes from the master table, or the cloned
414
+ * tables and get the index position for the data in the main table.
415
+ * @param {node} node TR, TH or TD element to get the information about
416
+ * @returns {int} If nNode is given as a TR, then a single index is
417
+ * returned, or if given as a cell, an array of [row index, column index
418
+ * (visible), column index (all)] is given.
419
+ */
420
+ "fnGetPosition": function ( node )
421
+ {
422
+ var idx;
423
+ var inst = this.s.dt.oInstance;
424
+
425
+ if ( ! $(node).parents('.DTFC_Cloned').length )
426
+ {
427
+ // Not in a cloned table
428
+ return inst.fnGetPosition( node );
429
+ }
430
+ else
431
+ {
432
+ // Its in the cloned table, so need to look up position
433
+ if ( node.nodeName.toLowerCase() === 'tr' ) {
434
+ idx = $(node).index();
435
+ return inst.fnGetPosition( $('tr', this.s.dt.nTBody)[ idx ] );
436
+ }
437
+ else
438
+ {
439
+ var colIdx = $(node).index();
440
+ idx = $(node.parentNode).index();
441
+ var row = inst.fnGetPosition( $('tr', this.s.dt.nTBody)[ idx ] );
442
+
443
+ return [
444
+ row,
445
+ colIdx,
446
+ inst.oApi._fnVisibleToColumnIndex( this.s.dt, colIdx )
447
+ ];
448
+ }
449
+ }
450
+ },
451
+
452
+
453
+
454
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
455
+ * Private methods (they are of course public in JS, but recommended as private)
456
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
457
+
458
+ /**
459
+ * Initialisation for FixedColumns
460
+ * @param {Object} oInit User settings for initialisation
461
+ * @returns {void}
462
+ * @private
463
+ */
464
+ "_fnConstruct": function ( oInit )
465
+ {
466
+ var i, iLen, iWidth,
467
+ that = this;
468
+
469
+ /* Sanity checking */
470
+ if ( typeof this.s.dt.oInstance.fnVersionCheck != 'function' ||
471
+ this.s.dt.oInstance.fnVersionCheck( '1.8.0' ) !== true )
472
+ {
473
+ alert( "FixedColumns "+FixedColumns.VERSION+" required DataTables 1.8.0 or later. "+
474
+ "Please upgrade your DataTables installation" );
475
+ return;
476
+ }
477
+
478
+ if ( this.s.dt.oScroll.sX === "" )
479
+ {
480
+ this.s.dt.oInstance.oApi._fnLog( this.s.dt, 1, "FixedColumns is not needed (no "+
481
+ "x-scrolling in DataTables enabled), so no action will be taken. Use 'FixedHeader' for "+
482
+ "column fixing when scrolling is not enabled" );
483
+ return;
484
+ }
485
+
486
+ /* Apply the settings from the user / defaults */
487
+ this.s = $.extend( true, this.s, FixedColumns.defaults, oInit );
488
+
489
+ /* Set up the DOM as we need it and cache nodes */
490
+ var classes = this.s.dt.oClasses;
491
+ this.dom.grid.dt = $(this.s.dt.nTable).parents('div.'+classes.sScrollWrapper)[0];
492
+ this.dom.scroller = $('div.'+classes.sScrollBody, this.dom.grid.dt )[0];
493
+
494
+ /* Set up the DOM that we want for the fixed column layout grid */
495
+ this._fnColCalc();
496
+ this._fnGridSetup();
497
+
498
+ /* Event handlers */
499
+ var mouseController;
500
+ var mouseDown = false;
501
+
502
+ // When the mouse is down (drag scroll) the mouse controller cannot
503
+ // change, as the browser keeps the original element as the scrolling one
504
+ $(this.s.dt.nTableWrapper).on( 'mousedown.DTFC', function () {
505
+ mouseDown = true;
506
+
507
+ $(document).one( 'mouseup', function () {
508
+ mouseDown = false;
509
+ } );
510
+ } );
511
+
512
+ // When the body is scrolled - scroll the left and right columns
513
+ $(this.dom.scroller)
514
+ .on( 'mouseover.DTFC touchstart.DTFC', function () {
515
+ if ( ! mouseDown ) {
516
+ mouseController = 'main';
517
+ }
518
+ } )
519
+ .on( 'scroll.DTFC', function (e) {
520
+ if ( ! mouseController && e.originalEvent ) {
521
+ mouseController = 'main';
522
+ }
523
+
524
+ if ( mouseController === 'main' ) {
525
+ if ( that.s.iLeftColumns > 0 ) {
526
+ that.dom.grid.left.liner.scrollTop = that.dom.scroller.scrollTop;
527
+ }
528
+ if ( that.s.iRightColumns > 0 ) {
529
+ that.dom.grid.right.liner.scrollTop = that.dom.scroller.scrollTop;
530
+ }
531
+ }
532
+ } );
533
+
534
+ var wheelType = 'onwheel' in document.createElement('div') ?
535
+ 'wheel.DTFC' :
536
+ 'mousewheel.DTFC';
537
+
538
+ if ( that.s.iLeftColumns > 0 ) {
539
+ // When scrolling the left column, scroll the body and right column
540
+ $(that.dom.grid.left.liner)
541
+ .on( 'mouseover.DTFC touchstart.DTFC', function () {
542
+ if ( ! mouseDown ) {
543
+ mouseController = 'left';
544
+ }
545
+ } )
546
+ .on( 'scroll.DTFC', function ( e ) {
547
+ if ( ! mouseController && e.originalEvent ) {
548
+ mouseController = 'left';
549
+ }
550
+
551
+ if ( mouseController === 'left' ) {
552
+ that.dom.scroller.scrollTop = that.dom.grid.left.liner.scrollTop;
553
+ if ( that.s.iRightColumns > 0 ) {
554
+ that.dom.grid.right.liner.scrollTop = that.dom.grid.left.liner.scrollTop;
555
+ }
556
+ }
557
+ } )
558
+ .on( wheelType, function(e) {
559
+ // Pass horizontal scrolling through
560
+ var xDelta = e.type === 'wheel' ?
561
+ -e.originalEvent.deltaX :
562
+ e.originalEvent.wheelDeltaX;
563
+ that.dom.scroller.scrollLeft -= xDelta;
564
+ } );
565
+ }
566
+
567
+ if ( that.s.iRightColumns > 0 ) {
568
+ // When scrolling the right column, scroll the body and the left column
569
+ $(that.dom.grid.right.liner)
570
+ .on( 'mouseover.DTFC touchstart.DTFC', function () {
571
+ if ( ! mouseDown ) {
572
+ mouseController = 'right';
573
+ }
574
+ } )
575
+ .on( 'scroll.DTFC', function ( e ) {
576
+ if ( ! mouseController && e.originalEvent ) {
577
+ mouseController = 'right';
578
+ }
579
+
580
+ if ( mouseController === 'right' ) {
581
+ that.dom.scroller.scrollTop = that.dom.grid.right.liner.scrollTop;
582
+ if ( that.s.iLeftColumns > 0 ) {
583
+ that.dom.grid.left.liner.scrollTop = that.dom.grid.right.liner.scrollTop;
584
+ }
585
+ }
586
+ } )
587
+ .on( wheelType, function(e) {
588
+ // Pass horizontal scrolling through
589
+ var xDelta = e.type === 'wheel' ?
590
+ -e.originalEvent.deltaX :
591
+ e.originalEvent.wheelDeltaX;
592
+ that.dom.scroller.scrollLeft -= xDelta;
593
+ } );
594
+ }
595
+
596
+ $(window).on( 'resize.DTFC', function () {
597
+ that._fnGridLayout.call( that );
598
+ } );
599
+
600
+ var bFirstDraw = true;
601
+ var jqTable = $(this.s.dt.nTable);
602
+
603
+ jqTable
604
+ .on( 'draw.dt.DTFC', function () {
605
+ that._fnColCalc();
606
+ that._fnDraw.call( that, bFirstDraw );
607
+ bFirstDraw = false;
608
+ } )
609
+ .on( 'column-sizing.dt.DTFC', function () {
610
+ that._fnColCalc();
611
+ that._fnGridLayout( that );
612
+ } )
613
+ .on( 'column-visibility.dt.DTFC', function ( e, settings, column, vis, recalc ) {
614
+ if ( recalc === undefined || recalc ) {
615
+ that._fnColCalc();
616
+ that._fnGridLayout( that );
617
+ that._fnDraw( true );
618
+ }
619
+ } )
620
+ .on( 'select.dt.DTFC deselect.dt.DTFC', function ( e, dt, type, indexes ) {
621
+ if ( e.namespace === 'dt' ) {
622
+ that._fnDraw( false );
623
+ }
624
+ } )
625
+ .on( 'destroy.dt.DTFC', function () {
626
+ jqTable.off( '.DTFC' );
627
+
628
+ $(that.dom.scroller).off( '.DTFC' );
629
+ $(window).off( '.DTFC' );
630
+ $(that.s.dt.nTableWrapper).off( '.DTFC' );
631
+
632
+ $(that.dom.grid.left.liner).off( '.DTFC '+wheelType );
633
+ $(that.dom.grid.left.wrapper).remove();
634
+
635
+ $(that.dom.grid.right.liner).off( '.DTFC '+wheelType );
636
+ $(that.dom.grid.right.wrapper).remove();
637
+ } );
638
+
639
+ /* Get things right to start with - note that due to adjusting the columns, there must be
640
+ * another redraw of the main table. It doesn't need to be a full redraw however.
641
+ */
642
+ this._fnGridLayout();
643
+ this.s.dt.oInstance.fnDraw(false);
644
+ },
645
+
646
+
647
+ /**
648
+ * Calculate the column widths for the grid layout
649
+ * @returns {void}
650
+ * @private
651
+ */
652
+ "_fnColCalc": function ()
653
+ {
654
+ var that = this;
655
+ var iLeftWidth = 0;
656
+ var iRightWidth = 0;
657
+
658
+ this.s.aiInnerWidths = [];
659
+ this.s.aiOuterWidths = [];
660
+
661
+ $.each( this.s.dt.aoColumns, function (i, col) {
662
+ var th = $(col.nTh);
663
+ var border;
664
+
665
+ if ( ! th.filter(':visible').length ) {
666
+ that.s.aiInnerWidths.push( 0 );
667
+ that.s.aiOuterWidths.push( 0 );
668
+ }
669
+ else
670
+ {
671
+ // Inner width is used to assign widths to cells
672
+ // Outer width is used to calculate the container
673
+ var iWidth = th.outerWidth();
674
+
675
+ // When working with the left most-cell, need to add on the
676
+ // table's border to the outerWidth, since we need to take
677
+ // account of it, but it isn't in any cell
678
+ if ( that.s.aiOuterWidths.length === 0 ) {
679
+ border = $(that.s.dt.nTable).css('border-left-width');
680
+ iWidth += typeof border === 'string' ? 1 : parseInt( border, 10 );
681
+ }
682
+
683
+ // Likewise with the final column on the right
684
+ if ( that.s.aiOuterWidths.length === that.s.dt.aoColumns.length-1 ) {
685
+ border = $(that.s.dt.nTable).css('border-right-width');
686
+ iWidth += typeof border === 'string' ? 1 : parseInt( border, 10 );
687
+ }
688
+
689
+ that.s.aiOuterWidths.push( iWidth );
690
+ that.s.aiInnerWidths.push( th.width() );
691
+
692
+ if ( i < that.s.iLeftColumns )
693
+ {
694
+ iLeftWidth += iWidth;
695
+ }
696
+
697
+ if ( that.s.iTableColumns-that.s.iRightColumns <= i )
698
+ {
699
+ iRightWidth += iWidth;
700
+ }
701
+ }
702
+ } );
703
+
704
+ this.s.iLeftWidth = iLeftWidth;
705
+ this.s.iRightWidth = iRightWidth;
706
+ },
707
+
708
+
709
+ /**
710
+ * Set up the DOM for the fixed column. The way the layout works is to create a 1x3 grid
711
+ * for the left column, the DataTable (for which we just reuse the scrolling element DataTable
712
+ * puts into the DOM) and the right column. In each of he two fixed column elements there is a
713
+ * grouping wrapper element and then a head, body and footer wrapper. In each of these we then
714
+ * place the cloned header, body or footer tables. This effectively gives as 3x3 grid structure.
715
+ * @returns {void}
716
+ * @private
717
+ */
718
+ "_fnGridSetup": function ()
719
+ {
720
+ var that = this;
721
+ var oOverflow = this._fnDTOverflow();
722
+ var block;
723
+
724
+ this.dom.body = this.s.dt.nTable;
725
+ this.dom.header = this.s.dt.nTHead.parentNode;
726
+ this.dom.header.parentNode.parentNode.style.position = "relative";
727
+
728
+ var nSWrapper =
729
+ $('<div class="DTFC_ScrollWrapper" style="position:relative; clear:both;">'+
730
+ '<div class="DTFC_LeftWrapper" style="position:absolute; top:0; left:0;">'+
731
+ '<div class="DTFC_LeftHeadWrapper" style="position:relative; top:0; left:0; overflow:hidden;"></div>'+
732
+ '<div class="DTFC_LeftBodyWrapper" style="position:relative; top:0; left:0; overflow:hidden;">'+
733
+ '<div class="DTFC_LeftBodyLiner" style="position:relative; top:0; left:0; overflow-y:scroll;"></div>'+
734
+ '</div>'+
735
+ '<div class="DTFC_LeftFootWrapper" style="position:relative; top:0; left:0; overflow:hidden;"></div>'+
736
+ '</div>'+
737
+ '<div class="DTFC_RightWrapper" style="position:absolute; top:0; right:0;">'+
738
+ '<div class="DTFC_RightHeadWrapper" style="position:relative; top:0; left:0;">'+
739
+ '<div class="DTFC_RightHeadBlocker DTFC_Blocker" style="position:absolute; top:0; bottom:0;"></div>'+
740
+ '</div>'+
741
+ '<div class="DTFC_RightBodyWrapper" style="position:relative; top:0; left:0; overflow:hidden;">'+
742
+ '<div class="DTFC_RightBodyLiner" style="position:relative; top:0; left:0; overflow-y:scroll;"></div>'+
743
+ '</div>'+
744
+ '<div class="DTFC_RightFootWrapper" style="position:relative; top:0; left:0;">'+
745
+ '<div class="DTFC_RightFootBlocker DTFC_Blocker" style="position:absolute; top:0; bottom:0;"></div>'+
746
+ '</div>'+
747
+ '</div>'+
748
+ '</div>')[0];
749
+ var nLeft = nSWrapper.childNodes[0];
750
+ var nRight = nSWrapper.childNodes[1];
751
+
752
+ this.dom.grid.dt.parentNode.insertBefore( nSWrapper, this.dom.grid.dt );
753
+ nSWrapper.appendChild( this.dom.grid.dt );
754
+
755
+ this.dom.grid.wrapper = nSWrapper;
756
+
757
+ if ( this.s.iLeftColumns > 0 )
758
+ {
759
+ this.dom.grid.left.wrapper = nLeft;
760
+ this.dom.grid.left.head = nLeft.childNodes[0];
761
+ this.dom.grid.left.body = nLeft.childNodes[1];
762
+ this.dom.grid.left.liner = $('div.DTFC_LeftBodyLiner', nSWrapper)[0];
763
+
764
+ nSWrapper.appendChild( nLeft );
765
+ }
766
+
767
+ if ( this.s.iRightColumns > 0 )
768
+ {
769
+ this.dom.grid.right.wrapper = nRight;
770
+ this.dom.grid.right.head = nRight.childNodes[0];
771
+ this.dom.grid.right.body = nRight.childNodes[1];
772
+ this.dom.grid.right.liner = $('div.DTFC_RightBodyLiner', nSWrapper)[0];
773
+
774
+ nRight.style.right = oOverflow.bar+"px";
775
+
776
+ block = $('div.DTFC_RightHeadBlocker', nSWrapper)[0];
777
+ block.style.width = oOverflow.bar+"px";
778
+ block.style.right = -oOverflow.bar+"px";
779
+ this.dom.grid.right.headBlock = block;
780
+
781
+ block = $('div.DTFC_RightFootBlocker', nSWrapper)[0];
782
+ block.style.width = oOverflow.bar+"px";
783
+ block.style.right = -oOverflow.bar+"px";
784
+ this.dom.grid.right.footBlock = block;
785
+
786
+ nSWrapper.appendChild( nRight );
787
+ }
788
+
789
+ if ( this.s.dt.nTFoot )
790
+ {
791
+ this.dom.footer = this.s.dt.nTFoot.parentNode;
792
+ if ( this.s.iLeftColumns > 0 )
793
+ {
794
+ this.dom.grid.left.foot = nLeft.childNodes[2];
795
+ }
796
+ if ( this.s.iRightColumns > 0 )
797
+ {
798
+ this.dom.grid.right.foot = nRight.childNodes[2];
799
+ }
800
+ }
801
+
802
+ // RTL support - swap the position of the left and right columns (#48)
803
+ if ( this.s.rtl ) {
804
+ $('div.DTFC_RightHeadBlocker', nSWrapper).css( {
805
+ left: -oOverflow.bar+'px',
806
+ right: ''
807
+ } );
808
+ }
809
+ },
810
+
811
+
812
+ /**
813
+ * Style and position the grid used for the FixedColumns layout
814
+ * @returns {void}
815
+ * @private
816
+ */
817
+ "_fnGridLayout": function ()
818
+ {
819
+ var that = this;
820
+ var oGrid = this.dom.grid;
821
+ var iWidth = $(oGrid.wrapper).width();
822
+ var iBodyHeight = $(this.s.dt.nTable.parentNode).outerHeight();
823
+ var iFullHeight = $(this.s.dt.nTable.parentNode.parentNode).outerHeight();
824
+ var oOverflow = this._fnDTOverflow();
825
+ var iLeftWidth = this.s.iLeftWidth;
826
+ var iRightWidth = this.s.iRightWidth;
827
+ var rtl = $(this.dom.body).css('direction') === 'rtl';
828
+ var wrapper;
829
+ var scrollbarAdjust = function ( node, width ) {
830
+ if ( ! oOverflow.bar ) {
831
+ // If there is no scrollbar (Macs) we need to hide the auto scrollbar
832
+ node.style.width = (width+20)+"px";
833
+ node.style.paddingRight = "20px";
834
+ node.style.boxSizing = "border-box";
835
+ }
836
+ else if ( that._firefoxScrollError() ) {
837
+ // See the above function for why this is required
838
+ if ( $(node).height() > 34 ) {
839
+ node.style.width = (width+oOverflow.bar)+"px";
840
+ }
841
+ }
842
+ else {
843
+ // Otherwise just overflow by the scrollbar
844
+ node.style.width = (width+oOverflow.bar)+"px";
845
+ }
846
+ };
847
+
848
+ // When x scrolling - don't paint the fixed columns over the x scrollbar
849
+ if ( oOverflow.x )
850
+ {
851
+ iBodyHeight -= oOverflow.bar;
852
+ }
853
+
854
+ oGrid.wrapper.style.height = iFullHeight+"px";
855
+
856
+ if ( this.s.iLeftColumns > 0 )
857
+ {
858
+ wrapper = oGrid.left.wrapper;
859
+ wrapper.style.width = iLeftWidth+'px';
860
+ wrapper.style.height = '1px';
861
+
862
+ // Swap the position of the left and right columns for rtl (#48)
863
+ // This is always up against the edge, scrollbar on the far side
864
+ if ( rtl ) {
865
+ wrapper.style.left = '';
866
+ wrapper.style.right = 0;
867
+ }
868
+ else {
869
+ wrapper.style.left = 0;
870
+ wrapper.style.right = '';
871
+ }
872
+
873
+ oGrid.left.body.style.height = iBodyHeight+"px";
874
+ if ( oGrid.left.foot ) {
875
+ oGrid.left.foot.style.top = (oOverflow.x ? oOverflow.bar : 0)+"px"; // shift footer for scrollbar
876
+ }
877
+
878
+ scrollbarAdjust( oGrid.left.liner, iLeftWidth );
879
+ oGrid.left.liner.style.height = iBodyHeight+"px";
880
+ }
881
+
882
+ if ( this.s.iRightColumns > 0 )
883
+ {
884
+ wrapper = oGrid.right.wrapper;
885
+ wrapper.style.width = iRightWidth+'px';
886
+ wrapper.style.height = '1px';
887
+
888
+ // Need to take account of the vertical scrollbar
889
+ if ( this.s.rtl ) {
890
+ wrapper.style.left = oOverflow.y ? oOverflow.bar+'px' : 0;
891
+ wrapper.style.right = '';
892
+ }
893
+ else {
894
+ wrapper.style.left = '';
895
+ wrapper.style.right = oOverflow.y ? oOverflow.bar+'px' : 0;
896
+ }
897
+
898
+ oGrid.right.body.style.height = iBodyHeight+"px";
899
+ if ( oGrid.right.foot ) {
900
+ oGrid.right.foot.style.top = (oOverflow.x ? oOverflow.bar : 0)+"px";
901
+ }
902
+
903
+ scrollbarAdjust( oGrid.right.liner, iRightWidth );
904
+ oGrid.right.liner.style.height = iBodyHeight+"px";
905
+
906
+ oGrid.right.headBlock.style.display = oOverflow.y ? 'block' : 'none';
907
+ oGrid.right.footBlock.style.display = oOverflow.y ? 'block' : 'none';
908
+ }
909
+ },
910
+
911
+
912
+ /**
913
+ * Get information about the DataTable's scrolling state - specifically if the table is scrolling
914
+ * on either the x or y axis, and also the scrollbar width.
915
+ * @returns {object} Information about the DataTables scrolling state with the properties:
916
+ * 'x', 'y' and 'bar'
917
+ * @private
918
+ */
919
+ "_fnDTOverflow": function ()
920
+ {
921
+ var nTable = this.s.dt.nTable;
922
+ var nTableScrollBody = nTable.parentNode;
923
+ var out = {
924
+ "x": false,
925
+ "y": false,
926
+ "bar": this.s.dt.oScroll.iBarWidth
927
+ };
928
+
929
+ if ( nTable.offsetWidth > nTableScrollBody.clientWidth )
930
+ {
931
+ out.x = true;
932
+ }
933
+
934
+ if ( nTable.offsetHeight > nTableScrollBody.clientHeight )
935
+ {
936
+ out.y = true;
937
+ }
938
+
939
+ return out;
940
+ },
941
+
942
+
943
+ /**
944
+ * Clone and position the fixed columns
945
+ * @returns {void}
946
+ * @param {Boolean} bAll Indicate if the header and footer should be updated as well (true)
947
+ * @private
948
+ */
949
+ "_fnDraw": function ( bAll )
950
+ {
951
+ this._fnGridLayout();
952
+ this._fnCloneLeft( bAll );
953
+ this._fnCloneRight( bAll );
954
+
955
+ /* Draw callback function */
956
+ if ( this.s.fnDrawCallback !== null )
957
+ {
958
+ this.s.fnDrawCallback.call( this, this.dom.clone.left, this.dom.clone.right );
959
+ }
960
+
961
+ /* Event triggering */
962
+ $(this).trigger( 'draw.dtfc', {
963
+ "leftClone": this.dom.clone.left,
964
+ "rightClone": this.dom.clone.right
965
+ } );
966
+ },
967
+
968
+
969
+ /**
970
+ * Clone the right columns
971
+ * @returns {void}
972
+ * @param {Boolean} bAll Indicate if the header and footer should be updated as well (true)
973
+ * @private
974
+ */
975
+ "_fnCloneRight": function ( bAll )
976
+ {
977
+ if ( this.s.iRightColumns <= 0 ) {
978
+ return;
979
+ }
980
+
981
+ var that = this,
982
+ i, jq,
983
+ aiColumns = [];
984
+
985
+ for ( i=this.s.iTableColumns-this.s.iRightColumns ; i<this.s.iTableColumns ; i++ ) {
986
+ if ( this.s.dt.aoColumns[i].bVisible ) {
987
+ aiColumns.push( i );
988
+ }
989
+ }
990
+
991
+ this._fnClone( this.dom.clone.right, this.dom.grid.right, aiColumns, bAll );
992
+ },
993
+
994
+
995
+ /**
996
+ * Clone the left columns
997
+ * @returns {void}
998
+ * @param {Boolean} bAll Indicate if the header and footer should be updated as well (true)
999
+ * @private
1000
+ */
1001
+ "_fnCloneLeft": function ( bAll )
1002
+ {
1003
+ if ( this.s.iLeftColumns <= 0 ) {
1004
+ return;
1005
+ }
1006
+
1007
+ var that = this,
1008
+ i, jq,
1009
+ aiColumns = [];
1010
+
1011
+ for ( i=0 ; i<this.s.iLeftColumns ; i++ ) {
1012
+ if ( this.s.dt.aoColumns[i].bVisible ) {
1013
+ aiColumns.push( i );
1014
+ }
1015
+ }
1016
+
1017
+ this._fnClone( this.dom.clone.left, this.dom.grid.left, aiColumns, bAll );
1018
+ },
1019
+
1020
+
1021
+ /**
1022
+ * Make a copy of the layout object for a header or footer element from DataTables. Note that
1023
+ * this method will clone the nodes in the layout object.
1024
+ * @returns {Array} Copy of the layout array
1025
+ * @param {Object} aoOriginal Layout array from DataTables (aoHeader or aoFooter)
1026
+ * @param {Object} aiColumns Columns to copy
1027
+ * @param {boolean} events Copy cell events or not
1028
+ * @private
1029
+ */
1030
+ "_fnCopyLayout": function ( aoOriginal, aiColumns, events )
1031
+ {
1032
+ var aReturn = [];
1033
+ var aClones = [];
1034
+ var aCloned = [];
1035
+
1036
+ for ( var i=0, iLen=aoOriginal.length ; i<iLen ; i++ )
1037
+ {
1038
+ var aRow = [];
1039
+ aRow.nTr = $(aoOriginal[i].nTr).clone(events, false)[0];
1040
+
1041
+ for ( var j=0, jLen=this.s.iTableColumns ; j<jLen ; j++ )
1042
+ {
1043
+ if ( $.inArray( j, aiColumns ) === -1 )
1044
+ {
1045
+ continue;
1046
+ }
1047
+
1048
+ var iCloned = $.inArray( aoOriginal[i][j].cell, aCloned );
1049
+ if ( iCloned === -1 )
1050
+ {
1051
+ var nClone = $(aoOriginal[i][j].cell).clone(events, false)[0];
1052
+ aClones.push( nClone );
1053
+ aCloned.push( aoOriginal[i][j].cell );
1054
+
1055
+ aRow.push( {
1056
+ "cell": nClone,
1057
+ "unique": aoOriginal[i][j].unique
1058
+ } );
1059
+ }
1060
+ else
1061
+ {
1062
+ aRow.push( {
1063
+ "cell": aClones[ iCloned ],
1064
+ "unique": aoOriginal[i][j].unique
1065
+ } );
1066
+ }
1067
+ }
1068
+
1069
+ aReturn.push( aRow );
1070
+ }
1071
+
1072
+ return aReturn;
1073
+ },
1074
+
1075
+
1076
+ /**
1077
+ * Clone the DataTable nodes and place them in the DOM (sized correctly)
1078
+ * @returns {void}
1079
+ * @param {Object} oClone Object containing the header, footer and body cloned DOM elements
1080
+ * @param {Object} oGrid Grid object containing the display grid elements for the cloned
1081
+ * column (left or right)
1082
+ * @param {Array} aiColumns Column indexes which should be operated on from the DataTable
1083
+ * @param {Boolean} bAll Indicate if the header and footer should be updated as well (true)
1084
+ * @private
1085
+ */
1086
+ "_fnClone": function ( oClone, oGrid, aiColumns, bAll )
1087
+ {
1088
+ var that = this,
1089
+ i, iLen, j, jLen, jq, nTarget, iColumn, nClone, iIndex, aoCloneLayout,
1090
+ jqCloneThead, aoFixedHeader,
1091
+ dt = this.s.dt;
1092
+
1093
+ /*
1094
+ * Header
1095
+ */
1096
+ if ( bAll )
1097
+ {
1098
+ $(oClone.header).remove();
1099
+
1100
+ oClone.header = $(this.dom.header).clone(true, false)[0];
1101
+ oClone.header.className += " DTFC_Cloned";
1102
+ oClone.header.style.width = "100%";
1103
+ oGrid.head.appendChild( oClone.header );
1104
+
1105
+ /* Copy the DataTables layout cache for the header for our floating column */
1106
+ aoCloneLayout = this._fnCopyLayout( dt.aoHeader, aiColumns, true );
1107
+ jqCloneThead = $('>thead', oClone.header);
1108
+ jqCloneThead.empty();
1109
+
1110
+ /* Add the created cloned TR elements to the table */
1111
+ for ( i=0, iLen=aoCloneLayout.length ; i<iLen ; i++ )
1112
+ {
1113
+ jqCloneThead[0].appendChild( aoCloneLayout[i].nTr );
1114
+ }
1115
+
1116
+ /* Use the handy _fnDrawHead function in DataTables to do the rowspan/colspan
1117
+ * calculations for us
1118
+ */
1119
+ dt.oApi._fnDrawHead( dt, aoCloneLayout, true );
1120
+ }
1121
+ else
1122
+ {
1123
+ /* To ensure that we copy cell classes exactly, regardless of colspan, multiple rows
1124
+ * etc, we make a copy of the header from the DataTable again, but don't insert the
1125
+ * cloned cells, just copy the classes across. To get the matching layout for the
1126
+ * fixed component, we use the DataTables _fnDetectHeader method, allowing 1:1 mapping
1127
+ */
1128
+ aoCloneLayout = this._fnCopyLayout( dt.aoHeader, aiColumns, false );
1129
+ aoFixedHeader=[];
1130
+
1131
+ dt.oApi._fnDetectHeader( aoFixedHeader, $('>thead', oClone.header)[0] );
1132
+
1133
+ for ( i=0, iLen=aoCloneLayout.length ; i<iLen ; i++ )
1134
+ {
1135
+ for ( j=0, jLen=aoCloneLayout[i].length ; j<jLen ; j++ )
1136
+ {
1137
+ aoFixedHeader[i][j].cell.className = aoCloneLayout[i][j].cell.className;
1138
+
1139
+ // If jQuery UI theming is used we need to copy those elements as well
1140
+ $('span.DataTables_sort_icon', aoFixedHeader[i][j].cell).each( function () {
1141
+ this.className = $('span.DataTables_sort_icon', aoCloneLayout[i][j].cell)[0].className;
1142
+ } );
1143
+ }
1144
+ }
1145
+ }
1146
+ this._fnEqualiseHeights( 'thead', this.dom.header, oClone.header );
1147
+
1148
+ /*
1149
+ * Body
1150
+ */
1151
+ if ( this.s.sHeightMatch == 'auto' )
1152
+ {
1153
+ /* Remove any heights which have been applied already and let the browser figure it out */
1154
+ $('>tbody>tr', that.dom.body).css('height', 'auto');
1155
+ }
1156
+
1157
+ if ( oClone.body !== null )
1158
+ {
1159
+ $(oClone.body).remove();
1160
+ oClone.body = null;
1161
+ }
1162
+
1163
+ oClone.body = $(this.dom.body).clone(true)[0];
1164
+ oClone.body.className += " DTFC_Cloned";
1165
+ oClone.body.style.paddingBottom = dt.oScroll.iBarWidth+"px";
1166
+ oClone.body.style.marginBottom = (dt.oScroll.iBarWidth*2)+"px"; /* For IE */
1167
+ if ( oClone.body.getAttribute('id') !== null )
1168
+ {
1169
+ oClone.body.removeAttribute('id');
1170
+ }
1171
+
1172
+ $('>thead>tr', oClone.body).empty();
1173
+ $('>tfoot', oClone.body).remove();
1174
+
1175
+ var nBody = $('tbody', oClone.body)[0];
1176
+ $(nBody).empty();
1177
+ if ( dt.aiDisplay.length > 0 )
1178
+ {
1179
+ /* Copy the DataTables' header elements to force the column width in exactly the
1180
+ * same way that DataTables does it - have the header element, apply the width and
1181
+ * colapse it down
1182
+ */
1183
+ var nInnerThead = $('>thead>tr', oClone.body)[0];
1184
+ for ( iIndex=0 ; iIndex<aiColumns.length ; iIndex++ )
1185
+ {
1186
+ iColumn = aiColumns[iIndex];
1187
+
1188
+ nClone = $(dt.aoColumns[iColumn].nTh).clone(true)[0];
1189
+ nClone.innerHTML = "";
1190
+
1191
+ var oStyle = nClone.style;
1192
+ oStyle.paddingTop = "0";
1193
+ oStyle.paddingBottom = "0";
1194
+ oStyle.borderTopWidth = "0";
1195
+ oStyle.borderBottomWidth = "0";
1196
+ oStyle.height = 0;
1197
+ oStyle.width = that.s.aiInnerWidths[iColumn]+"px";
1198
+
1199
+ nInnerThead.appendChild( nClone );
1200
+ }
1201
+
1202
+ /* Add in the tbody elements, cloning form the master table */
1203
+ $('>tbody>tr', that.dom.body).each( function (z) {
1204
+ var i = that.s.dt.oFeatures.bServerSide===false ?
1205
+ that.s.dt.aiDisplay[ that.s.dt._iDisplayStart+z ] : z;
1206
+ var aTds = that.s.dt.aoData[ i ].anCells || $(this).children('td, th');
1207
+
1208
+ var n = this.cloneNode(false);
1209
+ n.removeAttribute('id');
1210
+ n.setAttribute( 'data-dt-row', i );
1211
+
1212
+ for ( iIndex=0 ; iIndex<aiColumns.length ; iIndex++ )
1213
+ {
1214
+ iColumn = aiColumns[iIndex];
1215
+
1216
+ if ( aTds.length > 0 )
1217
+ {
1218
+ nClone = $( aTds[iColumn] ).clone(true, true)[0];
1219
+ nClone.setAttribute( 'data-dt-row', i );
1220
+ nClone.setAttribute( 'data-dt-column', iIndex );
1221
+ n.appendChild( nClone );
1222
+ }
1223
+ }
1224
+ nBody.appendChild( n );
1225
+ } );
1226
+ }
1227
+ else
1228
+ {
1229
+ $('>tbody>tr', that.dom.body).each( function (z) {
1230
+ nClone = this.cloneNode(true);
1231
+ nClone.className += ' DTFC_NoData';
1232
+ $('td', nClone).html('');
1233
+ nBody.appendChild( nClone );
1234
+ } );
1235
+ }
1236
+
1237
+ oClone.body.style.width = "100%";
1238
+ oClone.body.style.margin = "0";
1239
+ oClone.body.style.padding = "0";
1240
+
1241
+ // Interop with Scroller - need to use a height forcing element in the
1242
+ // scrolling area in the same way that Scroller does in the body scroll.
1243
+ if ( dt.oScroller !== undefined )
1244
+ {
1245
+ var scrollerForcer = dt.oScroller.dom.force;
1246
+
1247
+ if ( ! oGrid.forcer ) {
1248
+ oGrid.forcer = scrollerForcer.cloneNode( true );
1249
+ oGrid.liner.appendChild( oGrid.forcer );
1250
+ }
1251
+ else {
1252
+ oGrid.forcer.style.height = scrollerForcer.style.height;
1253
+ }
1254
+ }
1255
+
1256
+ oGrid.liner.appendChild( oClone.body );
1257
+
1258
+ this._fnEqualiseHeights( 'tbody', that.dom.body, oClone.body );
1259
+
1260
+ /*
1261
+ * Footer
1262
+ */
1263
+ if ( dt.nTFoot !== null )
1264
+ {
1265
+ if ( bAll )
1266
+ {
1267
+ if ( oClone.footer !== null )
1268
+ {
1269
+ oClone.footer.parentNode.removeChild( oClone.footer );
1270
+ }
1271
+ oClone.footer = $(this.dom.footer).clone(true, true)[0];
1272
+ oClone.footer.className += " DTFC_Cloned";
1273
+ oClone.footer.style.width = "100%";
1274
+ oGrid.foot.appendChild( oClone.footer );
1275
+
1276
+ /* Copy the footer just like we do for the header */
1277
+ aoCloneLayout = this._fnCopyLayout( dt.aoFooter, aiColumns, true );
1278
+ var jqCloneTfoot = $('>tfoot', oClone.footer);
1279
+ jqCloneTfoot.empty();
1280
+
1281
+ for ( i=0, iLen=aoCloneLayout.length ; i<iLen ; i++ )
1282
+ {
1283
+ jqCloneTfoot[0].appendChild( aoCloneLayout[i].nTr );
1284
+ }
1285
+ dt.oApi._fnDrawHead( dt, aoCloneLayout, true );
1286
+ }
1287
+ else
1288
+ {
1289
+ aoCloneLayout = this._fnCopyLayout( dt.aoFooter, aiColumns, false );
1290
+ var aoCurrFooter=[];
1291
+
1292
+ dt.oApi._fnDetectHeader( aoCurrFooter, $('>tfoot', oClone.footer)[0] );
1293
+
1294
+ for ( i=0, iLen=aoCloneLayout.length ; i<iLen ; i++ )
1295
+ {
1296
+ for ( j=0, jLen=aoCloneLayout[i].length ; j<jLen ; j++ )
1297
+ {
1298
+ aoCurrFooter[i][j].cell.className = aoCloneLayout[i][j].cell.className;
1299
+ }
1300
+ }
1301
+ }
1302
+ this._fnEqualiseHeights( 'tfoot', this.dom.footer, oClone.footer );
1303
+ }
1304
+
1305
+ /* Equalise the column widths between the header footer and body - body get's priority */
1306
+ var anUnique = dt.oApi._fnGetUniqueThs( dt, $('>thead', oClone.header)[0] );
1307
+ $(anUnique).each( function (i) {
1308
+ iColumn = aiColumns[i];
1309
+ this.style.width = that.s.aiInnerWidths[iColumn]+"px";
1310
+ } );
1311
+
1312
+ if ( that.s.dt.nTFoot !== null )
1313
+ {
1314
+ anUnique = dt.oApi._fnGetUniqueThs( dt, $('>tfoot', oClone.footer)[0] );
1315
+ $(anUnique).each( function (i) {
1316
+ iColumn = aiColumns[i];
1317
+ this.style.width = that.s.aiInnerWidths[iColumn]+"px";
1318
+ } );
1319
+ }
1320
+ },
1321
+
1322
+
1323
+ /**
1324
+ * From a given table node (THEAD etc), get a list of TR direct child elements
1325
+ * @param {Node} nIn Table element to search for TR elements (THEAD, TBODY or TFOOT element)
1326
+ * @returns {Array} List of TR elements found
1327
+ * @private
1328
+ */
1329
+ "_fnGetTrNodes": function ( nIn )
1330
+ {
1331
+ var aOut = [];
1332
+ for ( var i=0, iLen=nIn.childNodes.length ; i<iLen ; i++ )
1333
+ {
1334
+ if ( nIn.childNodes[i].nodeName.toUpperCase() == "TR" )
1335
+ {
1336
+ aOut.push( nIn.childNodes[i] );
1337
+ }
1338
+ }
1339
+ return aOut;
1340
+ },
1341
+
1342
+
1343
+ /**
1344
+ * Equalise the heights of the rows in a given table node in a cross browser way
1345
+ * @returns {void}
1346
+ * @param {String} nodeName Node type - thead, tbody or tfoot
1347
+ * @param {Node} original Original node to take the heights from
1348
+ * @param {Node} clone Copy the heights to
1349
+ * @private
1350
+ */
1351
+ "_fnEqualiseHeights": function ( nodeName, original, clone )
1352
+ {
1353
+ if ( this.s.sHeightMatch == 'none' && nodeName !== 'thead' && nodeName !== 'tfoot' )
1354
+ {
1355
+ return;
1356
+ }
1357
+
1358
+ var that = this,
1359
+ i, iLen, iHeight, iHeight2, iHeightOriginal, iHeightClone,
1360
+ rootOriginal = original.getElementsByTagName(nodeName)[0],
1361
+ rootClone = clone.getElementsByTagName(nodeName)[0],
1362
+ jqBoxHack = $('>'+nodeName+'>tr:eq(0)', original).children(':first'),
1363
+ iBoxHack = jqBoxHack.outerHeight() - jqBoxHack.height(),
1364
+ anOriginal = this._fnGetTrNodes( rootOriginal ),
1365
+ anClone = this._fnGetTrNodes( rootClone ),
1366
+ heights = [];
1367
+
1368
+ for ( i=0, iLen=anClone.length ; i<iLen ; i++ )
1369
+ {
1370
+ iHeightOriginal = anOriginal[i].offsetHeight;
1371
+ iHeightClone = anClone[i].offsetHeight;
1372
+ iHeight = iHeightClone > iHeightOriginal ? iHeightClone : iHeightOriginal;
1373
+
1374
+ if ( this.s.sHeightMatch == 'semiauto' )
1375
+ {
1376
+ anOriginal[i]._DTTC_iHeight = iHeight;
1377
+ }
1378
+
1379
+ heights.push( iHeight );
1380
+ }
1381
+
1382
+ for ( i=0, iLen=anClone.length ; i<iLen ; i++ )
1383
+ {
1384
+ anClone[i].style.height = heights[i]+"px";
1385
+ anOriginal[i].style.height = heights[i]+"px";
1386
+ }
1387
+ },
1388
+
1389
+ /**
1390
+ * Determine if the UA suffers from Firefox's overflow:scroll scrollbars
1391
+ * not being shown bug.
1392
+ *
1393
+ * Firefox doesn't draw scrollbars, even if it is told to using
1394
+ * overflow:scroll, if the div is less than 34px height. See bugs 292284 and
1395
+ * 781885. Using UA detection here since this is particularly hard to detect
1396
+ * using objects - its a straight up rendering error in Firefox.
1397
+ *
1398
+ * @return {boolean} True if Firefox error is present, false otherwise
1399
+ */
1400
+ _firefoxScrollError: function () {
1401
+ if ( _firefoxScroll === undefined ) {
1402
+ var test = $('<div/>')
1403
+ .css( {
1404
+ position: 'absolute',
1405
+ top: 0,
1406
+ left: 0,
1407
+ height: 10,
1408
+ width: 50,
1409
+ overflow: 'scroll'
1410
+ } )
1411
+ .appendTo( 'body' );
1412
+
1413
+ // Make sure this doesn't apply on Macs with 0 width scrollbars
1414
+ _firefoxScroll = (
1415
+ test[0].clientWidth === test[0].offsetWidth && this._fnDTOverflow().bar !== 0
1416
+ );
1417
+
1418
+ test.remove();
1419
+ }
1420
+
1421
+ return _firefoxScroll;
1422
+ }
1423
+ } );
1424
+
1425
+
1426
+
1427
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1428
+ * Statics
1429
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1430
+
1431
+ /**
1432
+ * FixedColumns default settings for initialisation
1433
+ * @name FixedColumns.defaults
1434
+ * @namespace
1435
+ * @static
1436
+ */
1437
+ FixedColumns.defaults = /** @lends FixedColumns.defaults */{
1438
+ /**
1439
+ * Number of left hand columns to fix in position
1440
+ * @type int
1441
+ * @default 1
1442
+ * @static
1443
+ * @example
1444
+ * var = $('#example').dataTable( {
1445
+ * "scrollX": "100%"
1446
+ * } );
1447
+ * new $.fn.dataTable.fixedColumns( table, {
1448
+ * "leftColumns": 2
1449
+ * } );
1450
+ */
1451
+ "iLeftColumns": 1,
1452
+
1453
+ /**
1454
+ * Number of right hand columns to fix in position
1455
+ * @type int
1456
+ * @default 0
1457
+ * @static
1458
+ * @example
1459
+ * var table = $('#example').dataTable( {
1460
+ * "scrollX": "100%"
1461
+ * } );
1462
+ * new $.fn.dataTable.fixedColumns( table, {
1463
+ * "rightColumns": 1
1464
+ * } );
1465
+ */
1466
+ "iRightColumns": 0,
1467
+
1468
+ /**
1469
+ * Draw callback function which is called when FixedColumns has redrawn the fixed assets
1470
+ * @type function(object, object):void
1471
+ * @default null
1472
+ * @static
1473
+ * @example
1474
+ * var table = $('#example').dataTable( {
1475
+ * "scrollX": "100%"
1476
+ * } );
1477
+ * new $.fn.dataTable.fixedColumns( table, {
1478
+ * "drawCallback": function () {
1479
+ * alert( "FixedColumns redraw" );
1480
+ * }
1481
+ * } );
1482
+ */
1483
+ "fnDrawCallback": null,
1484
+
1485
+ /**
1486
+ * Height matching algorthim to use. This can be "none" which will result in no height
1487
+ * matching being applied by FixedColumns (height matching could be forced by CSS in this
1488
+ * case), "semiauto" whereby the height calculation will be performed once, and the result
1489
+ * cached to be used again (fnRecalculateHeight can be used to force recalculation), or
1490
+ * "auto" when height matching is performed on every draw (slowest but must accurate)
1491
+ * @type string
1492
+ * @default semiauto
1493
+ * @static
1494
+ * @example
1495
+ * var table = $('#example').dataTable( {
1496
+ * "scrollX": "100%"
1497
+ * } );
1498
+ * new $.fn.dataTable.fixedColumns( table, {
1499
+ * "heightMatch": "auto"
1500
+ * } );
1501
+ */
1502
+ "sHeightMatch": "semiauto"
1503
+ };
1504
+
1505
+
1506
+
1507
+
1508
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1509
+ * Constants
1510
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1511
+
1512
+ /**
1513
+ * FixedColumns version
1514
+ * @name FixedColumns.version
1515
+ * @type String
1516
+ * @default See code
1517
+ * @static
1518
+ */
1519
+ FixedColumns.version = "3.2.2";
1520
+
1521
+
1522
+
1523
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1524
+ * DataTables API integration
1525
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1526
+
1527
+ DataTable.Api.register( 'fixedColumns()', function () {
1528
+ return this;
1529
+ } );
1530
+
1531
+ DataTable.Api.register( 'fixedColumns().update()', function () {
1532
+ return this.iterator( 'table', function ( ctx ) {
1533
+ if ( ctx._oFixedColumns ) {
1534
+ ctx._oFixedColumns.fnUpdate();
1535
+ }
1536
+ } );
1537
+ } );
1538
+
1539
+ DataTable.Api.register( 'fixedColumns().relayout()', function () {
1540
+ return this.iterator( 'table', function ( ctx ) {
1541
+ if ( ctx._oFixedColumns ) {
1542
+ ctx._oFixedColumns.fnRedrawLayout();
1543
+ }
1544
+ } );
1545
+ } );
1546
+
1547
+ DataTable.Api.register( 'rows().recalcHeight()', function () {
1548
+ return this.iterator( 'row', function ( ctx, idx ) {
1549
+ if ( ctx._oFixedColumns ) {
1550
+ ctx._oFixedColumns.fnRecalculateHeight( this.row(idx).node() );
1551
+ }
1552
+ } );
1553
+ } );
1554
+
1555
+ DataTable.Api.register( 'fixedColumns().rowIndex()', function ( row ) {
1556
+ row = $(row);
1557
+
1558
+ return row.parents('.DTFC_Cloned').length ?
1559
+ this.rows( { page: 'current' } ).indexes()[ row.index() ] :
1560
+ this.row( row ).index();
1561
+ } );
1562
+
1563
+ DataTable.Api.register( 'fixedColumns().cellIndex()', function ( cell ) {
1564
+ cell = $(cell);
1565
+
1566
+ if ( cell.parents('.DTFC_Cloned').length ) {
1567
+ var rowClonedIdx = cell.parent().index();
1568
+ var rowIdx = this.rows( { page: 'current' } ).indexes()[ rowClonedIdx ];
1569
+ var columnIdx;
1570
+
1571
+ if ( cell.parents('.DTFC_LeftWrapper').length ) {
1572
+ columnIdx = cell.index();
1573
+ }
1574
+ else {
1575
+ var columns = this.columns().flatten().length;
1576
+ columnIdx = columns - this.context[0]._oFixedColumns.s.iRightColumns + cell.index();
1577
+ }
1578
+
1579
+ return {
1580
+ row: rowIdx,
1581
+ column: this.column.index( 'toData', columnIdx ),
1582
+ columnVisible: columnIdx
1583
+ };
1584
+ }
1585
+ else {
1586
+ return this.cell( cell ).index();
1587
+ }
1588
+ } );
1589
+
1590
+
1591
+
1592
+
1593
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1594
+ * Initialisation
1595
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1596
+
1597
+ // Attach a listener to the document which listens for DataTables initialisation
1598
+ // events so we can automatically initialise
1599
+ $(document).on( 'init.dt.fixedColumns', function (e, settings) {
1600
+ if ( e.namespace !== 'dt' ) {
1601
+ return;
1602
+ }
1603
+
1604
+ var init = settings.oInit.fixedColumns;
1605
+ var defaults = DataTable.defaults.fixedColumns;
1606
+
1607
+ if ( init || defaults ) {
1608
+ var opts = $.extend( {}, init, defaults );
1609
+
1610
+ if ( init !== false ) {
1611
+ new FixedColumns( settings, opts );
1612
+ }
1613
+ }
1614
+ } );
1615
+
1616
+
1617
+
1618
+ // Make FixedColumns accessible from the DataTables instance
1619
+ $.fn.dataTable.FixedColumns = FixedColumns;
1620
+ $.fn.DataTable.FixedColumns = FixedColumns;
1621
+
1622
+ return FixedColumns;
1623
+ }));