datatable 0.1.0alpha2

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