jquery-datatables 1.10.12

Sign up to get free protection for your applications and to get access to all the features.
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
+ }));