datatable 0.1.0alpha2

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 (187) hide show
  1. data/.bundle/config +3 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +9 -0
  5. data/Gemfile.lock +83 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.md +135 -0
  8. data/Rakefile +27 -0
  9. data/TODO +71 -0
  10. data/datatable.gemspec +20 -0
  11. data/example_app/.DS_Store +0 -0
  12. data/example_app/.gitignore +6 -0
  13. data/example_app/.rspec +1 -0
  14. data/example_app/Gemfile +35 -0
  15. data/example_app/Gemfile.lock +126 -0
  16. data/example_app/Rakefile +7 -0
  17. data/example_app/app/controllers/application_controller.rb +3 -0
  18. data/example_app/app/controllers/orders_controller.rb +13 -0
  19. data/example_app/app/datatables/orders_index.rb +31 -0
  20. data/example_app/app/helpers/application_helper.rb +2 -0
  21. data/example_app/app/models/customer.rb +4 -0
  22. data/example_app/app/models/item.rb +4 -0
  23. data/example_app/app/models/order.rb +5 -0
  24. data/example_app/app/models/order_item.rb +4 -0
  25. data/example_app/app/models/sales_rep.rb +3 -0
  26. data/example_app/app/views/layouts/application.html.erb +12 -0
  27. data/example_app/app/views/orders/index.html.erb +14 -0
  28. data/example_app/config/application.rb +41 -0
  29. data/example_app/config/boot.rb +6 -0
  30. data/example_app/config/database.yml.mysql +20 -0
  31. data/example_app/config/database.yml.pg +20 -0
  32. data/example_app/config/environment.rb +5 -0
  33. data/example_app/config/environments/development.rb +28 -0
  34. data/example_app/config/environments/production.rb +49 -0
  35. data/example_app/config/environments/test.rb +35 -0
  36. data/example_app/config/initializers/backtrace_silencers.rb +7 -0
  37. data/example_app/config/initializers/datatable.rb +6 -0
  38. data/example_app/config/initializers/inflections.rb +10 -0
  39. data/example_app/config/initializers/mime_types.rb +5 -0
  40. data/example_app/config/initializers/secret_token.rb +9 -0
  41. data/example_app/config/initializers/session_store.rb +8 -0
  42. data/example_app/config/locales/en.yml +5 -0
  43. data/example_app/config/routes.rb +6 -0
  44. data/example_app/config.ru +4 -0
  45. data/example_app/db/migrate/20110429185712_create_customers.rb +15 -0
  46. data/example_app/db/migrate/20110429185742_create_sales_reps.rb +14 -0
  47. data/example_app/db/migrate/20110429185807_create_items.rb +15 -0
  48. data/example_app/db/migrate/20110429185913_create_orders.rb +15 -0
  49. data/example_app/db/migrate/20110429190005_create_order_items.rb +14 -0
  50. data/example_app/db/schema.rb +53 -0
  51. data/example_app/db/seeds.rb +49 -0
  52. data/example_app/lib/tasks/.gitkeep +0 -0
  53. data/example_app/lib/tasks/setup.rake +12 -0
  54. data/example_app/public/404.html +26 -0
  55. data/example_app/public/422.html +26 -0
  56. data/example_app/public/500.html +26 -0
  57. data/example_app/public/datatable/css/demo_page.css +99 -0
  58. data/example_app/public/datatable/css/demo_table.css +539 -0
  59. data/example_app/public/datatable/css/demo_table_jui.css +521 -0
  60. data/example_app/public/datatable/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  61. data/example_app/public/datatable/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  62. data/example_app/public/datatable/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  63. data/example_app/public/datatable/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  64. data/example_app/public/datatable/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  65. data/example_app/public/datatable/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  66. data/example_app/public/datatable/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  67. data/example_app/public/datatable/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  68. data/example_app/public/datatable/css/smoothness/images/ui-icons_222222_256x240.png +0 -0
  69. data/example_app/public/datatable/css/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  70. data/example_app/public/datatable/css/smoothness/images/ui-icons_454545_256x240.png +0 -0
  71. data/example_app/public/datatable/css/smoothness/images/ui-icons_888888_256x240.png +0 -0
  72. data/example_app/public/datatable/css/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  73. data/example_app/public/datatable/css/smoothness/jquery-ui-1.8.14.custom.css +568 -0
  74. data/example_app/public/datatable/images/back_disabled.jpg +0 -0
  75. data/example_app/public/datatable/images/back_enabled.jpg +0 -0
  76. data/example_app/public/datatable/images/favicon.ico +0 -0
  77. data/example_app/public/datatable/images/forward_disabled.jpg +0 -0
  78. data/example_app/public/datatable/images/forward_enabled.jpg +0 -0
  79. data/example_app/public/datatable/images/sort_asc.png +0 -0
  80. data/example_app/public/datatable/images/sort_asc_disabled.png +0 -0
  81. data/example_app/public/datatable/images/sort_both.png +0 -0
  82. data/example_app/public/datatable/images/sort_desc.png +0 -0
  83. data/example_app/public/datatable/images/sort_desc_disabled.png +0 -0
  84. data/example_app/public/datatable/js/jquery-ui-1.8.14.custom.min.js +789 -0
  85. data/example_app/public/datatable/js/jquery.dataTables.js +7347 -0
  86. data/example_app/public/datatable/js/jquery.dataTables.min.js +151 -0
  87. data/example_app/public/favicon.ico +0 -0
  88. data/example_app/public/flash/copy_cvs_xls.swf +0 -0
  89. data/example_app/public/flash/copy_cvs_xls_pdf.swf +0 -0
  90. data/example_app/public/images/rails.png +0 -0
  91. data/example_app/public/javascripts/application.js +2 -0
  92. data/example_app/public/javascripts/jquery.js +8936 -0
  93. data/example_app/public/javascripts/jquery.min.js +18 -0
  94. data/example_app/public/javascripts/jquery_ujs.js +316 -0
  95. data/example_app/public/robots.txt +5 -0
  96. data/example_app/public/stylesheets/.gitkeep +0 -0
  97. data/example_app/script/rails +6 -0
  98. data/example_app/spec/datatables/active_record_dsl_spec.rb +59 -0
  99. data/example_app/spec/datatables/active_record_link_to_spec.rb +22 -0
  100. data/example_app/spec/datatables/active_record_pagination_spec.rb +94 -0
  101. data/example_app/spec/datatables/active_record_table_operations_spec.rb +180 -0
  102. data/example_app/spec/datatables/config_spec.rb +10 -0
  103. data/example_app/spec/datatables/query_params_spec.rb +73 -0
  104. data/example_app/spec/datatables/sql_default_spec.rb +22 -0
  105. data/example_app/spec/datatables/sql_pagination_spec.rb +177 -0
  106. data/example_app/spec/datatables/sql_search_cast_spec.rb +6 -0
  107. data/example_app/spec/datatables/sql_search_global_spec.rb +107 -0
  108. data/example_app/spec/datatables/sql_search_individual_spec.rb +113 -0
  109. data/example_app/spec/datatables/sql_search_where_spec.rb +87 -0
  110. data/example_app/spec/datatables/sql_sorting_spec.rb +80 -0
  111. data/example_app/spec/datatables/sql_variables_spec.rb +104 -0
  112. data/example_app/spec/factories/customer_factory.rb +4 -0
  113. data/example_app/spec/factories/item_factory.rb +2 -0
  114. data/example_app/spec/factories/order_factory.rb +7 -0
  115. data/example_app/spec/factories/order_item_factory.rb +2 -0
  116. data/example_app/spec/factories/sales_rep_factory.rb +4 -0
  117. data/example_app/spec/helpers/aocolumn_spec.rb +239 -0
  118. data/example_app/spec/helpers/data_table_helper_spec.rb +148 -0
  119. data/example_app/spec/helpers/headings_spec.rb +71 -0
  120. data/example_app/spec/spec_helper.rb +29 -0
  121. data/generators.txt +6 -0
  122. data/images/datatable_screenshot.png +0 -0
  123. data/lib/datatable/active_record_dsl.rb +49 -0
  124. data/lib/datatable/errors.rb +5 -0
  125. data/lib/datatable/helper.rb +199 -0
  126. data/lib/datatable/railtie.rb +17 -0
  127. data/lib/datatable/version.rb +4 -0
  128. data/lib/datatable.rb +341 -0
  129. data/lib/generators/datatable/install_generator.rb +58 -0
  130. data/lib/generators/datatable/new_generator.rb +46 -0
  131. data/lib/generators/templates/datatable.rb +33 -0
  132. data/lib/generators/templates/datatable_initializer.rb +6 -0
  133. data/vendor/datatable/Readme.txt +11 -0
  134. data/vendor/datatable/extras/TableTools/media/css/TableTools.css +264 -0
  135. data/vendor/datatable/extras/TableTools/media/css/TableTools_JUI.css +182 -0
  136. data/vendor/datatable/extras/TableTools/media/images/background.png +0 -0
  137. data/vendor/datatable/extras/TableTools/media/images/collection.png +0 -0
  138. data/vendor/datatable/extras/TableTools/media/images/collection_hover.png +0 -0
  139. data/vendor/datatable/extras/TableTools/media/images/copy.png +0 -0
  140. data/vendor/datatable/extras/TableTools/media/images/copy_hover.png +0 -0
  141. data/vendor/datatable/extras/TableTools/media/images/csv.png +0 -0
  142. data/vendor/datatable/extras/TableTools/media/images/csv_hover.png +0 -0
  143. data/vendor/datatable/extras/TableTools/media/images/pdf.png +0 -0
  144. data/vendor/datatable/extras/TableTools/media/images/pdf_hover.png +0 -0
  145. data/vendor/datatable/extras/TableTools/media/images/print.png +0 -0
  146. data/vendor/datatable/extras/TableTools/media/images/print_hover.png +0 -0
  147. data/vendor/datatable/extras/TableTools/media/images/xls.png +0 -0
  148. data/vendor/datatable/extras/TableTools/media/images/xls_hover.png +0 -0
  149. data/vendor/datatable/extras/TableTools/media/js/TableTools.js +2410 -0
  150. data/vendor/datatable/extras/TableTools/media/js/TableTools.min.js +78 -0
  151. data/vendor/datatable/extras/TableTools/media/js/TableTools.min.js.gz +0 -0
  152. data/vendor/datatable/extras/TableTools/media/js/ZeroClipboard.js +365 -0
  153. data/vendor/datatable/extras/TableTools/media/swf/copy_cvs_xls.swf +0 -0
  154. data/vendor/datatable/extras/TableTools/media/swf/copy_cvs_xls_pdf.swf +0 -0
  155. data/vendor/datatable/license-bsd.txt +10 -0
  156. data/vendor/datatable/license-gpl2.txt +339 -0
  157. data/vendor/datatable/media/css/demo_page.css +99 -0
  158. data/vendor/datatable/media/css/demo_table.css +539 -0
  159. data/vendor/datatable/media/css/demo_table_jui.css +521 -0
  160. data/vendor/datatable/media/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  161. data/vendor/datatable/media/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  162. data/vendor/datatable/media/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  163. data/vendor/datatable/media/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  164. data/vendor/datatable/media/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  165. data/vendor/datatable/media/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  166. data/vendor/datatable/media/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  167. data/vendor/datatable/media/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  168. data/vendor/datatable/media/css/smoothness/images/ui-icons_222222_256x240.png +0 -0
  169. data/vendor/datatable/media/css/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  170. data/vendor/datatable/media/css/smoothness/images/ui-icons_454545_256x240.png +0 -0
  171. data/vendor/datatable/media/css/smoothness/images/ui-icons_888888_256x240.png +0 -0
  172. data/vendor/datatable/media/css/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  173. data/vendor/datatable/media/css/smoothness/jquery-ui-1.8.14.custom.css +568 -0
  174. data/vendor/datatable/media/images/back_disabled.jpg +0 -0
  175. data/vendor/datatable/media/images/back_enabled.jpg +0 -0
  176. data/vendor/datatable/media/images/favicon.ico +0 -0
  177. data/vendor/datatable/media/images/forward_disabled.jpg +0 -0
  178. data/vendor/datatable/media/images/forward_enabled.jpg +0 -0
  179. data/vendor/datatable/media/images/sort_asc.png +0 -0
  180. data/vendor/datatable/media/images/sort_asc_disabled.png +0 -0
  181. data/vendor/datatable/media/images/sort_both.png +0 -0
  182. data/vendor/datatable/media/images/sort_desc.png +0 -0
  183. data/vendor/datatable/media/images/sort_desc_disabled.png +0 -0
  184. data/vendor/datatable/media/js/jquery-ui-1.8.14.custom.min.js +789 -0
  185. data/vendor/datatable/media/js/jquery.dataTables.js +7347 -0
  186. data/vendor/datatable/media/js/jquery.dataTables.min.js +151 -0
  187. metadata +270 -0
@@ -0,0 +1,2410 @@
1
+ /*
2
+ * File: TableTools.js
3
+ * Version: 2.0.1
4
+ * Description: Tools and buttons for DataTables
5
+ * Author: Allan Jardine (www.sprymedia.co.uk)
6
+ * Language: Javascript
7
+ * License: LGPL / 3 point BSD
8
+ * Project: DataTables
9
+ *
10
+ * Copyright 2009-2011 Allan Jardine, all rights reserved.
11
+ */
12
+
13
+ /* Global scope for TableTools */
14
+ var TableTools;
15
+
16
+ (function($, window, document) {
17
+
18
+ /**
19
+ * TableTools provides flexible buttons and other tools for a DataTables enhanced table
20
+ * @class TableTools
21
+ * @constructor
22
+ * @param {Object} oDT DataTables instance
23
+ * @param {Object} oOpts TableTools options
24
+ * @param {String} oOpts.sSwfPath ZeroClipboard SWF path
25
+ * @param {String} oOpts.sRowSelect Row selection options - 'none', 'single' or 'multi'
26
+ * @param {Function} oOpts.fnPreRowSelect Callback function just prior to row selection
27
+ * @param {Function} oOpts.fnRowSelected Callback function just after row selection
28
+ * @param {Function} oOpts.fnRowDeselected Callback function when row is deselected
29
+ * @param {Array} oOpts.aButtons List of buttons to be used
30
+ */
31
+ TableTools = function( oDT, oOpts )
32
+ {
33
+ /* Santiy check that we are a new instance */
34
+ if ( !this.CLASS || this.CLASS != "TableTools" )
35
+ {
36
+ alert( "Warning: TableTools must be initialised with the keyword 'new'" );
37
+ }
38
+
39
+
40
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
41
+ * Public class variables
42
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
43
+
44
+ /**
45
+ * @namespace Settings object which contains customisable information for TableTools instance
46
+ */
47
+ this.s = {
48
+ /**
49
+ * Store 'this' so the instance can be retreieved from the settings object
50
+ * @property that
51
+ * @type object
52
+ * @default this
53
+ */
54
+ "that": this,
55
+
56
+ /**
57
+ * DataTables settings objects
58
+ * @property dt
59
+ * @type object
60
+ * @default null
61
+ */
62
+ "dt": null,
63
+
64
+ /**
65
+ * @namespace Print specific information
66
+ */
67
+ "print": {
68
+ /**
69
+ * DataTables draw 'start' point before the printing display was shown
70
+ * @property saveStart
71
+ * @type int
72
+ * @default -1
73
+ */
74
+ "saveStart": -1,
75
+
76
+ /**
77
+ * DataTables draw 'length' point before the printing display was shown
78
+ * @property saveLength
79
+ * @type int
80
+ * @default -1
81
+ */
82
+ "saveLength": -1,
83
+
84
+ /**
85
+ * Page scrolling point before the printing display was shown so it can be restored
86
+ * @property saveScroll
87
+ * @type int
88
+ * @default -1
89
+ */
90
+ "saveScroll": -1,
91
+
92
+ /**
93
+ * Wrapped function to end the print display (to maintain scope)
94
+ * @property funcEnd
95
+ * @type Function
96
+ * @default function () {}
97
+ */
98
+ "funcEnd": function () {}
99
+ },
100
+
101
+ /**
102
+ * A unique ID is assigned to each button in each instance
103
+ * @property buttonCounter
104
+ * @type int
105
+ * @default 0
106
+ */
107
+ "buttonCounter": 0,
108
+
109
+ /**
110
+ * @namespace Select rows specific information
111
+ */
112
+ "select": {
113
+ /**
114
+ * Select type - can be 'none', 'single' or 'multi'
115
+ * @property type
116
+ * @type string
117
+ * @default ""
118
+ */
119
+ "type": "",
120
+
121
+ /**
122
+ * Array of nodes which are currently selected
123
+ * @property selected
124
+ * @type array
125
+ * @default []
126
+ */
127
+ "selected": [],
128
+
129
+ /**
130
+ * Function to run before the selection can take place. Will cancel the select if the
131
+ * function returns false
132
+ * @property preRowSelect
133
+ * @type Function
134
+ * @default null
135
+ */
136
+ "preRowSelect": null,
137
+
138
+ /**
139
+ * Function to run when a row is selected
140
+ * @property postSelected
141
+ * @type Function
142
+ * @default null
143
+ */
144
+ "postSelected": null,
145
+
146
+ /**
147
+ * Function to run when a row is deselected
148
+ * @property postDeselected
149
+ * @type Function
150
+ * @default null
151
+ */
152
+ "postDeselected": null,
153
+
154
+ /**
155
+ * Indicate if all rows are selected (needed for server-side processing)
156
+ * @property all
157
+ * @type boolean
158
+ * @default false
159
+ */
160
+ "all": false,
161
+
162
+ /**
163
+ * Class name to add to selected TR nodes
164
+ * @property selectedClass
165
+ * @type String
166
+ * @default ""
167
+ */
168
+ "selectedClass": ""
169
+ },
170
+
171
+ /**
172
+ * Store of the user input customisation object
173
+ * @property custom
174
+ * @type object
175
+ * @default {}
176
+ */
177
+ "custom": {},
178
+
179
+ /**
180
+ * SWF movie path
181
+ * @property swfPath
182
+ * @type string
183
+ * @default ""
184
+ */
185
+ "swfPath": "",
186
+
187
+ /**
188
+ * Default button set
189
+ * @property buttonSet
190
+ * @type array
191
+ * @default []
192
+ */
193
+ "buttonSet": [],
194
+
195
+ /**
196
+ * When there is more than one TableTools instance for a DataTable, there must be a
197
+ * master which controls events (row selection etc)
198
+ * @property master
199
+ * @type boolean
200
+ * @default false
201
+ */
202
+ "master": false
203
+ };
204
+
205
+
206
+ /**
207
+ * @namespace Common and useful DOM elements for the class instance
208
+ */
209
+ this.dom = {
210
+ /**
211
+ * DIV element that is create and all TableTools buttons (and their children) put into
212
+ * @property container
213
+ * @type node
214
+ * @default null
215
+ */
216
+ "container": null,
217
+
218
+ /**
219
+ * The table node to which TableTools will be applied
220
+ * @property table
221
+ * @type node
222
+ * @default null
223
+ */
224
+ "table": null,
225
+
226
+ /**
227
+ * @namespace Nodes used for the print display
228
+ */
229
+ "print": {
230
+ /**
231
+ * Nodes which have been removed from the display by setting them to display none
232
+ * @property hidden
233
+ * @type array
234
+ * @default []
235
+ */
236
+ "hidden": [],
237
+
238
+ /**
239
+ * The information display saying tellng the user about the print display
240
+ * @property message
241
+ * @type node
242
+ * @default null
243
+ */
244
+ "message": null
245
+ },
246
+
247
+ /**
248
+ * @namespace Nodes used for a collection display. This contains the currently used collection
249
+ */
250
+ "collection": {
251
+ /**
252
+ * The div wrapper containing the buttons in the collection (i.e. the menu)
253
+ * @property collection
254
+ * @type node
255
+ * @default null
256
+ */
257
+ "collection": null,
258
+
259
+ /**
260
+ * Background display to provide focus and capture events
261
+ * @property background
262
+ * @type node
263
+ * @default null
264
+ */
265
+ "background": null
266
+ }
267
+ };
268
+
269
+
270
+
271
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
272
+ * Public class methods
273
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
274
+
275
+ /**
276
+ * Retreieve the settings object from an instance
277
+ * @method fnSettings
278
+ * @returns {object} TableTools settings object
279
+ */
280
+ this.fnSettings = function () {
281
+ return this.s;
282
+ };
283
+
284
+
285
+ /* Constructor logic */
286
+ if ( typeof oOpts == 'undefined' )
287
+ {
288
+ oOpts = {};
289
+ }
290
+
291
+ this.s.dt = oDT.fnSettings();
292
+ this._fnConstruct( oOpts );
293
+
294
+ return this;
295
+ };
296
+
297
+
298
+
299
+ TableTools.prototype = {
300
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
301
+ * Public methods
302
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
303
+
304
+ /**
305
+ * Retreieve the settings object from an instance
306
+ * @method fnGetSelected
307
+ * @returns {array} List of TR nodes which are currently selected
308
+ */
309
+ "fnGetSelected": function ()
310
+ {
311
+ var masterS = this._fnGetMasterSettings();
312
+ return masterS.select.selected;
313
+ },
314
+
315
+ /**
316
+ * Check to see if a current row is selected or not
317
+ * @method fnGetSelected
318
+ * @param {Node} n TR node to check if it is currently selected or not
319
+ * @returns {Boolean} true if select, false otherwise
320
+ */
321
+ "fnIsSelected": function ( n )
322
+ {
323
+ var selected = this.fnGetSelected();
324
+ for ( var i=0, iLen=selected.length ; i<iLen ; i++ )
325
+ {
326
+ if ( n == selected[i] )
327
+ {
328
+ return true;
329
+ }
330
+ }
331
+ return false;
332
+ },
333
+
334
+ /**
335
+ * Select all rows in the table
336
+ * @method fnSelectAll
337
+ * @returns void
338
+ */
339
+ "fnSelectAll": function ()
340
+ {
341
+ var masterS = this._fnGetMasterSettings();
342
+ masterS.that._fnRowSelectAll();
343
+ },
344
+
345
+
346
+ /**
347
+ * Deselect all rows in the table
348
+ * @method fnSelectNone
349
+ * @returns void
350
+ */
351
+ "fnSelectNone": function ()
352
+ {
353
+ var masterS = this._fnGetMasterSettings();
354
+ masterS.that._fnRowDeselectAll();
355
+ },
356
+
357
+
358
+ /**
359
+ * Get the title of the document - useful for file names. The title is retrieved from either
360
+ * the configuration object's 'title' parameter, or the HTML document title
361
+ * @method fnGetTitle
362
+ * @param {Object} oConfig Button configuration object
363
+ * @returns {String} Button title
364
+ */
365
+ "fnGetTitle": function( oConfig )
366
+ {
367
+ var sTitle = "";
368
+ if ( typeof oConfig.sTitle != 'undefined' && oConfig.sTitle !== "" ) {
369
+ sTitle = oConfig.sTitle;
370
+ } else {
371
+ var anTitle = document.getElementsByTagName('title');
372
+ if ( anTitle.length > 0 )
373
+ {
374
+ sTitle = anTitle[0].innerHTML;
375
+ }
376
+ }
377
+
378
+ /* Strip characters which the OS will object to - checking for UTF8 support in the scripting
379
+ * engine
380
+ */
381
+ if ( "\u00A1".toString().length < 4 ) {
382
+ return sTitle.replace(/[^a-zA-Z0-9_\u00A1-\uFFFF\.,\-_ !\(\)]/g, "");
383
+ } else {
384
+ return sTitle.replace(/[^a-zA-Z0-9_\.,\-_ !\(\)]/g, "");
385
+ }
386
+ },
387
+
388
+
389
+ /**
390
+ * Calculate a unity array with the column width by proportion for a set of columns to be
391
+ * included for a button. This is particularly useful for PDF creation, where we can use the
392
+ * column widths calculated by the browser to size the columns in the PDF.
393
+ * @method fnCalcColRations
394
+ * @param {Object} oConfig Button configuration object
395
+ * @returns {Array} Unity array of column ratios
396
+ */
397
+ "fnCalcColRatios": function ( oConfig )
398
+ {
399
+ var
400
+ aoCols = this.s.dt.aoColumns,
401
+ aColumnsInc = this._fnColumnTargets( oConfig.mColumns ),
402
+ aColWidths = [],
403
+ iWidth = 0, iTotal = 0, i, iLen;
404
+
405
+ for ( i=0, iLen=aColumnsInc.length ; i<iLen ; i++ )
406
+ {
407
+ if ( aColumnsInc[i] )
408
+ {
409
+ iWidth = aoCols[i].nTh.offsetWidth;
410
+ iTotal += iWidth;
411
+ aColWidths.push( iWidth );
412
+ }
413
+ }
414
+
415
+ for ( i=0, iLen=aColWidths.length ; i<iLen ; i++ )
416
+ {
417
+ aColWidths[i] = aColWidths[i] / iTotal;
418
+ }
419
+
420
+ return aColWidths.join('\t');
421
+ },
422
+
423
+
424
+ /**
425
+ * Get the information contained in a table as a string
426
+ * @method fnGetTableData
427
+ * @param {Object} oConfig Button configuration object
428
+ * @returns {String} Table data as a string
429
+ */
430
+ "fnGetTableData": function ( oConfig )
431
+ {
432
+ /* In future this could be used to get data from a plain HTML source as well as DataTables */
433
+ if ( this.s.dt )
434
+ {
435
+ return this._fnGetDataTablesData( oConfig );
436
+ }
437
+ },
438
+
439
+
440
+ /**
441
+ * Pass text to a flash button instance, which will be used on the button's click handler
442
+ * @method fnSetText
443
+ * @param {Object} clip Flash button object
444
+ * @param {String} text Text to set
445
+ * @returns void
446
+ */
447
+ "fnSetText": function ( clip, text )
448
+ {
449
+ this._fnFlashSetText( clip, text );
450
+ },
451
+
452
+
453
+ /**
454
+ * Resize the flash elements of the buttons attached to this TableTools instance - this is
455
+ * useful for when initialising TableTools when it is hidden (display:none) since sizes can't
456
+ * be calculated at that time.
457
+ * @method fnResizeButtons
458
+ * @returns void
459
+ */
460
+ "fnResizeButtons": function ()
461
+ {
462
+ for ( var cli in ZeroClipboard.clients )
463
+ {
464
+ if ( cli )
465
+ {
466
+ var client = ZeroClipboard.clients[cli];
467
+ if ( typeof client.domElement != 'undefined' &&
468
+ client.domElement.parentNode == this.dom.container )
469
+ {
470
+ client.positionElement();
471
+ }
472
+ }
473
+ }
474
+ },
475
+
476
+
477
+ /**
478
+ * Check to see if any of the ZeroClipboard client's attached need to be resized
479
+ * @method fnResizeRequired
480
+ * @returns void
481
+ */
482
+ "fnResizeRequired": function ()
483
+ {
484
+ for ( var cli in ZeroClipboard.clients )
485
+ {
486
+ if ( cli )
487
+ {
488
+ var client = ZeroClipboard.clients[cli];
489
+ if ( typeof client.domElement != 'undefined' &&
490
+ client.domElement.parentNode == this.dom.container &&
491
+ client.sized === false )
492
+ {
493
+ return true;
494
+ }
495
+ }
496
+ }
497
+ return false;
498
+ },
499
+
500
+
501
+
502
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
503
+ * Private methods (they are of course public in JS, but recommended as private)
504
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
505
+
506
+ /**
507
+ * Constructor logic
508
+ * @method _fnConstruct
509
+ * @param {Object} oOpts Same as TableTools constructor
510
+ * @returns void
511
+ * @private
512
+ */
513
+ "_fnConstruct": function ( oOpts )
514
+ {
515
+ this._fnCustomiseSettings( oOpts );
516
+
517
+ /* Container element */
518
+ this.dom.container = document.createElement('div');
519
+ this.dom.container.style.position = "relative";
520
+ this.dom.container.className = !this.s.dt.bJUI ? "DTTT_container" :
521
+ "DTTT_container ui-buttonset ui-buttonset-multi";
522
+
523
+ /* Row selection config */
524
+ if ( this.s.select.type != 'none' )
525
+ {
526
+ this._fnRowSelectConfig();
527
+ }
528
+
529
+ /* Buttons */
530
+ this._fnButtonDefinations( this.s.buttonSet, this.dom.container );
531
+ },
532
+
533
+
534
+ /**
535
+ * Take the user defined settings and the default settings and combine them.
536
+ * @method _fnCustomiseSettings
537
+ * @param {Object} oOpts Same as TableTools constructor
538
+ * @returns void
539
+ * @private
540
+ */
541
+ "_fnCustomiseSettings": function ( oOpts )
542
+ {
543
+ /* Is this the master control instance or not? */
544
+ if ( typeof this.s.dt._TableToolsInit == 'undefined' )
545
+ {
546
+ this.s.master = true;
547
+ this.s.dt._TableToolsInit = true;
548
+ }
549
+
550
+ /* We can use the table node from comparisons to group controls */
551
+ this.dom.table = this.s.dt.nTable;
552
+
553
+ /* Clone the defaults and then the user options */
554
+ this.s.custom = $.extend( {}, TableTools.DEFAULTS, oOpts );
555
+
556
+ /* Flash file location */
557
+ this.s.swfPath = this.s.custom.sSwfPath;
558
+ if ( typeof ZeroClipboard != 'undefined' )
559
+ {
560
+ ZeroClipboard.moviePath = this.s.swfPath;
561
+ }
562
+
563
+ /* Table row selecting */
564
+ this.s.select.type = this.s.custom.sRowSelect;
565
+ this.s.select.preRowSelect = this.s.custom.fnPreRowSelect;
566
+ this.s.select.postSelected = this.s.custom.fnRowSelected;
567
+ this.s.select.postDeselected = this.s.custom.fnRowDeselected;
568
+ this.s.select.selectedClass = this.s.custom.sSelectedClass;
569
+
570
+ /* Button set */
571
+ this.s.buttonSet = this.s.custom.aButtons;
572
+ },
573
+
574
+
575
+ /**
576
+ * Take the user input arrays and expand them to be fully defined, and then add them to a given
577
+ * DOM element
578
+ * @method _fnButtonDefinations
579
+ * @param {array} buttonSet Set of user defined buttons
580
+ * @param {node} wrapper Node to add the created buttons to
581
+ * @returns void
582
+ * @private
583
+ */
584
+ "_fnButtonDefinations": function ( buttonSet, wrapper )
585
+ {
586
+ var buttonDef;
587
+
588
+ for ( var i=0, iLen=buttonSet.length ; i<iLen ; i++ )
589
+ {
590
+ if ( typeof buttonSet[i] == "string" )
591
+ {
592
+ if ( typeof TableTools.BUTTONS[ buttonSet[i] ] == 'undefined' )
593
+ {
594
+ alert( "TableTools: Warning - unknown button type: "+buttonSet[i] );
595
+ continue;
596
+ }
597
+ buttonDef = $.extend( {}, TableTools.BUTTONS[ buttonSet[i] ], true );
598
+ }
599
+ else
600
+ {
601
+ if ( typeof TableTools.BUTTONS[ buttonSet[i].sExtends ] == 'undefined' )
602
+ {
603
+ alert( "TableTools: Warning - unknown button type: "+buttonSet[i].sExtends );
604
+ continue;
605
+ }
606
+ var o = $.extend( {}, TableTools.BUTTONS[ buttonSet[i].sExtends ], true );
607
+ buttonDef = $.extend( o, buttonSet[i], true );
608
+ }
609
+
610
+ if ( this.s.dt.bJUI )
611
+ {
612
+ buttonDef.sButtonClass += " ui-button ui-state-default";
613
+ buttonDef.sButtonClassHover += " ui-button ui-state-default ui-state-hover";
614
+ }
615
+
616
+ wrapper.appendChild( this._fnCreateButton( buttonDef ) );
617
+ }
618
+ },
619
+
620
+
621
+ /**
622
+ * Create and configure a TableTools button
623
+ * @method _fnCreateButton
624
+ * @param {Object} oConfig Button configuration object
625
+ * @returns {Node} Button element
626
+ * @private
627
+ */
628
+ "_fnCreateButton": function ( oConfig )
629
+ {
630
+ var nButton = this._fnButtonBase( oConfig );
631
+
632
+ if ( oConfig.sAction == "print" )
633
+ {
634
+ this._fnPrintConfig( nButton, oConfig );
635
+ }
636
+ else if ( oConfig.sAction.match(/flash/) )
637
+ {
638
+ this._fnFlashConfig( nButton, oConfig );
639
+ }
640
+ else if ( oConfig.sAction == "text" )
641
+ {
642
+ this._fnTextConfig( nButton, oConfig );
643
+ }
644
+ else if ( oConfig.sAction == "collection" )
645
+ {
646
+ this._fnTextConfig( nButton, oConfig );
647
+ this._fnCollectionConfig( nButton, oConfig );
648
+ }
649
+
650
+ return nButton;
651
+ },
652
+
653
+
654
+ /**
655
+ * Create the DOM needed for the button and apply some base properties. All buttons start here
656
+ * @method _fnButtonBase
657
+ * @param {o} oConfig Button configuration object
658
+ * @returns {Node} DIV element for the button
659
+ * @private
660
+ */
661
+ "_fnButtonBase": function ( o )
662
+ {
663
+ var
664
+ nButton = document.createElement('button'),
665
+ nSpan = document.createElement('span'),
666
+ masterS = this._fnGetMasterSettings();
667
+
668
+ nButton.className = "DTTT_button "+o.sButtonClass;
669
+ nButton.setAttribute('id', "ToolTables_"+this.s.dt.sInstance+"_"+masterS.buttonCounter );
670
+ nButton.appendChild( nSpan );
671
+ nSpan.innerHTML = o.sButtonText;
672
+
673
+ masterS.buttonCounter++;
674
+
675
+ return nButton;
676
+ },
677
+
678
+
679
+ /**
680
+ * Get the settings object for the master instance. When more than one TableTools instance is
681
+ * assigned to a DataTable, only one of them can be the 'master' (for the select rows). As such,
682
+ * we will typically want to interact with that master for global properties.
683
+ * @method _fnGetMasterSettings
684
+ * @returns {Object} TableTools settings object
685
+ * @private
686
+ */
687
+ "_fnGetMasterSettings": function ()
688
+ {
689
+ if ( this.s.master )
690
+ {
691
+ return this.s;
692
+ }
693
+ else
694
+ {
695
+ /* Look for the master which has the same DT as this one */
696
+ var instances = TableTools._aInstances;
697
+ for ( var i=0, iLen=instances.length ; i<iLen ; i++ )
698
+ {
699
+ if ( this.dom.table == instances[i].s.dt.nTable )
700
+ {
701
+ return instances[i].s;
702
+ }
703
+ }
704
+ }
705
+ },
706
+
707
+
708
+
709
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
710
+ * Button collection functions
711
+ */
712
+
713
+ /**
714
+ * Create a collection button, when activated will present a drop downlist of other buttons
715
+ * @param {Node} nButton Button to use for the collection activation
716
+ * @param {Object} oConfig Button configuration object
717
+ * @returns void
718
+ * @private
719
+ */
720
+ "_fnCollectionConfig": function ( nButton, oConfig )
721
+ {
722
+ var nHidden = document.createElement('div');
723
+ nHidden.style.display = "none";
724
+ nHidden.className = !this.s.dt.bJUI ? "DTTT_collection" :
725
+ "DTTT_collection ui-buttonset ui-buttonset-multi";
726
+ oConfig._collection = nHidden;
727
+
728
+ this._fnButtonDefinations( oConfig.aButtons, nHidden );
729
+ },
730
+
731
+
732
+ /**
733
+ * Show a button collection
734
+ * @param {Node} nButton Button to use for the collection
735
+ * @param {Object} oConfig Button configuration object
736
+ * @returns void
737
+ * @private
738
+ */
739
+ "_fnCollectionShow": function ( nButton, oConfig )
740
+ {
741
+ var
742
+ that = this,
743
+ oPos = $(nButton).offset(),
744
+ nHidden = oConfig._collection,
745
+ iDivX = oPos.left,
746
+ iDivY = oPos.top + $(nButton).outerHeight(),
747
+ iWinHeight = $(window).height(), iDocHeight = $(document).height(),
748
+ iWinWidth = $(window).width(), iDocWidth = $(document).width();
749
+
750
+ nHidden.style.position = "absolute";
751
+ nHidden.style.left = iDivX+"px";
752
+ nHidden.style.top = iDivY+"px";
753
+ nHidden.style.display = "block";
754
+ $(nHidden).css('opacity',0);
755
+
756
+ var nBackground = document.createElement('div');
757
+ nBackground.style.position = "absolute";
758
+ nBackground.style.left = "0px";
759
+ nBackground.style.top = "0px";
760
+ nBackground.style.height = ((iWinHeight>iDocHeight)? iWinHeight : iDocHeight) +"px";
761
+ nBackground.style.width = ((iWinWidth>iDocWidth)? iWinWidth : iDocWidth) +"px";
762
+ nBackground.className = "DTTT_collection_background";
763
+ $(nBackground).css('opacity',0);
764
+
765
+ document.body.appendChild( nBackground );
766
+ document.body.appendChild( nHidden );
767
+
768
+ /* Visual corrections to try and keep the collection visible */
769
+ var iDivWidth = $(nHidden).outerWidth();
770
+ var iDivHeight = $(nHidden).outerHeight();
771
+
772
+ if ( iDivX + iDivWidth > iDocWidth )
773
+ {
774
+ nHidden.style.left = (iDocWidth-iDivWidth)+"px";
775
+ }
776
+
777
+ if ( iDivY + iDivHeight > iDocHeight )
778
+ {
779
+ nHidden.style.top = (iDivY-iDivHeight-$(nButton).outerHeight())+"px";
780
+ }
781
+
782
+ this.dom.collection.collection = nHidden;
783
+ this.dom.collection.background = nBackground;
784
+
785
+ /* This results in a very small delay for the end user but it allows the animation to be
786
+ * much smoother. If you don't want the animation, then the setTimeout can be removed
787
+ */
788
+ setTimeout( function () {
789
+ $(nHidden).animate({"opacity": 1}, 500);
790
+ $(nBackground).animate({"opacity": 0.25}, 500);
791
+ }, 10 );
792
+
793
+ /* Event handler to remove the collection display */
794
+ $(nBackground).click( function () {
795
+ that._fnCollectionHide.call( that, null, null );
796
+ } );
797
+ },
798
+
799
+
800
+ /**
801
+ * Hide a button collection
802
+ * @param {Node} nButton Button to use for the collection
803
+ * @param {Object} oConfig Button configuration object
804
+ * @returns void
805
+ * @private
806
+ */
807
+ "_fnCollectionHide": function ( nButton, oConfig )
808
+ {
809
+ if ( oConfig !== null && oConfig.sExtends == 'collection' )
810
+ {
811
+ return;
812
+ }
813
+
814
+ if ( this.dom.collection.collection !== null )
815
+ {
816
+ $(this.dom.collection.collection).animate({"opacity": 0}, 500, function (e) {
817
+ this.style.display = "none";
818
+ } );
819
+
820
+ $(this.dom.collection.background).animate({"opacity": 0}, 500, function (e) {
821
+ this.parentNode.removeChild( this );
822
+ } );
823
+
824
+ this.dom.collection.collection = null;
825
+ this.dom.collection.background = null;
826
+ }
827
+ },
828
+
829
+
830
+
831
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
832
+ * Row selection functions
833
+ */
834
+
835
+ /**
836
+ * Add event handlers to a table to allow for row selection
837
+ * @method _fnRowSelectConfig
838
+ * @returns void
839
+ * @private
840
+ */
841
+ "_fnRowSelectConfig": function ()
842
+ {
843
+ if ( this.s.master )
844
+ {
845
+ var
846
+ that = this,
847
+ i, iLen,
848
+ aoOpenRows = this.s.dt.aoOpenRows;
849
+
850
+ $(that.s.dt.nTable).addClass( 'DTTT_selectable' );
851
+
852
+ $('tr', that.s.dt.nTBody).live( 'click', function(e) {
853
+ /* Sub-table must be ignored (odd that the selector won't do this with >) */
854
+ if ( this.parentNode != that.s.dt.nTBody )
855
+ {
856
+ return;
857
+ }
858
+
859
+ /* Not interested in selecting 'opened' rows */
860
+ for ( i=0, iLen=aoOpenRows.length ; i<iLen ; i++ )
861
+ {
862
+ if ( this == aoOpenRows[i].nTr )
863
+ {
864
+ return;
865
+ }
866
+ }
867
+
868
+ /* User defined selection function */
869
+ if ( that.s.select.preRowSelect !== null && !that.s.select.preRowSelect.call(that, e) )
870
+ {
871
+ return;
872
+ }
873
+
874
+ /* And go */
875
+ if ( that.s.select.type == "single" )
876
+ {
877
+ that._fnRowSelectSingle.call( that, this );
878
+ }
879
+ else
880
+ {
881
+ that._fnRowSelectMulti.call( that, this );
882
+ }
883
+ } );
884
+
885
+ /* Add a draw callback handler for when 'select' all is active and we are using server-side
886
+ * processing, so TableTools will automatically select the new rows for us
887
+ */
888
+ that.s.dt.aoDrawCallback.push( {
889
+ "fn": function () {
890
+ if ( that.s.select.all && that.s.dt.oFeatures.bServerSide )
891
+ {
892
+ that.fnSelectAll();
893
+ }
894
+ },
895
+ "sName": "TableTools_select"
896
+ } );
897
+ }
898
+ },
899
+
900
+
901
+ /**
902
+ * Select or deselect a row based on its current state when only one row is allowed to be
903
+ * selected at a time (i.e. if there is a row already selected, deselect it). If the selected
904
+ * row is the one being passed in, just deselect and take no further action.
905
+ * @method _fnRowSelectSingle
906
+ * @param {Node} nNode TR element which is being 'activated' in some way
907
+ * @returns void
908
+ * @private
909
+ */
910
+ "_fnRowSelectSingle": function ( nNode )
911
+ {
912
+ if ( this.s.master )
913
+ {
914
+ /* Do nothing on the DataTables 'empty' result set row */
915
+ if ( $('td', nNode).hasClass(this.s.dt.oClasses.sRowEmpty) )
916
+ {
917
+ return;
918
+ }
919
+
920
+ if ( $(nNode).hasClass(this.s.select.selectedClass) )
921
+ {
922
+ this._fnRowDeselect( nNode );
923
+ }
924
+ else
925
+ {
926
+ if ( this.s.select.selected.length !== 0 )
927
+ {
928
+ this._fnRowDeselectAll();
929
+ }
930
+
931
+ this.s.select.selected.push( nNode );
932
+ $(nNode).addClass( this.s.select.selectedClass );
933
+
934
+ if ( this.s.select.postSelected !== null )
935
+ {
936
+ this.s.select.postSelected.call( this, nNode );
937
+ }
938
+ }
939
+
940
+ TableTools._fnEventDispatch( this, 'select', nNode );
941
+ }
942
+ },
943
+
944
+
945
+ /**
946
+ * Select or deselect a row based on its current state when multiple rows are allowed to be
947
+ * selected.
948
+ * @method _fnRowSelectMulti
949
+ * @param {Node} nNode TR element which is being 'activated' in some way
950
+ * @returns void
951
+ * @private
952
+ */
953
+ "_fnRowSelectMulti": function ( nNode )
954
+ {
955
+ if ( this.s.master )
956
+ {
957
+ /* Do nothing on the DataTables 'empty' result set row */
958
+ if ( $('td', nNode).hasClass(this.s.dt.oClasses.sRowEmpty) )
959
+ {
960
+ return;
961
+ }
962
+
963
+ if ( $(nNode).hasClass(this.s.select.selectedClass) )
964
+ {
965
+ this._fnRowDeselect( nNode );
966
+ }
967
+ else
968
+ {
969
+ this.s.select.selected.push( nNode );
970
+ $(nNode).addClass( this.s.select.selectedClass );
971
+
972
+ if ( this.s.select.postSelected !== null )
973
+ {
974
+ this.s.select.postSelected.call( this, nNode );
975
+ }
976
+ }
977
+
978
+ TableTools._fnEventDispatch( this, 'select', nNode );
979
+ }
980
+ },
981
+
982
+
983
+ /**
984
+ * Select all TR elements in the table. Note that this function will still operate in 'single'
985
+ * select mode, which might not be what you desire (in which case, don't call this function!)
986
+ * @method _fnRowSelectAll
987
+ * @returns void
988
+ * @private
989
+ */
990
+ "_fnRowSelectAll": function ( )
991
+ {
992
+ if ( this.s.master )
993
+ {
994
+ var n;
995
+ for ( var i=0, iLen=this.s.dt.aiDisplayMaster.length ; i<iLen ; i++ )
996
+ {
997
+ n = this.s.dt.aoData[ this.s.dt.aiDisplayMaster[i] ].nTr;
998
+
999
+ if ( !$(n).hasClass(this.s.select.selectedClass) )
1000
+ {
1001
+ this.s.select.selected.push( n );
1002
+ $(n).addClass( this.s.select.selectedClass );
1003
+ }
1004
+ }
1005
+
1006
+ this.s.select.all = true;
1007
+ TableTools._fnEventDispatch( this, 'select', null );
1008
+ }
1009
+ },
1010
+
1011
+
1012
+ /**
1013
+ * Deselect all TR elements in the table. If nothing is currently selected, then no action is
1014
+ * taken.
1015
+ * @method _fnRowDeselectAll
1016
+ * @returns void
1017
+ * @private
1018
+ */
1019
+ "_fnRowDeselectAll": function ( )
1020
+ {
1021
+ if ( this.s.master )
1022
+ {
1023
+ for ( var i=this.s.select.selected.length-1 ; i>=0 ; i-- )
1024
+ {
1025
+ this._fnRowDeselect( i );
1026
+ }
1027
+
1028
+ this.s.select.all = false;
1029
+ TableTools._fnEventDispatch( this, 'select', null );
1030
+ }
1031
+ },
1032
+
1033
+
1034
+ /**
1035
+ * Deselect a single row, based on its index in the selected array, or a TR node (when the
1036
+ * index is then computed)
1037
+ * @method _fnRowDeselect
1038
+ * @param {int|Node} i Node or index of node in selected array, which is to be deselected
1039
+ * @returns void
1040
+ * @private
1041
+ */
1042
+ "_fnRowDeselect": function ( i )
1043
+ {
1044
+ if ( typeof i.nodeName != 'undefined' )
1045
+ {
1046
+ i = $.inArray( i, this.s.select.selected );
1047
+ }
1048
+
1049
+ var nNode = this.s.select.selected[i];
1050
+ $(nNode).removeClass(this.s.select.selectedClass);
1051
+ this.s.select.selected.splice( i, 1 );
1052
+
1053
+ if ( this.s.select.postDeselected !== null )
1054
+ {
1055
+ this.s.select.postDeselected.call( this, nNode );
1056
+ }
1057
+
1058
+ this.s.select.all = false;
1059
+ },
1060
+
1061
+
1062
+
1063
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1064
+ * Text button functions
1065
+ */
1066
+
1067
+ /**
1068
+ * Configure a text based button for interaction events
1069
+ * @method _fnTextConfig
1070
+ * @param {Node} nButton Button element which is being considered
1071
+ * @param {Object} oConfig Button configuration object
1072
+ * @returns void
1073
+ * @private
1074
+ */
1075
+ "_fnTextConfig": function ( nButton, oConfig )
1076
+ {
1077
+ var that = this;
1078
+
1079
+ if ( oConfig.fnInit !== null )
1080
+ {
1081
+ oConfig.fnInit.call( this, nButton, oConfig );
1082
+ }
1083
+
1084
+ if ( oConfig.sToolTip !== "" )
1085
+ {
1086
+ nButton.title = oConfig.sToolTip;
1087
+ }
1088
+
1089
+ $(nButton).hover( function () {
1090
+ $(nButton).removeClass( oConfig.sButtonClass ).
1091
+ addClass(oConfig.sButtonClassHover );
1092
+ if ( oConfig.fnMouseover !== null )
1093
+ {
1094
+ oConfig.fnMouseover.call( this, nButton, oConfig, null );
1095
+ }
1096
+ }, function () {
1097
+ $(nButton).removeClass( oConfig.sButtonClassHover ).
1098
+ addClass( oConfig.sButtonClass );
1099
+ if ( oConfig.fnMouseout !== null )
1100
+ {
1101
+ oConfig.fnMouseout.call( this, nButton, oConfig, null );
1102
+ }
1103
+ } );
1104
+
1105
+ if ( oConfig.fnSelect !== null )
1106
+ {
1107
+ TableTools._fnEventListen( this, 'select', function (n) {
1108
+ oConfig.fnSelect.call( that, nButton, oConfig, n );
1109
+ } );
1110
+ }
1111
+
1112
+ $(nButton).click( function (e) {
1113
+ e.preventDefault();
1114
+
1115
+ if ( oConfig.fnClick !== null )
1116
+ {
1117
+ oConfig.fnClick.call( that, nButton, oConfig, null );
1118
+ }
1119
+
1120
+ /* Provide a complete function to match the behaviour of the flash elements */
1121
+ if ( oConfig.fnComplete !== null )
1122
+ {
1123
+ oConfig.fnComplete.call( that, nButton, oConfig, null, null );
1124
+ }
1125
+
1126
+ that._fnCollectionHide( nButton, oConfig );
1127
+ } );
1128
+ },
1129
+
1130
+
1131
+
1132
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1133
+ * Flash button functions
1134
+ */
1135
+
1136
+ /**
1137
+ * Configure a flash based button for interaction events
1138
+ * @method _fnFlashConfig
1139
+ * @param {Node} nButton Button element which is being considered
1140
+ * @param {o} oConfig Button configuration object
1141
+ * @returns void
1142
+ * @private
1143
+ */
1144
+ "_fnFlashConfig": function ( nButton, oConfig )
1145
+ {
1146
+ var that = this;
1147
+ var flash = new ZeroClipboard.Client();
1148
+
1149
+ if ( oConfig.fnInit !== null )
1150
+ {
1151
+ oConfig.fnInit.call( this, nButton, oConfig );
1152
+ }
1153
+
1154
+ flash.setHandCursor( true );
1155
+
1156
+ if ( oConfig.sAction == "flash_save" )
1157
+ {
1158
+ flash.setAction( 'save' );
1159
+ flash.setCharSet( (oConfig.sCharSet=="utf16le") ? 'UTF16LE' : 'UTF8' );
1160
+ flash.setBomInc( oConfig.bBomInc );
1161
+ flash.setFileName( oConfig.sFileName.replace('*', this.fnGetTitle(oConfig)) );
1162
+ }
1163
+ else if ( oConfig.sAction == "flash_pdf" )
1164
+ {
1165
+ flash.setAction( 'pdf' );
1166
+ flash.setFileName( oConfig.sFileName.replace('*', this.fnGetTitle(oConfig)) );
1167
+ }
1168
+ else
1169
+ {
1170
+ flash.setAction( 'copy' );
1171
+ }
1172
+
1173
+ flash.addEventListener('mouseOver', function(client) {
1174
+ $(nButton).removeClass( oConfig.sButtonClass ).
1175
+ addClass(oConfig.sButtonClassHover );
1176
+
1177
+ if ( oConfig.fnMouseover !== null )
1178
+ {
1179
+ oConfig.fnMouseover.call( that, nButton, oConfig, flash );
1180
+ }
1181
+ } );
1182
+
1183
+ flash.addEventListener('mouseOut', function(client) {
1184
+ $(nButton).removeClass( oConfig.sButtonClassHover ).
1185
+ addClass(oConfig.sButtonClass );
1186
+
1187
+ if ( oConfig.fnMouseout !== null )
1188
+ {
1189
+ oConfig.fnMouseout.call( that, nButton, oConfig, flash );
1190
+ }
1191
+ } );
1192
+
1193
+ flash.addEventListener('mouseDown', function(client) {
1194
+ if ( oConfig.fnClick !== null )
1195
+ {
1196
+ oConfig.fnClick.call( that, nButton, oConfig, flash );
1197
+ }
1198
+ } );
1199
+
1200
+ flash.addEventListener('complete', function (client, text) {
1201
+ if ( oConfig.fnComplete !== null )
1202
+ {
1203
+ oConfig.fnComplete.call( that, nButton, oConfig, flash, text );
1204
+ }
1205
+ that._fnCollectionHide( nButton, oConfig );
1206
+ } );
1207
+
1208
+ this._fnFlashGlue( flash, nButton, oConfig.sToolTip );
1209
+ },
1210
+
1211
+
1212
+ /**
1213
+ * Wait until the id is in the DOM before we "glue" the swf. Note that this function will call
1214
+ * itself (using setTimeout) until it completes successfully
1215
+ * @method _fnFlashGlue
1216
+ * @param {Object} clip Zero clipboard object
1217
+ * @param {Node} node node to glue swf to
1218
+ * @param {String} text title of the flash movie
1219
+ * @returns void
1220
+ * @private
1221
+ */
1222
+ "_fnFlashGlue": function ( flash, node, text )
1223
+ {
1224
+ var that = this;
1225
+ var id = node.getAttribute('id');
1226
+
1227
+ if ( document.getElementById(id) )
1228
+ {
1229
+ flash.glue( node, text );
1230
+
1231
+ /* Catch those who are using a TableTools 1 version of ZeroClipboard */
1232
+ if ( flash.domElement.parentNode != flash.div.parentNode &&
1233
+ typeof that.__bZCWarning == 'undefined' )
1234
+ {
1235
+ that.s.dt.oApi._fnLog( this.s.dt, 0, "It looks like you are using the version of "+
1236
+ "ZeroClipboard which came with TableTools 1. Please update to use the version that "+
1237
+ "came with TableTools 2." );
1238
+ that.__bZCWarning = true;
1239
+ }
1240
+ }
1241
+ else
1242
+ {
1243
+ setTimeout( function () {
1244
+ that._fnFlashGlue( flash, node, text );
1245
+ }, 100 );
1246
+ }
1247
+ },
1248
+
1249
+
1250
+ /**
1251
+ * Set the text for the flash clip to deal with
1252
+ *
1253
+ * This function is required for large information sets. There is a limit on the
1254
+ * amount of data that can be transfered between Javascript and Flash in a single call, so
1255
+ * we use this method to build up the text in Flash by sending over chunks. It is estimated
1256
+ * that the data limit is around 64k, although it is undocuments, and appears to be different
1257
+ * between different flash versions. We chunk at 8KiB.
1258
+ * @method _fnFlashSetText
1259
+ * @param {Object} clip the ZeroClipboard object
1260
+ * @param {String} sData the data to be set
1261
+ * @returns void
1262
+ * @private
1263
+ */
1264
+ "_fnFlashSetText": function ( clip, sData )
1265
+ {
1266
+ var asData = this._fnChunkData( sData, 8192 );
1267
+
1268
+ clip.clearText();
1269
+ for ( var i=0, iLen=asData.length ; i<iLen ; i++ )
1270
+ {
1271
+ clip.appendText( asData[i] );
1272
+ }
1273
+ },
1274
+
1275
+
1276
+
1277
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1278
+ * Data retrieval functions
1279
+ */
1280
+
1281
+ /**
1282
+ * Convert the mixed columns variable into a boolean array the same size as the columns, which
1283
+ * indicates which columns we want to include
1284
+ * @method _fnColumnTargets
1285
+ * @param {String|Array} mColumns The columns to be included in data retreieval. If a string
1286
+ * then it can take the value of "visible" or "hidden" (to include all visible or
1287
+ * hidden columns respectively). Or an array of column indexes
1288
+ * @returns {Array} A boolean array the length of the columns of the table, which each value
1289
+ * indicating if the column is to be included or not
1290
+ * @private
1291
+ */
1292
+ "_fnColumnTargets": function ( mColumns )
1293
+ {
1294
+ var aColumns = [];
1295
+ var dt = this.s.dt;
1296
+
1297
+ if ( typeof mColumns == "object" )
1298
+ {
1299
+ for ( i=0, iLen=dt.aoColumns.length ; i<iLen ; i++ )
1300
+ {
1301
+ aColumns.push( false );
1302
+ }
1303
+
1304
+ for ( i=0, iLen=mColumns.length ; i<iLen ; i++ )
1305
+ {
1306
+ aColumns[ mColumns[i] ] = true;
1307
+ }
1308
+ }
1309
+ else if ( mColumns == "visible" )
1310
+ {
1311
+ for ( i=0, iLen=dt.aoColumns.length ; i<iLen ; i++ )
1312
+ {
1313
+ aColumns.push( dt.aoColumns[i].bVisible ? true : false );
1314
+ }
1315
+ }
1316
+ else if ( mColumns == "hidden" )
1317
+ {
1318
+ for ( i=0, iLen=dt.aoColumns.length ; i<iLen ; i++ )
1319
+ {
1320
+ aColumns.push( dt.aoColumns[i].bVisible ? false : true );
1321
+ }
1322
+ }
1323
+ else /* all */
1324
+ {
1325
+ for ( i=0, iLen=dt.aoColumns.length ; i<iLen ; i++ )
1326
+ {
1327
+ aColumns.push( true );
1328
+ }
1329
+ }
1330
+
1331
+ return aColumns;
1332
+ },
1333
+
1334
+
1335
+ /**
1336
+ * New line character(s) depend on the platforms
1337
+ * @method method
1338
+ * @param {Object} oConfig Button configuration object - only interested in oConfig.sNewLine
1339
+ * @returns {String} Newline character
1340
+ */
1341
+ "_fnNewline": function ( oConfig )
1342
+ {
1343
+ if ( oConfig.sNewLine == "auto" )
1344
+ {
1345
+ return navigator.userAgent.match(/Windows/) ? "\r\n" : "\n";
1346
+ }
1347
+ else
1348
+ {
1349
+ return oConfig.sNewLine;
1350
+ }
1351
+ },
1352
+
1353
+
1354
+ /**
1355
+ * Get data from DataTables' internals and format it for output
1356
+ * @method _fnGetDataTablesData
1357
+ * @param {Object} oConfig Button configuration object
1358
+ * @param {String} oConfig.sFieldBoundary Field boundary for the data cells in the string
1359
+ * @param {String} oConfig.sFieldSeperator Field seperator for the data cells
1360
+ * @param {String} oConfig.sNewline New line options
1361
+ * @param {Mixed} oConfig.mColumns Which columns should be included in the output
1362
+ * @param {Boolean} oConfig.bHeader Include the header
1363
+ * @param {Boolean} oConfig.bFooter Include the footer
1364
+ * @param {Boolean} oConfig.bSelectedOnly Include only the selected rows in the output
1365
+ * @returns {String} Concatinated string of data
1366
+ * @private
1367
+ */
1368
+ "_fnGetDataTablesData": function ( oConfig )
1369
+ {
1370
+ var i, iLen, j, jLen;
1371
+ var sData = '', sLoopData = '';
1372
+ var dt = this.s.dt;
1373
+ var regex = new RegExp(oConfig.sFieldBoundary, "g"); /* Do it here for speed */
1374
+ var aColumnsInc = this._fnColumnTargets( oConfig.mColumns );
1375
+ var sNewline = this._fnNewline( oConfig );
1376
+
1377
+ /*
1378
+ * Header
1379
+ */
1380
+ if ( oConfig.bHeader )
1381
+ {
1382
+ for ( i=0, iLen=dt.aoColumns.length ; i<iLen ; i++ )
1383
+ {
1384
+ if ( aColumnsInc[i] )
1385
+ {
1386
+ sLoopData = dt.aoColumns[i].sTitle.replace(/\n/g," ").replace( /<.*?>/g, "" );
1387
+ sLoopData = this._fnHtmlDecode( sLoopData );
1388
+
1389
+ sData += this._fnBoundData( sLoopData, oConfig.sFieldBoundary, regex ) +
1390
+ oConfig.sFieldSeperator;
1391
+ }
1392
+ }
1393
+ sData = sData.slice( 0, oConfig.sFieldSeperator.length*-1 );
1394
+ sData += sNewline;
1395
+ }
1396
+
1397
+ /*
1398
+ * Body
1399
+ */
1400
+ for ( j=0, jLen=dt.aiDisplay.length ; j<jLen ; j++ )
1401
+ {
1402
+ if ( typeof oConfig.bSelectedOnly && oConfig.bSelectedOnly &&
1403
+ !$(dt.aoData[ dt.aiDisplay[j] ].nTr).hasClass( this.s.select.selectedClass ) )
1404
+ {
1405
+ continue;
1406
+ }
1407
+
1408
+ /* Columns */
1409
+ for ( i=0, iLen=dt.aoColumns.length ; i<iLen ; i++ )
1410
+ {
1411
+ if ( aColumnsInc[i] )
1412
+ {
1413
+ /* Convert to strings (with small optimisation) */
1414
+ var mTypeData = dt.aoData[ dt.aiDisplay[j] ]._aData[ i ];
1415
+ if ( typeof mTypeData == "string" )
1416
+ {
1417
+ /* Strip newlines, replace img tags with alt attr. and finally strip html... */
1418
+ sLoopData = mTypeData.replace(/\n/g," ");
1419
+ sLoopData =
1420
+ sLoopData.replace(/<img.*?\s+alt\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s>]+)).*?>/gi,
1421
+ '$1$2$3');
1422
+ sLoopData = sLoopData.replace( /<.*?>/g, "" );
1423
+ }
1424
+ else
1425
+ {
1426
+ sLoopData = mTypeData+"";
1427
+ }
1428
+
1429
+ /* Trim and clean the data */
1430
+ sLoopData = sLoopData.replace(/^\s+/, '').replace(/\s+$/, '');
1431
+ sLoopData = this._fnHtmlDecode( sLoopData );
1432
+
1433
+ /* Bound it and add it to the total data */
1434
+ sData += this._fnBoundData( sLoopData, oConfig.sFieldBoundary, regex ) +
1435
+ oConfig.sFieldSeperator;
1436
+ }
1437
+ }
1438
+ sData = sData.slice( 0, oConfig.sFieldSeperator.length*-1 );
1439
+ sData += sNewline;
1440
+ }
1441
+
1442
+ /* Remove the last new line */
1443
+ sData.slice( 0, -1 );
1444
+
1445
+ /*
1446
+ * Footer
1447
+ */
1448
+ if ( oConfig.bFooter )
1449
+ {
1450
+ for ( i=0, iLen=dt.aoColumns.length ; i<iLen ; i++ )
1451
+ {
1452
+ if ( aColumnsInc[i] && dt.aoColumns[i].nTf !== null )
1453
+ {
1454
+ sLoopData = dt.aoColumns[i].nTf.innerHTML.replace(/\n/g," ").replace( /<.*?>/g, "" );
1455
+ sLoopData = this._fnHtmlDecode( sLoopData );
1456
+
1457
+ sData += this._fnBoundData( sLoopData, oConfig.sFieldBoundary, regex ) +
1458
+ oConfig.sFieldSeperator;
1459
+ }
1460
+ }
1461
+ sData = sData.slice( 0, oConfig.sFieldSeperator.length*-1 );
1462
+ }
1463
+
1464
+ /* No pointers here - this is a string copy :-) */
1465
+ _sLastData = sData;
1466
+ return sData;
1467
+ },
1468
+
1469
+
1470
+ /**
1471
+ * Wrap data up with a boundary string
1472
+ * @method _fnBoundData
1473
+ * @param {String} sData data to bound
1474
+ * @param {String} sBoundary bounding char(s)
1475
+ * @param {RegExp} regex search for the bounding chars - constructed outside for efficincy
1476
+ * in the loop
1477
+ * @returns {String} bound data
1478
+ * @private
1479
+ */
1480
+ "_fnBoundData": function ( sData, sBoundary, regex )
1481
+ {
1482
+ if ( sBoundary === "" )
1483
+ {
1484
+ return sData;
1485
+ }
1486
+ else
1487
+ {
1488
+ return sBoundary + sData.replace(regex, "\\"+sBoundary) + sBoundary;
1489
+ }
1490
+ },
1491
+
1492
+
1493
+ /**
1494
+ * Break a string up into an array of smaller strings
1495
+ * @method _fnChunkData
1496
+ * @param {String} sData data to be broken up
1497
+ * @param {Int} iSize chunk size
1498
+ * @returns {Array} String array of broken up text
1499
+ * @private
1500
+ */
1501
+ "_fnChunkData": function ( sData, iSize )
1502
+ {
1503
+ var asReturn = [];
1504
+ var iStrlen = sData.length;
1505
+
1506
+ for ( var i=0 ; i<iStrlen ; i+=iSize )
1507
+ {
1508
+ if ( i+iSize < iStrlen )
1509
+ {
1510
+ asReturn.push( sData.substring( i, i+iSize ) );
1511
+ }
1512
+ else
1513
+ {
1514
+ asReturn.push( sData.substring( i, iStrlen ) );
1515
+ }
1516
+ }
1517
+
1518
+ return asReturn;
1519
+ },
1520
+
1521
+
1522
+ /**
1523
+ * Decode HTML entities
1524
+ * @method _fnHtmlDecode
1525
+ * @param {String} sData encoded string
1526
+ * @returns {String} decoded string
1527
+ * @private
1528
+ */
1529
+ "_fnHtmlDecode": function ( sData )
1530
+ {
1531
+ if ( sData.indexOf('&') == -1 )
1532
+ {
1533
+ return sData;
1534
+ }
1535
+
1536
+ var
1537
+ aData = this._fnChunkData( sData, 2048 ),
1538
+ n = document.createElement('div'),
1539
+ i, iLen, iIndex,
1540
+ sReturn = "", sInner;
1541
+
1542
+ /* nodeValue has a limit in browsers - so we chunk the data into smaller segments to build
1543
+ * up the string. Note that the 'trick' here is to remember than we might have split over
1544
+ * an HTML entity, so we backtrack a little to make sure this doesn't happen
1545
+ */
1546
+ for ( i=0, iLen=aData.length ; i<iLen ; i++ )
1547
+ {
1548
+ /* Magic number 8 is because no entity is longer then strlen 8 in ISO 8859-1 */
1549
+ iIndex = aData[i].lastIndexOf( '&' );
1550
+ if ( iIndex != -1 && aData[i].length >= 8 && iIndex > aData[i].length - 8 )
1551
+ {
1552
+ sInner = aData[i].substr( iIndex );
1553
+ aData[i] = aData[i].substr( 0, iIndex );
1554
+ }
1555
+
1556
+ n.innerHTML = aData[i];
1557
+ sReturn += n.childNodes[0].nodeValue;
1558
+ }
1559
+
1560
+ return sReturn;
1561
+ },
1562
+
1563
+
1564
+
1565
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1566
+ * Printing functions
1567
+ */
1568
+
1569
+ /**
1570
+ * Configure a button for printing
1571
+ * @method _fnPrintConfig
1572
+ * @param {Node} nButton Button element which is being considered
1573
+ * @param {Object} oConfig Button configuration object
1574
+ * @returns void
1575
+ * @private
1576
+ */
1577
+ "_fnPrintConfig": function ( nButton, oConfig )
1578
+ {
1579
+ var that = this;
1580
+
1581
+ if ( oConfig.fnInit !== null )
1582
+ {
1583
+ oConfig.fnInit.call( this, nButton, oConfig );
1584
+ }
1585
+
1586
+ $(nButton).hover( function () {
1587
+ $(nButton).removeClass( oConfig.sButtonClass ).
1588
+ addClass(oConfig.sButtonClassHover );
1589
+ }, function () {
1590
+ $(nButton).removeClass( oConfig.sButtonClassHover ).
1591
+ addClass(oConfig.sButtonClass );
1592
+ } );
1593
+
1594
+ if ( oConfig.fnSelect !== null )
1595
+ {
1596
+ TableTools._fnEventListen( this, 'select', function (n) {
1597
+ oConfig.fnSelect.call( that, nButton, oConfig, n );
1598
+ } );
1599
+ }
1600
+
1601
+ $(nButton).click( function (e) {
1602
+ e.preventDefault();
1603
+
1604
+ that._fnPrintStart.call( that, e, oConfig);
1605
+
1606
+ if ( oConfig.fnClick !== null )
1607
+ {
1608
+ oConfig.fnClick.call( that, nButton, oConfig, null );
1609
+ }
1610
+
1611
+ /* Provide a complete function to match the behaviour of the flash elements */
1612
+ if ( oConfig.fnComplete !== null )
1613
+ {
1614
+ oConfig.fnComplete.call( that, nButton, oConfig, null, null );
1615
+ }
1616
+
1617
+ that._fnCollectionHide( nButton, oConfig );
1618
+ } );
1619
+ },
1620
+
1621
+ /**
1622
+ * Show print display
1623
+ * @method _fnPrintStart
1624
+ * @param {Event} e Event object
1625
+ * @param {Object} oConfig Button configuration object
1626
+ * @returns void
1627
+ * @private
1628
+ */
1629
+ "_fnPrintStart": function ( e, oConfig )
1630
+ {
1631
+ var that = this;
1632
+ var oSetDT = this.s.dt;
1633
+
1634
+ /* Parse through the DOM hiding everything that isn't needed for the table */
1635
+ this._fnPrintHideNodes( oSetDT.nTable );
1636
+
1637
+ /* Show the whole table */
1638
+ this.s.print.saveStart = oSetDT._iDisplayStart;
1639
+ this.s.print.saveLength = oSetDT._iDisplayLength;
1640
+
1641
+ if ( oConfig.bShowAll )
1642
+ {
1643
+ oSetDT._iDisplayStart = 0;
1644
+ oSetDT._iDisplayLength = -1;
1645
+ oSetDT.oApi._fnCalculateEnd( oSetDT );
1646
+ oSetDT.oApi._fnDraw( oSetDT );
1647
+ }
1648
+
1649
+ /* Adjust the display for scrolling which might be done by DataTables */
1650
+ if ( oSetDT.oScroll.sX !== "" || oSetDT.oScroll.sY !== "" )
1651
+ {
1652
+ this._fnPrintScrollStart( oSetDT );
1653
+ }
1654
+
1655
+ /* Remove the other DataTables feature nodes - but leave the table! and info div */
1656
+ var anFeature = oSetDT.aanFeatures;
1657
+ for ( var cFeature in anFeature )
1658
+ {
1659
+ if ( cFeature != 'i' && cFeature != 't' && cFeature.length == 1 )
1660
+ {
1661
+ for ( var i=0, iLen=anFeature[cFeature].length ; i<iLen ; i++ )
1662
+ {
1663
+ this.dom.print.hidden.push( {
1664
+ "node": anFeature[cFeature][i],
1665
+ "display": "block"
1666
+ } );
1667
+ anFeature[cFeature][i].style.display = "none";
1668
+ }
1669
+ }
1670
+ }
1671
+
1672
+ /* Print class can be used for styling */
1673
+ $(document.body).addClass( 'DTTT_Print' );
1674
+
1675
+ /* Add a node telling the user what is going on */
1676
+ if ( oConfig.sInfo !== "" )
1677
+ {
1678
+ var nInfo = document.createElement( "div" );
1679
+ nInfo.className = "DTTT_print_info";
1680
+ nInfo.innerHTML = oConfig.sInfo;
1681
+ document.body.appendChild( nInfo );
1682
+
1683
+ setTimeout( function() {
1684
+ $(nInfo).fadeOut( "normal", function() {
1685
+ document.body.removeChild( nInfo );
1686
+ } );
1687
+ }, 2000 );
1688
+ }
1689
+
1690
+ /* Add a message at the top of the page */
1691
+ if ( oConfig.sMessage !== "" )
1692
+ {
1693
+ this.dom.print.message = document.createElement( "div" );
1694
+ this.dom.print.message.className = "DTTT_PrintMessage";
1695
+ this.dom.print.message.innerHTML = oConfig.sMessage;
1696
+ document.body.insertBefore( this.dom.print.message, document.body.childNodes[0] );
1697
+ }
1698
+
1699
+ /* Cache the scrolling and the jump to the top of the t=page */
1700
+ this.s.print.saveScroll = $(window).scrollTop();
1701
+ window.scrollTo( 0, 0 );
1702
+
1703
+ this.s.print.funcEnd = function(e) {
1704
+ that._fnPrintEnd.call( that, e );
1705
+ };
1706
+ $(document).bind( "keydown", null, this.s.print.funcEnd );
1707
+ },
1708
+
1709
+
1710
+ /**
1711
+ * Printing is finished, resume normal display
1712
+ * @method _fnPrintEnd
1713
+ * @param {Event} e Event object
1714
+ * @returns void
1715
+ * @private
1716
+ */
1717
+ "_fnPrintEnd": function ( e )
1718
+ {
1719
+ /* Only interested in the escape key */
1720
+ if ( e.keyCode == 27 )
1721
+ {
1722
+ e.preventDefault();
1723
+
1724
+ var that = this;
1725
+ var oSetDT = this.s.dt;
1726
+ var oSetPrint = this.s.print;
1727
+ var oDomPrint = this.dom.print;
1728
+
1729
+ /* Show all hidden nodes */
1730
+ this._fnPrintShowNodes();
1731
+
1732
+ /* Restore DataTables' scrolling */
1733
+ if ( oSetDT.oScroll.sX !== "" || oSetDT.oScroll.sY !== "" )
1734
+ {
1735
+ this._fnPrintScrollEnd();
1736
+ }
1737
+
1738
+ /* Restore the scroll */
1739
+ window.scrollTo( 0, oSetPrint.saveScroll );
1740
+
1741
+ /* Drop the print message */
1742
+ if ( oDomPrint.message !== null )
1743
+ {
1744
+ document.body.removeChild( oDomPrint.message );
1745
+ oDomPrint.message = null;
1746
+ }
1747
+
1748
+ /* Styling class */
1749
+ $(document.body).removeClass( 'DTTT_Print' );
1750
+
1751
+ /* Restore the table length */
1752
+ oSetDT._iDisplayStart = oSetPrint.saveStart;
1753
+ oSetDT._iDisplayLength = oSetPrint.saveLength;
1754
+ oSetDT.oApi._fnCalculateEnd( oSetDT );
1755
+ oSetDT.oApi._fnDraw( oSetDT );
1756
+
1757
+ $(document).unbind( "keydown", this.s.print.funcEnd );
1758
+ this.s.print.funcEnd = null;
1759
+ }
1760
+ },
1761
+
1762
+
1763
+ /**
1764
+ * Take account of scrolling in DataTables by showing the full table
1765
+ * @returns void
1766
+ * @private
1767
+ */
1768
+ "_fnPrintScrollStart": function ()
1769
+ {
1770
+ var
1771
+ oSetDT = this.s.dt,
1772
+ nScrollHeadInner = oSetDT.nScrollHead.getElementsByTagName('div')[0],
1773
+ nScrollHeadTable = nScrollHeadInner.getElementsByTagName('table')[0],
1774
+ nScrollBody = oSetDT.nTable.parentNode;
1775
+
1776
+ /* Copy the header in the thead in the body table, this way we show one single table when
1777
+ * in print view. Note that this section of code is more or less verbatim from DT 1.7.0
1778
+ */
1779
+ var nTheadSize = oSetDT.nTable.getElementsByTagName('thead');
1780
+ if ( nTheadSize.length > 0 )
1781
+ {
1782
+ oSetDT.nTable.removeChild( nTheadSize[0] );
1783
+ }
1784
+
1785
+ if ( oSetDT.nTFoot !== null )
1786
+ {
1787
+ var nTfootSize = oSetDT.nTable.getElementsByTagName('tfoot');
1788
+ if ( nTfootSize.length > 0 )
1789
+ {
1790
+ oSetDT.nTable.removeChild( nTfootSize[0] );
1791
+ }
1792
+ }
1793
+
1794
+ nTheadSize = oSetDT.nTHead.cloneNode(true);
1795
+ oSetDT.nTable.insertBefore( nTheadSize, oSetDT.nTable.childNodes[0] );
1796
+
1797
+ if ( oSetDT.nTFoot !== null )
1798
+ {
1799
+ nTfootSize = oSetDT.nTFoot.cloneNode(true);
1800
+ oSetDT.nTable.insertBefore( nTfootSize, oSetDT.nTable.childNodes[1] );
1801
+ }
1802
+
1803
+ /* Now adjust the table's viewport so we can actually see it */
1804
+ if ( oSetDT.oScroll.sX !== "" )
1805
+ {
1806
+ oSetDT.nTable.style.width = $(oSetDT.nTable).outerWidth()+"px";
1807
+ nScrollBody.style.width = $(oSetDT.nTable).outerWidth()+"px";
1808
+ nScrollBody.style.overflow = "visible";
1809
+ }
1810
+
1811
+ if ( oSetDT.oScroll.sY !== "" )
1812
+ {
1813
+ nScrollBody.style.height = $(oSetDT.nTable).outerHeight()+"px";
1814
+ nScrollBody.style.overflow = "visible";
1815
+ }
1816
+ },
1817
+
1818
+
1819
+ /**
1820
+ * Take account of scrolling in DataTables by showing the full table. Note that the redraw of
1821
+ * the DataTable that we do will actually deal with the majority of the hardword here
1822
+ * @returns void
1823
+ * @private
1824
+ */
1825
+ "_fnPrintScrollEnd": function ()
1826
+ {
1827
+ var
1828
+ oSetDT = this.s.dt,
1829
+ nScrollBody = oSetDT.nTable.parentNode;
1830
+
1831
+ if ( oSetDT.oScroll.sX !== "" )
1832
+ {
1833
+ nScrollBody.style.width = oSetDT.oApi._fnStringToCss( oSetDT.oScroll.sX );
1834
+ nScrollBody.style.overflow = "auto";
1835
+ }
1836
+
1837
+ if ( oSetDT.oScroll.sY !== "" )
1838
+ {
1839
+ nScrollBody.style.height = oSetDT.oApi._fnStringToCss( oSetDT.oScroll.sY );
1840
+ nScrollBody.style.overflow = "auto";
1841
+ }
1842
+ },
1843
+
1844
+
1845
+ /**
1846
+ * Resume the display of all TableTools hidden nodes
1847
+ * @method _fnPrintShowNodes
1848
+ * @returns void
1849
+ * @private
1850
+ */
1851
+ "_fnPrintShowNodes": function ( )
1852
+ {
1853
+ var anHidden = this.dom.print.hidden;
1854
+
1855
+ for ( var i=0, iLen=anHidden.length ; i<iLen ; i++ )
1856
+ {
1857
+ anHidden[i].node.style.display = anHidden[i].display;
1858
+ }
1859
+ anHidden.splice( 0, anHidden.length );
1860
+ },
1861
+
1862
+
1863
+ /**
1864
+ * Hide nodes which are not needed in order to display the table. Note that this function is
1865
+ * recursive
1866
+ * @method _fnPrintHideNodes
1867
+ * @param {Node} nNode Element which should be showing in a 'print' display
1868
+ * @returns void
1869
+ * @private
1870
+ */
1871
+ "_fnPrintHideNodes": function ( nNode )
1872
+ {
1873
+ var anHidden = this.dom.print.hidden;
1874
+
1875
+ var nParent = nNode.parentNode;
1876
+ var nChildren = nParent.childNodes;
1877
+ for ( var i=0, iLen=nChildren.length ; i<iLen ; i++ )
1878
+ {
1879
+ if ( nChildren[i] != nNode && nChildren[i].nodeType == 1 )
1880
+ {
1881
+ /* If our node is shown (don't want to show nodes which were previously hidden) */
1882
+ var sDisplay = $(nChildren[i]).css("display");
1883
+ if ( sDisplay != "none" )
1884
+ {
1885
+ /* Cache the node and it's previous state so we can restore it */
1886
+ anHidden.push( {
1887
+ "node": nChildren[i],
1888
+ "display": sDisplay
1889
+ } );
1890
+ nChildren[i].style.display = "none";
1891
+ }
1892
+ }
1893
+ }
1894
+
1895
+ if ( nParent.nodeName != "BODY" )
1896
+ {
1897
+ this._fnPrintHideNodes( nParent );
1898
+ }
1899
+ }
1900
+ };
1901
+
1902
+
1903
+
1904
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1905
+ * Static variables
1906
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1907
+
1908
+ /**
1909
+ * Store of all instances that have been created of TableTools, so one can look up other (when
1910
+ * there is need of a master)
1911
+ * @property _aInstances
1912
+ * @type Array
1913
+ * @default []
1914
+ * @private
1915
+ */
1916
+ TableTools._aInstances = [];
1917
+
1918
+
1919
+ /**
1920
+ * Store of all listeners and their callback functions
1921
+ * @property _aListeners
1922
+ * @type Array
1923
+ * @default []
1924
+ */
1925
+ TableTools._aListeners = [];
1926
+
1927
+
1928
+
1929
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1930
+ * Static methods
1931
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1932
+
1933
+ /**
1934
+ * Get an array of all the master instances
1935
+ * @method fnGetMasters
1936
+ * @returns {Array} List of master TableTools instances
1937
+ * @static
1938
+ */
1939
+ TableTools.fnGetMasters = function ()
1940
+ {
1941
+ var a = [];
1942
+ for ( var i=0, iLen=TableTools._aInstances.length ; i<iLen ; i++ )
1943
+ {
1944
+ if ( TableTools._aInstances[i].s.master )
1945
+ {
1946
+ a.push( TableTools._aInstances[i].s );
1947
+ }
1948
+ }
1949
+ return a;
1950
+ };
1951
+
1952
+ /**
1953
+ * Get the master instance for a table node (or id if a string is given)
1954
+ * @method fnGetInstance
1955
+ * @returns {Object} ID of table OR table node, for which we want the TableTools instance
1956
+ * @static
1957
+ */
1958
+ TableTools.fnGetInstance = function ( node )
1959
+ {
1960
+ if ( typeof node != 'object' )
1961
+ {
1962
+ node = document.getElementById(node);
1963
+ }
1964
+
1965
+ for ( var i=0, iLen=TableTools._aInstances.length ; i<iLen ; i++ )
1966
+ {
1967
+ if ( TableTools._aInstances[i].s.master && TableTools._aInstances[i].dom.table == node )
1968
+ {
1969
+ return TableTools._aInstances[i];
1970
+ }
1971
+ }
1972
+ return null;
1973
+ };
1974
+
1975
+
1976
+ /**
1977
+ * Add a listener for a specific event
1978
+ * @method _fnEventListen
1979
+ * @param {Object} that Scope of the listening function (i.e. 'this' in the caller)
1980
+ * @param {String} type Event type
1981
+ * @param {Function} fn Function
1982
+ * @returns void
1983
+ * @private
1984
+ * @static
1985
+ */
1986
+ TableTools._fnEventListen = function ( that, type, fn )
1987
+ {
1988
+ TableTools._aListeners.push( {
1989
+ "that": that,
1990
+ "type": type,
1991
+ "fn": fn
1992
+ } );
1993
+ };
1994
+
1995
+
1996
+ /**
1997
+ * An event has occured - look up every listener and fire it off. We check that the event we are
1998
+ * going to fire is attached to the same table (using the table node as reference) before firing
1999
+ * @method _fnEventDispatch
2000
+ * @param {Object} that Scope of the listening function (i.e. 'this' in the caller)
2001
+ * @param {String} type Event type
2002
+ * @param {Node} node Element that the event occured on (may be null)
2003
+ * @returns void
2004
+ * @private
2005
+ * @static
2006
+ */
2007
+ TableTools._fnEventDispatch = function ( that, type, node )
2008
+ {
2009
+ var listeners = TableTools._aListeners;
2010
+ for ( var i=0, iLen=listeners.length ; i<iLen ; i++ )
2011
+ {
2012
+ if ( that.dom.table == listeners[i].that.dom.table && listeners[i].type == type )
2013
+ {
2014
+ listeners[i].fn( node );
2015
+ }
2016
+ }
2017
+ };
2018
+
2019
+
2020
+
2021
+
2022
+
2023
+
2024
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2025
+ * Constants
2026
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2027
+
2028
+
2029
+ /**
2030
+ * @namespace Default button configurations
2031
+ */
2032
+ TableTools.BUTTONS = {
2033
+ "csv": {
2034
+ "sAction": "flash_save",
2035
+ "sCharSet": "utf8",
2036
+ "bBomInc": false,
2037
+ "sFileName": "*.csv",
2038
+ "sFieldBoundary": "'",
2039
+ "sFieldSeperator": ",",
2040
+ "sNewLine": "auto",
2041
+ "sTitle": "",
2042
+ "sToolTip": "",
2043
+ "sButtonClass": "DTTT_button_csv",
2044
+ "sButtonClassHover": "DTTT_button_csv_hover",
2045
+ "sButtonText": "CSV",
2046
+ "mColumns": "all", /* "all", "visible", "hidden" or array of column integers */
2047
+ "bHeader": true,
2048
+ "bFooter": true,
2049
+ "bSelectedOnly": false,
2050
+ "fnMouseover": null,
2051
+ "fnMouseout": null,
2052
+ "fnClick": function( nButton, oConfig, flash ) {
2053
+ this.fnSetText( flash, this.fnGetTableData(oConfig) );
2054
+ },
2055
+ "fnSelect": null,
2056
+ "fnComplete": null,
2057
+ "fnInit": null
2058
+ },
2059
+ "xls": {
2060
+ "sAction": "flash_save",
2061
+ "sCharSet": "utf16le",
2062
+ "bBomInc": true,
2063
+ "sFileName": "*.csv",
2064
+ "sFieldBoundary": "",
2065
+ "sFieldSeperator": "\t",
2066
+ "sNewLine": "auto",
2067
+ "sTitle": "",
2068
+ "sToolTip": "",
2069
+ "sButtonClass": "DTTT_button_xls",
2070
+ "sButtonClassHover": "DTTT_button_xls_hover",
2071
+ "sButtonText": "Excel",
2072
+ "mColumns": "all",
2073
+ "bHeader": true,
2074
+ "bFooter": true,
2075
+ "bSelectedOnly": false,
2076
+ "fnMouseover": null,
2077
+ "fnMouseout": null,
2078
+ "fnClick": function( nButton, oConfig, flash ) {
2079
+ this.fnSetText( flash, this.fnGetTableData(oConfig) );
2080
+ },
2081
+ "fnSelect": null,
2082
+ "fnComplete": null,
2083
+ "fnInit": null
2084
+ },
2085
+ "copy": {
2086
+ "sAction": "flash_copy",
2087
+ "sFieldBoundary": "",
2088
+ "sFieldSeperator": "\t",
2089
+ "sNewLine": "auto",
2090
+ "sToolTip": "",
2091
+ "sButtonClass": "DTTT_button_copy",
2092
+ "sButtonClassHover": "DTTT_button_copy_hover",
2093
+ "sButtonText": "Copy",
2094
+ "mColumns": "all",
2095
+ "bHeader": true,
2096
+ "bFooter": true,
2097
+ "bSelectedOnly": false,
2098
+ "fnMouseover": null,
2099
+ "fnMouseout": null,
2100
+ "fnClick": function( nButton, oConfig, flash ) {
2101
+ this.fnSetText( flash, this.fnGetTableData(oConfig) );
2102
+ },
2103
+ "fnSelect": null,
2104
+ "fnComplete": function(nButton, oConfig, flash, text) {
2105
+ var
2106
+ lines = text.split('\n').length,
2107
+ len = this.s.dt.nTFoot === null ? lines-1 : lines-2,
2108
+ plural = (len==1) ? "" : "s";
2109
+ alert( 'Copied '+len+' row'+plural+' to the clipboard' );
2110
+ },
2111
+ "fnInit": null
2112
+ },
2113
+ "pdf": {
2114
+ "sAction": "flash_pdf",
2115
+ "sFieldBoundary": "",
2116
+ "sFieldSeperator": "\t",
2117
+ "sNewLine": "\n",
2118
+ "sFileName": "*.pdf",
2119
+ "sToolTip": "",
2120
+ "sTitle": "",
2121
+ "sButtonClass": "DTTT_button_pdf",
2122
+ "sButtonClassHover": "DTTT_button_pdf_hover",
2123
+ "sButtonText": "PDF",
2124
+ "mColumns": "all",
2125
+ "bHeader": true,
2126
+ "bFooter": false,
2127
+ "bSelectedOnly": false,
2128
+ "fnMouseover": null,
2129
+ "fnMouseout": null,
2130
+ "sPdfOrientation": "portrait",
2131
+ "sPdfSize": "A4",
2132
+ "sPdfMessage": "",
2133
+ "fnClick": function( nButton, oConfig, flash ) {
2134
+ this.fnSetText( flash,
2135
+ "title:"+ this.fnGetTitle(oConfig) +"\n"+
2136
+ "message:"+ oConfig.sPdfMessage +"\n"+
2137
+ "colWidth:"+ this.fnCalcColRatios(oConfig) +"\n"+
2138
+ "orientation:"+ oConfig.sPdfOrientation +"\n"+
2139
+ "size:"+ oConfig.sPdfSize +"\n"+
2140
+ "--/TableToolsOpts--\n" +
2141
+ this.fnGetTableData(oConfig)
2142
+ );
2143
+ },
2144
+ "fnSelect": null,
2145
+ "fnComplete": null,
2146
+ "fnInit": null
2147
+ },
2148
+ "print": {
2149
+ "sAction": "print",
2150
+ "sInfo": "<h6>Print view</h6><p>Please use your browser's print function to "+
2151
+ "print this table. Press escape when finished.",
2152
+ "sMessage": "",
2153
+ "bShowAll": true,
2154
+ "sToolTip": "View print view",
2155
+ "sButtonClass": "DTTT_button_print",
2156
+ "sButtonClassHover": "DTTT_button_print_hover",
2157
+ "sButtonText": "Print",
2158
+ "fnMouseover": null,
2159
+ "fnMouseout": null,
2160
+ "fnClick": null,
2161
+ "fnSelect": null,
2162
+ "fnComplete": null,
2163
+ "fnInit": null
2164
+ },
2165
+ "text": {
2166
+ "sAction": "text",
2167
+ "sToolTip": "",
2168
+ "sButtonClass": "DTTT_button_text",
2169
+ "sButtonClassHover": "DTTT_button_text_hover",
2170
+ "sButtonText": "Text button",
2171
+ "mColumns": "all",
2172
+ "bHeader": true,
2173
+ "bFooter": true,
2174
+ "bSelectedOnly": false,
2175
+ "fnMouseover": null,
2176
+ "fnMouseout": null,
2177
+ "fnClick": null,
2178
+ "fnSelect": null,
2179
+ "fnComplete": null,
2180
+ "fnInit": null
2181
+ },
2182
+ "select": {
2183
+ "sAction": "text",
2184
+ "sToolTip": "",
2185
+ "sButtonClass": "DTTT_button_text",
2186
+ "sButtonClassHover": "DTTT_button_text_hover",
2187
+ "sButtonText": "Select button",
2188
+ "mColumns": "all",
2189
+ "bHeader": true,
2190
+ "bFooter": true,
2191
+ "fnMouseover": null,
2192
+ "fnMouseout": null,
2193
+ "fnClick": null,
2194
+ "fnSelect": function( nButton, oConfig ) {
2195
+ if ( this.fnGetSelected().length !== 0 ) {
2196
+ $(nButton).removeClass('DTTT_disabled');
2197
+ } else {
2198
+ $(nButton).addClass('DTTT_disabled');
2199
+ }
2200
+ },
2201
+ "fnComplete": null,
2202
+ "fnInit": function( nButton, oConfig ) {
2203
+ $(nButton).addClass('DTTT_disabled');
2204
+ }
2205
+ },
2206
+ "select_single": {
2207
+ "sAction": "text",
2208
+ "sToolTip": "",
2209
+ "sButtonClass": "DTTT_button_text",
2210
+ "sButtonClassHover": "DTTT_button_text_hover",
2211
+ "sButtonText": "Select button",
2212
+ "mColumns": "all",
2213
+ "bHeader": true,
2214
+ "bFooter": true,
2215
+ "fnMouseover": null,
2216
+ "fnMouseout": null,
2217
+ "fnClick": null,
2218
+ "fnSelect": function( nButton, oConfig ) {
2219
+ var iSelected = this.fnGetSelected().length;
2220
+ if ( iSelected == 1 ) {
2221
+ $(nButton).removeClass('DTTT_disabled');
2222
+ } else {
2223
+ $(nButton).addClass('DTTT_disabled');
2224
+ }
2225
+ },
2226
+ "fnComplete": null,
2227
+ "fnInit": function( nButton, oConfig ) {
2228
+ $(nButton).addClass('DTTT_disabled');
2229
+ }
2230
+ },
2231
+ "select_all": {
2232
+ "sAction": "text",
2233
+ "sToolTip": "",
2234
+ "sButtonClass": "DTTT_button_text",
2235
+ "sButtonClassHover": "DTTT_button_text_hover",
2236
+ "sButtonText": "Select all",
2237
+ "mColumns": "all",
2238
+ "bHeader": true,
2239
+ "bFooter": true,
2240
+ "fnMouseover": null,
2241
+ "fnMouseout": null,
2242
+ "fnClick": function( nButton, oConfig ) {
2243
+ this.fnSelectAll();
2244
+ },
2245
+ "fnSelect": function( nButton, oConfig ) {
2246
+ if ( this.fnGetSelected().length == this.s.dt.fnRecordsDisplay() ) {
2247
+ $(nButton).addClass('DTTT_disabled');
2248
+ } else {
2249
+ $(nButton).removeClass('DTTT_disabled');
2250
+ }
2251
+ },
2252
+ "fnComplete": null,
2253
+ "fnInit": null
2254
+ },
2255
+ "select_none": {
2256
+ "sAction": "text",
2257
+ "sToolTip": "",
2258
+ "sButtonClass": "DTTT_button_text",
2259
+ "sButtonClassHover": "DTTT_button_text_hover",
2260
+ "sButtonText": "Deselect all",
2261
+ "mColumns": "all",
2262
+ "bHeader": true,
2263
+ "bFooter": true,
2264
+ "fnMouseover": null,
2265
+ "fnMouseout": null,
2266
+ "fnClick": function( nButton, oConfig ) {
2267
+ this.fnSelectNone();
2268
+ },
2269
+ "fnSelect": function( nButton, oConfig ) {
2270
+ if ( this.fnGetSelected().length !== 0 ) {
2271
+ $(nButton).removeClass('DTTT_disabled');
2272
+ } else {
2273
+ $(nButton).addClass('DTTT_disabled');
2274
+ }
2275
+ },
2276
+ "fnComplete": null,
2277
+ "fnInit": function( nButton, oConfig ) {
2278
+ $(nButton).addClass('DTTT_disabled');
2279
+ }
2280
+ },
2281
+ "ajax": {
2282
+ "sAction": "text",
2283
+ "sFieldBoundary": "",
2284
+ "sFieldSeperator": "\t",
2285
+ "sNewLine": "\n",
2286
+ "sAjaxUrl": "/xhr.php",
2287
+ "sToolTip": "",
2288
+ "sButtonClass": "DTTT_button_text",
2289
+ "sButtonClassHover": "DTTT_button_text_hover",
2290
+ "sButtonText": "Ajax button",
2291
+ "mColumns": "all",
2292
+ "bHeader": true,
2293
+ "bFooter": true,
2294
+ "bSelectedOnly": false,
2295
+ "fnMouseover": null,
2296
+ "fnMouseout": null,
2297
+ "fnClick": function( nButton, oConfig ) {
2298
+ var sData = this.fnGetTableData(oConfig);
2299
+ $.ajax( {
2300
+ "url": oConfig.sAjaxUrl,
2301
+ "data": [
2302
+ { "name": "tableData", "value": sData }
2303
+ ],
2304
+ "success": oConfig.fnAjaxComplete,
2305
+ "dataType": "json",
2306
+ "type": "POST",
2307
+ "cache": false,
2308
+ "error": function () {
2309
+ alert( "Error detected when sending table data to server" );
2310
+ }
2311
+ } );
2312
+ },
2313
+ "fnSelect": null,
2314
+ "fnComplete": null,
2315
+ "fnInit": null,
2316
+ "fnAjaxComplete": function( json ) {
2317
+ alert( 'Ajax complete' );
2318
+ }
2319
+ },
2320
+ "collection": {
2321
+ "sAction": "collection",
2322
+ "sToolTip": "",
2323
+ "sButtonClass": "DTTT_button_collection",
2324
+ "sButtonClassHover": "DTTT_button_collection_hover",
2325
+ "sButtonText": "Collection",
2326
+ "fnMouseover": null,
2327
+ "fnMouseout": null,
2328
+ "fnClick": function( nButton, oConfig ) {
2329
+ this._fnCollectionShow(nButton, oConfig);
2330
+ },
2331
+ "fnSelect": null,
2332
+ "fnComplete": null,
2333
+ "fnInit": null
2334
+ }
2335
+ };
2336
+ /*
2337
+ * on* callback parameters:
2338
+ * 1. node - button element
2339
+ * 2. object - configuration object for this button
2340
+ * 3. object - ZeroClipboard reference (flash button only)
2341
+ * 4. string - Returned string from Flash (flash button only - and only on 'complete')
2342
+ */
2343
+
2344
+
2345
+ /**
2346
+ * @namespace TableTools default settings for initialisation
2347
+ */
2348
+ TableTools.DEFAULTS = {
2349
+ "sSwfPath": "media/swf/copy_cvs_xls_pdf.swf",
2350
+ "sRowSelect": "none",
2351
+ "sSelectedClass": "DTTT_selected",
2352
+ "fnPreRowSelect": null,
2353
+ "fnRowSelected": null,
2354
+ "fnRowDeselected": null,
2355
+ "aButtons": [ "copy", "csv", "xls", "pdf", "print" ]
2356
+ };
2357
+
2358
+
2359
+ /**
2360
+ * Name of this class
2361
+ * @constant CLASS
2362
+ * @type String
2363
+ * @default TableTools
2364
+ */
2365
+ TableTools.prototype.CLASS = "TableTools";
2366
+
2367
+
2368
+ /**
2369
+ * TableTools version
2370
+ * @constant VERSION
2371
+ * @type String
2372
+ * @default 2.0.1
2373
+ */
2374
+ TableTools.VERSION = "2.0.1";
2375
+ TableTools.prototype.VERSION = TableTools.VERSION;
2376
+
2377
+
2378
+
2379
+
2380
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2381
+ * Initialisation
2382
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2383
+
2384
+ /*
2385
+ * Register a new feature with DataTables
2386
+ */
2387
+ if ( typeof $.fn.dataTable == "function" &&
2388
+ typeof $.fn.dataTableExt.fnVersionCheck == "function" &&
2389
+ $.fn.dataTableExt.fnVersionCheck('1.7.0') )
2390
+ {
2391
+ $.fn.dataTableExt.aoFeatures.push( {
2392
+ "fnInit": function( oDTSettings ) {
2393
+ var oOpts = typeof oDTSettings.oInit.oTableTools != 'undefined' ?
2394
+ oDTSettings.oInit.oTableTools : {};
2395
+
2396
+ var oTT = new TableTools( oDTSettings.oInstance, oOpts );
2397
+ TableTools._aInstances.push( oTT );
2398
+
2399
+ return oTT.dom.container;
2400
+ },
2401
+ "cFeature": "T",
2402
+ "sFeature": "TableTools"
2403
+ } );
2404
+ }
2405
+ else
2406
+ {
2407
+ alert( "Warning: TableTools 2 requires DataTables 1.7 or greater - www.datatables.net/download");
2408
+ }
2409
+
2410
+ })(jQuery, window, document);