jquery-datatables-rails 1.12.2 → 2.1.10.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/dataTables/extras/filler.png +0 -0
  3. data/app/assets/images/dataTables/extras/loading-background.png +0 -0
  4. data/app/assets/images/dataTables/sort_asc_disabled.png +0 -0
  5. data/app/assets/javascripts/dataTables/extras/dataTables.autoFill.js +851 -0
  6. data/app/assets/javascripts/dataTables/extras/{ColReorder.js → dataTables.colReorder.js} +558 -223
  7. data/app/assets/javascripts/dataTables/extras/dataTables.colVis.js +1096 -0
  8. data/app/assets/javascripts/dataTables/extras/{FixedColumns.js → dataTables.fixedColumns.js} +163 -113
  9. data/app/assets/javascripts/dataTables/extras/{FixedHeader.js → dataTables.fixedHeader.js} +306 -219
  10. data/app/assets/javascripts/dataTables/extras/{KeyTable.js → dataTables.keyTable.js} +155 -95
  11. data/app/assets/javascripts/dataTables/extras/{Scroller.js → dataTables.scroller.js} +469 -188
  12. data/app/assets/javascripts/dataTables/extras/{TableTools.js → dataTables.tableTools.js} +949 -341
  13. data/app/assets/javascripts/dataTables/jquery.dataTables.foundation.js +4 -4
  14. data/app/assets/javascripts/dataTables/jquery.dataTables.js +10711 -8427
  15. data/app/assets/media/dataTables/extras/swf/copy_csv_xls.swf +0 -0
  16. data/app/assets/media/dataTables/extras/swf/copy_csv_xls_pdf.swf +0 -0
  17. data/app/assets/stylesheets/dataTables/extras/dataTables.autoFill.css.scss +24 -0
  18. data/app/assets/stylesheets/dataTables/extras/dataTables.colReorder.css.scss +14 -0
  19. data/app/assets/stylesheets/dataTables/extras/dataTables.colVis.css.scss +184 -0
  20. data/app/assets/stylesheets/dataTables/extras/dataTables.colvis.jqueryui.css.scss +23 -0
  21. data/app/assets/stylesheets/dataTables/extras/dataTables.fixedColumns.css.scss +24 -0
  22. data/app/assets/stylesheets/dataTables/extras/dataTables.fixedHeader.css.scss +7 -0
  23. data/app/assets/stylesheets/dataTables/extras/dataTables.keyTable.css.scss +7 -0
  24. data/app/assets/stylesheets/dataTables/extras/dataTables.scroller.css.scss +44 -0
  25. data/app/assets/stylesheets/dataTables/extras/{TableTools.css.erb → dataTables.tableTools.css.scss} +30 -15
  26. data/app/assets/stylesheets/dataTables/jquery.dataTables.bootstrap.css.scss +6 -0
  27. data/app/assets/stylesheets/dataTables/jquery.dataTables.css.scss +363 -184
  28. data/app/assets/stylesheets/dataTables/src/jquery.dataTables_themeroller.css +307 -220
  29. data/lib/jquery/datatables/rails/version.rb +1 -1
  30. metadata +42 -22
  31. data/app/assets/javascripts/dataTables/extras/AutoFill.js +0 -820
  32. data/app/assets/javascripts/dataTables/extras/ColVis.js +0 -1005
  33. data/app/assets/javascripts/dataTables/extras/TableTools.min.js +0 -77
  34. data/app/assets/stylesheets/dataTables/extras/ColReorder.css.erb +0 -21
  35. data/app/assets/stylesheets/dataTables/extras/ColVis.css +0 -76
  36. data/app/assets/stylesheets/dataTables/extras/ColVisAlt.css.erb +0 -104
@@ -1,33 +1,457 @@
1
- /*
2
- * File: TableTools.js
3
- * Version: 2.1.5
4
- * Description: Tools and buttons for DataTables
5
- * Author: Allan Jardine (www.sprymedia.co.uk)
6
- * Language: Javascript
7
- * License: GPL v2 or BSD 3 point style
8
- * Project: DataTables
9
- *
10
- * Copyright 2009-2013 Allan Jardine, all rights reserved.
1
+ /*! TableTools 2.2.1
2
+ * 2009-2014 SpryMedia Ltd - datatables.net/license
3
+ *
4
+ * ZeroClipboard 1.0.4
5
+ * Author: Joseph Huckaby - MIT licensed
6
+ */
7
+
8
+ /**
9
+ * @summary TableTools
10
+ * @description Tools and buttons for DataTables
11
+ * @version 2.2.1
12
+ * @file dataTables.tableTools.js
13
+ * @author SpryMedia Ltd (www.sprymedia.co.uk)
14
+ * @contact www.sprymedia.co.uk/contact
15
+ * @copyright Copyright 2009-2014 SpryMedia Ltd.
16
+ *
17
+ * This source file is free software, available under the following license:
18
+ * MIT license - http://datatables.net/license/mit
11
19
  *
12
- * This source file is free software, under either the GPL v2 license or a
13
- * BSD style license, available at:
14
- * http://datatables.net/license_gpl2
15
- * http://datatables.net/license_bsd
20
+ * This source file is distributed in the hope that it will be useful, but
21
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
23
+ *
24
+ * For details please refer to: http://www.datatables.net
16
25
  */
17
26
 
18
- /* Global scope for TableTools */
27
+
28
+ /* Global scope for TableTools for backwards compatibility.
29
+ * Will be removed in 2.3
30
+ */
19
31
  var TableTools;
20
32
 
33
+ (function(window, document, undefined) {
34
+
35
+
36
+ var factory = function( $, DataTable ) {
37
+ "use strict";
38
+
39
+
40
+ //include ZeroClipboard.js
41
+ /* ZeroClipboard 1.0.4
42
+ * Author: Joseph Huckaby
43
+ */
44
+
45
+ var ZeroClipboard_TableTools = {
46
+
47
+ version: "1.0.4-TableTools2",
48
+ clients: {}, // registered upload clients on page, indexed by id
49
+ moviePath: '', // URL to movie
50
+ nextId: 1, // ID of next movie
51
+
52
+ $: function(thingy) {
53
+ // simple DOM lookup utility function
54
+ if (typeof(thingy) == 'string') {
55
+ thingy = document.getElementById(thingy);
56
+ }
57
+ if (!thingy.addClass) {
58
+ // extend element with a few useful methods
59
+ thingy.hide = function() { this.style.display = 'none'; };
60
+ thingy.show = function() { this.style.display = ''; };
61
+ thingy.addClass = function(name) { this.removeClass(name); this.className += ' ' + name; };
62
+ thingy.removeClass = function(name) {
63
+ this.className = this.className.replace( new RegExp("\\s*" + name + "\\s*"), " ").replace(/^\s+/, '').replace(/\s+$/, '');
64
+ };
65
+ thingy.hasClass = function(name) {
66
+ return !!this.className.match( new RegExp("\\s*" + name + "\\s*") );
67
+ };
68
+ }
69
+ return thingy;
70
+ },
71
+
72
+ setMoviePath: function(path) {
73
+ // set path to ZeroClipboard.swf
74
+ this.moviePath = path;
75
+ },
76
+
77
+ dispatch: function(id, eventName, args) {
78
+ // receive event from flash movie, send to client
79
+ var client = this.clients[id];
80
+ if (client) {
81
+ client.receiveEvent(eventName, args);
82
+ }
83
+ },
84
+
85
+ register: function(id, client) {
86
+ // register new client to receive events
87
+ this.clients[id] = client;
88
+ },
89
+
90
+ getDOMObjectPosition: function(obj) {
91
+ // get absolute coordinates for dom element
92
+ var info = {
93
+ left: 0,
94
+ top: 0,
95
+ width: obj.width ? obj.width : obj.offsetWidth,
96
+ height: obj.height ? obj.height : obj.offsetHeight
97
+ };
98
+
99
+ if ( obj.style.width !== "" ) {
100
+ info.width = obj.style.width.replace("px","");
101
+ }
102
+
103
+ if ( obj.style.height !== "" ) {
104
+ info.height = obj.style.height.replace("px","");
105
+ }
106
+
107
+ while (obj) {
108
+ info.left += obj.offsetLeft;
109
+ info.top += obj.offsetTop;
110
+ obj = obj.offsetParent;
111
+ }
112
+
113
+ return info;
114
+ },
115
+
116
+ Client: function(elem) {
117
+ // constructor for new simple upload client
118
+ this.handlers = {};
119
+
120
+ // unique ID
121
+ this.id = ZeroClipboard_TableTools.nextId++;
122
+ this.movieId = 'ZeroClipboard_TableToolsMovie_' + this.id;
123
+
124
+ // register client with singleton to receive flash events
125
+ ZeroClipboard_TableTools.register(this.id, this);
126
+
127
+ // create movie
128
+ if (elem) {
129
+ this.glue(elem);
130
+ }
131
+ }
132
+ };
133
+
134
+ ZeroClipboard_TableTools.Client.prototype = {
135
+
136
+ id: 0, // unique ID for us
137
+ ready: false, // whether movie is ready to receive events or not
138
+ movie: null, // reference to movie object
139
+ clipText: '', // text to copy to clipboard
140
+ fileName: '', // default file save name
141
+ action: 'copy', // action to perform
142
+ handCursorEnabled: true, // whether to show hand cursor, or default pointer cursor
143
+ cssEffects: true, // enable CSS mouse effects on dom container
144
+ handlers: null, // user event handlers
145
+ sized: false,
146
+
147
+ glue: function(elem, title) {
148
+ // glue to DOM element
149
+ // elem can be ID or actual DOM element object
150
+ this.domElement = ZeroClipboard_TableTools.$(elem);
151
+
152
+ // float just above object, or zIndex 99 if dom element isn't set
153
+ var zIndex = 99;
154
+ if (this.domElement.style.zIndex) {
155
+ zIndex = parseInt(this.domElement.style.zIndex, 10) + 1;
156
+ }
157
+
158
+ // find X/Y position of domElement
159
+ var box = ZeroClipboard_TableTools.getDOMObjectPosition(this.domElement);
160
+
161
+ // create floating DIV above element
162
+ this.div = document.createElement('div');
163
+ var style = this.div.style;
164
+ style.position = 'absolute';
165
+ style.left = '0px';
166
+ style.top = '0px';
167
+ style.width = (box.width) + 'px';
168
+ style.height = box.height + 'px';
169
+ style.zIndex = zIndex;
170
+
171
+ if ( typeof title != "undefined" && title !== "" ) {
172
+ this.div.title = title;
173
+ }
174
+ if ( box.width !== 0 && box.height !== 0 ) {
175
+ this.sized = true;
176
+ }
177
+
178
+ // style.backgroundColor = '#f00'; // debug
179
+ if ( this.domElement ) {
180
+ this.domElement.appendChild(this.div);
181
+ this.div.innerHTML = this.getHTML( box.width, box.height ).replace(/&/g, '&');
182
+ }
183
+ },
184
+
185
+ positionElement: function() {
186
+ var box = ZeroClipboard_TableTools.getDOMObjectPosition(this.domElement);
187
+ var style = this.div.style;
188
+
189
+ style.position = 'absolute';
190
+ //style.left = (this.domElement.offsetLeft)+'px';
191
+ //style.top = this.domElement.offsetTop+'px';
192
+ style.width = box.width + 'px';
193
+ style.height = box.height + 'px';
194
+
195
+ if ( box.width !== 0 && box.height !== 0 ) {
196
+ this.sized = true;
197
+ } else {
198
+ return;
199
+ }
200
+
201
+ var flash = this.div.childNodes[0];
202
+ flash.width = box.width;
203
+ flash.height = box.height;
204
+ },
205
+
206
+ getHTML: function(width, height) {
207
+ // return HTML for movie
208
+ var html = '';
209
+ var flashvars = 'id=' + this.id +
210
+ '&width=' + width +
211
+ '&height=' + height;
212
+
213
+ if (navigator.userAgent.match(/MSIE/)) {
214
+ // IE gets an OBJECT tag
215
+ var protocol = location.href.match(/^https/i) ? 'https://' : 'http://';
216
+ html += '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="'+protocol+'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0" width="'+width+'" height="'+height+'" id="'+this.movieId+'" align="middle"><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="false" /><param name="movie" value="'+ZeroClipboard_TableTools.moviePath+'" /><param name="loop" value="false" /><param name="menu" value="false" /><param name="quality" value="best" /><param name="bgcolor" value="#ffffff" /><param name="flashvars" value="'+flashvars+'"/><param name="wmode" value="transparent"/></object>';
217
+ }
218
+ else {
219
+ // all other browsers get an EMBED tag
220
+ html += '<embed id="'+this.movieId+'" src="'+ZeroClipboard_TableTools.moviePath+'" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="'+width+'" height="'+height+'" name="'+this.movieId+'" align="middle" allowScriptAccess="always" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="'+flashvars+'" wmode="transparent" />';
221
+ }
222
+ return html;
223
+ },
224
+
225
+ hide: function() {
226
+ // temporarily hide floater offscreen
227
+ if (this.div) {
228
+ this.div.style.left = '-2000px';
229
+ }
230
+ },
231
+
232
+ show: function() {
233
+ // show ourselves after a call to hide()
234
+ this.reposition();
235
+ },
236
+
237
+ destroy: function() {
238
+ // destroy control and floater
239
+ if (this.domElement && this.div) {
240
+ this.hide();
241
+ this.div.innerHTML = '';
242
+
243
+ var body = document.getElementsByTagName('body')[0];
244
+ try { body.removeChild( this.div ); } catch(e) {}
245
+
246
+ this.domElement = null;
247
+ this.div = null;
248
+ }
249
+ },
250
+
251
+ reposition: function(elem) {
252
+ // reposition our floating div, optionally to new container
253
+ // warning: container CANNOT change size, only position
254
+ if (elem) {
255
+ this.domElement = ZeroClipboard_TableTools.$(elem);
256
+ if (!this.domElement) {
257
+ this.hide();
258
+ }
259
+ }
260
+
261
+ if (this.domElement && this.div) {
262
+ var box = ZeroClipboard_TableTools.getDOMObjectPosition(this.domElement);
263
+ var style = this.div.style;
264
+ style.left = '' + box.left + 'px';
265
+ style.top = '' + box.top + 'px';
266
+ }
267
+ },
268
+
269
+ clearText: function() {
270
+ // clear the text to be copy / saved
271
+ this.clipText = '';
272
+ if (this.ready) {
273
+ this.movie.clearText();
274
+ }
275
+ },
276
+
277
+ appendText: function(newText) {
278
+ // append text to that which is to be copied / saved
279
+ this.clipText += newText;
280
+ if (this.ready) { this.movie.appendText(newText) ;}
281
+ },
282
+
283
+ setText: function(newText) {
284
+ // set text to be copied to be copied / saved
285
+ this.clipText = newText;
286
+ if (this.ready) { this.movie.setText(newText) ;}
287
+ },
288
+
289
+ setCharSet: function(charSet) {
290
+ // set the character set (UTF16LE or UTF8)
291
+ this.charSet = charSet;
292
+ if (this.ready) { this.movie.setCharSet(charSet) ;}
293
+ },
294
+
295
+ setBomInc: function(bomInc) {
296
+ // set if the BOM should be included or not
297
+ this.incBom = bomInc;
298
+ if (this.ready) { this.movie.setBomInc(bomInc) ;}
299
+ },
300
+
301
+ setFileName: function(newText) {
302
+ // set the file name
303
+ this.fileName = newText;
304
+ if (this.ready) {
305
+ this.movie.setFileName(newText);
306
+ }
307
+ },
308
+
309
+ setAction: function(newText) {
310
+ // set action (save or copy)
311
+ this.action = newText;
312
+ if (this.ready) {
313
+ this.movie.setAction(newText);
314
+ }
315
+ },
316
+
317
+ addEventListener: function(eventName, func) {
318
+ // add user event listener for event
319
+ // event types: load, queueStart, fileStart, fileComplete, queueComplete, progress, error, cancel
320
+ eventName = eventName.toString().toLowerCase().replace(/^on/, '');
321
+ if (!this.handlers[eventName]) {
322
+ this.handlers[eventName] = [];
323
+ }
324
+ this.handlers[eventName].push(func);
325
+ },
326
+
327
+ setHandCursor: function(enabled) {
328
+ // enable hand cursor (true), or default arrow cursor (false)
329
+ this.handCursorEnabled = enabled;
330
+ if (this.ready) {
331
+ this.movie.setHandCursor(enabled);
332
+ }
333
+ },
334
+
335
+ setCSSEffects: function(enabled) {
336
+ // enable or disable CSS effects on DOM container
337
+ this.cssEffects = !!enabled;
338
+ },
339
+
340
+ receiveEvent: function(eventName, args) {
341
+ var self;
342
+
343
+ // receive event from flash
344
+ eventName = eventName.toString().toLowerCase().replace(/^on/, '');
345
+
346
+ // special behavior for certain events
347
+ switch (eventName) {
348
+ case 'load':
349
+ // movie claims it is ready, but in IE this isn't always the case...
350
+ // bug fix: Cannot extend EMBED DOM elements in Firefox, must use traditional function
351
+ this.movie = document.getElementById(this.movieId);
352
+ if (!this.movie) {
353
+ self = this;
354
+ setTimeout( function() { self.receiveEvent('load', null); }, 1 );
355
+ return;
356
+ }
357
+
358
+ // firefox on pc needs a "kick" in order to set these in certain cases
359
+ if (!this.ready && navigator.userAgent.match(/Firefox/) && navigator.userAgent.match(/Windows/)) {
360
+ self = this;
361
+ setTimeout( function() { self.receiveEvent('load', null); }, 100 );
362
+ this.ready = true;
363
+ return;
364
+ }
365
+
366
+ this.ready = true;
367
+ this.movie.clearText();
368
+ this.movie.appendText( this.clipText );
369
+ this.movie.setFileName( this.fileName );
370
+ this.movie.setAction( this.action );
371
+ this.movie.setCharSet( this.charSet );
372
+ this.movie.setBomInc( this.incBom );
373
+ this.movie.setHandCursor( this.handCursorEnabled );
374
+ break;
375
+
376
+ case 'mouseover':
377
+ if (this.domElement && this.cssEffects) {
378
+ //this.domElement.addClass('hover');
379
+ if (this.recoverActive) {
380
+ this.domElement.addClass('active');
381
+ }
382
+ }
383
+ break;
384
+
385
+ case 'mouseout':
386
+ if (this.domElement && this.cssEffects) {
387
+ this.recoverActive = false;
388
+ if (this.domElement.hasClass('active')) {
389
+ this.domElement.removeClass('active');
390
+ this.recoverActive = true;
391
+ }
392
+ //this.domElement.removeClass('hover');
393
+ }
394
+ break;
395
+
396
+ case 'mousedown':
397
+ if (this.domElement && this.cssEffects) {
398
+ this.domElement.addClass('active');
399
+ }
400
+ break;
401
+
402
+ case 'mouseup':
403
+ if (this.domElement && this.cssEffects) {
404
+ this.domElement.removeClass('active');
405
+ this.recoverActive = false;
406
+ }
407
+ break;
408
+ } // switch eventName
409
+
410
+ if (this.handlers[eventName]) {
411
+ for (var idx = 0, len = this.handlers[eventName].length; idx < len; idx++) {
412
+ var func = this.handlers[eventName][idx];
413
+
414
+ if (typeof(func) == 'function') {
415
+ // actual function reference
416
+ func(this, args);
417
+ }
418
+ else if ((typeof(func) == 'object') && (func.length == 2)) {
419
+ // PHP style object + method, i.e. [myObject, 'myMethod']
420
+ func[0][ func[1] ](this, args);
421
+ }
422
+ else if (typeof(func) == 'string') {
423
+ // name of function
424
+ window[func](this, args);
425
+ }
426
+ } // foreach event handler defined
427
+ } // user defined handler for event
428
+ }
429
+
430
+ };
431
+
432
+ // For the Flash binding to work, ZeroClipboard_TableTools must be on the global
433
+ // object list
434
+ window.ZeroClipboard_TableTools = ZeroClipboard_TableTools;
435
+ //include TableTools.js
436
+ /* TableTools
437
+ * 2009-2014 SpryMedia Ltd - datatables.net/license
438
+ */
439
+
440
+ /*globals TableTools,ZeroClipboard_TableTools*/
441
+
442
+
21
443
  (function($, window, document) {
22
444
 
23
445
  /**
24
446
  * TableTools provides flexible buttons and other tools for a DataTables enhanced table
25
447
  * @class TableTools
26
448
  * @constructor
27
- * @param {Object} oDT DataTables instance
449
+ * @param {Object} oDT DataTables instance. When using DataTables 1.10 this can
450
+ * also be a jQuery collection, jQuery selector, table node, DataTables API
451
+ * instance or DataTables settings object.
28
452
  * @param {Object} oOpts TableTools options
29
453
  * @param {String} oOpts.sSwfPath ZeroClipboard SWF path
30
- * @param {String} oOpts.sRowSelect Row selection options - 'none', 'single' or 'multi'
454
+ * @param {String} oOpts.sRowSelect Row selection options - 'none', 'single', 'multi' or 'os'
31
455
  * @param {Function} oOpts.fnPreRowSelect Callback function just prior to row selection
32
456
  * @param {Function} oOpts.fnRowSelected Callback function just after row selection
33
457
  * @param {Function} oOpts.fnRowDeselected Callback function when row is deselected
@@ -40,12 +464,18 @@ TableTools = function( oDT, oOpts )
40
464
  {
41
465
  alert( "Warning: TableTools must be initialised with the keyword 'new'" );
42
466
  }
43
-
44
-
467
+
468
+ // In 1.10 we can use the API to get the settings object from a number of
469
+ // sources
470
+ var dtSettings = $.fn.dataTable.Api ?
471
+ new $.fn.dataTable.Api( oDT ).settings()[0] :
472
+ oDT.fnSettings();
473
+
474
+
45
475
  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
46
476
  * Public class variables
47
477
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
48
-
478
+
49
479
  /**
50
480
  * @namespace Settings object which contains customisable information for TableTools instance
51
481
  */
@@ -57,15 +487,15 @@ TableTools = function( oDT, oOpts )
57
487
  * @default this
58
488
  */
59
489
  "that": this,
60
-
490
+
61
491
  /**
62
492
  * DataTables settings objects
63
493
  * @property dt
64
494
  * @type object
65
495
  * @default <i>From the oDT init option</i>
66
496
  */
67
- "dt": oDT.fnSettings(),
68
-
497
+ "dt": dtSettings,
498
+
69
499
  /**
70
500
  * @namespace Print specific information
71
501
  */
@@ -75,42 +505,42 @@ TableTools = function( oDT, oOpts )
75
505
  * @property saveStart
76
506
  * @type int
77
507
  * @default -1
78
- */
79
- "saveStart": -1,
80
-
508
+ */
509
+ "saveStart": -1,
510
+
81
511
  /**
82
512
  * DataTables draw 'length' point before the printing display was shown
83
513
  * @property saveLength
84
514
  * @type int
85
515
  * @default -1
86
- */
87
- "saveLength": -1,
88
-
516
+ */
517
+ "saveLength": -1,
518
+
89
519
  /**
90
520
  * Page scrolling point before the printing display was shown so it can be restored
91
521
  * @property saveScroll
92
522
  * @type int
93
523
  * @default -1
94
- */
95
- "saveScroll": -1,
96
-
524
+ */
525
+ "saveScroll": -1,
526
+
97
527
  /**
98
528
  * Wrapped function to end the print display (to maintain scope)
99
529
  * @property funcEnd
100
- * @type Function
530
+ * @type Function
101
531
  * @default function () {}
102
- */
103
- "funcEnd": function () {}
104
- },
105
-
532
+ */
533
+ "funcEnd": function () {}
534
+ },
535
+
106
536
  /**
107
537
  * A unique ID is assigned to each button in each instance
108
538
  * @property buttonCounter
109
539
  * @type int
110
540
  * @default 0
111
541
  */
112
- "buttonCounter": 0,
113
-
542
+ "buttonCounter": 0,
543
+
114
544
  /**
115
545
  * @namespace Select rows specific information
116
546
  */
@@ -122,7 +552,7 @@ TableTools = function( oDT, oOpts )
122
552
  * @default ""
123
553
  */
124
554
  "type": "",
125
-
555
+
126
556
  /**
127
557
  * Array of nodes which are currently selected
128
558
  * @property selected
@@ -130,7 +560,7 @@ TableTools = function( oDT, oOpts )
130
560
  * @default []
131
561
  */
132
562
  "selected": [],
133
-
563
+
134
564
  /**
135
565
  * Function to run before the selection can take place. Will cancel the select if the
136
566
  * function returns false
@@ -139,7 +569,7 @@ TableTools = function( oDT, oOpts )
139
569
  * @default null
140
570
  */
141
571
  "preRowSelect": null,
142
-
572
+
143
573
  /**
144
574
  * Function to run when a row is selected
145
575
  * @property postSelected
@@ -147,7 +577,7 @@ TableTools = function( oDT, oOpts )
147
577
  * @default null
148
578
  */
149
579
  "postSelected": null,
150
-
580
+
151
581
  /**
152
582
  * Function to run when a row is deselected
153
583
  * @property postDeselected
@@ -155,7 +585,7 @@ TableTools = function( oDT, oOpts )
155
585
  * @default null
156
586
  */
157
587
  "postDeselected": null,
158
-
588
+
159
589
  /**
160
590
  * Indicate if all rows are selected (needed for server-side processing)
161
591
  * @property all
@@ -163,7 +593,7 @@ TableTools = function( oDT, oOpts )
163
593
  * @default false
164
594
  */
165
595
  "all": false,
166
-
596
+
167
597
  /**
168
598
  * Class name to add to selected TR nodes
169
599
  * @property selectedClass
@@ -172,7 +602,7 @@ TableTools = function( oDT, oOpts )
172
602
  */
173
603
  "selectedClass": ""
174
604
  },
175
-
605
+
176
606
  /**
177
607
  * Store of the user input customisation object
178
608
  * @property custom
@@ -180,7 +610,7 @@ TableTools = function( oDT, oOpts )
180
610
  * @default {}
181
611
  */
182
612
  "custom": {},
183
-
613
+
184
614
  /**
185
615
  * SWF movie path
186
616
  * @property swfPath
@@ -188,7 +618,7 @@ TableTools = function( oDT, oOpts )
188
618
  * @default ""
189
619
  */
190
620
  "swfPath": "",
191
-
621
+
192
622
  /**
193
623
  * Default button set
194
624
  * @property buttonSet
@@ -196,7 +626,7 @@ TableTools = function( oDT, oOpts )
196
626
  * @default []
197
627
  */
198
628
  "buttonSet": [],
199
-
629
+
200
630
  /**
201
631
  * When there is more than one TableTools instance for a DataTable, there must be a
202
632
  * master which controls events (row selection etc)
@@ -205,15 +635,15 @@ TableTools = function( oDT, oOpts )
205
635
  * @default false
206
636
  */
207
637
  "master": false,
208
-
638
+
209
639
  /**
210
640
  * Tag names that are used for creating collections and buttons
211
641
  * @namesapce
212
642
  */
213
643
  "tags": {}
214
644
  };
215
-
216
-
645
+
646
+
217
647
  /**
218
648
  * @namespace Common and useful DOM elements for the class instance
219
649
  */
@@ -225,7 +655,7 @@ TableTools = function( oDT, oOpts )
225
655
  * @default null
226
656
  */
227
657
  "container": null,
228
-
658
+
229
659
  /**
230
660
  * The table node to which TableTools will be applied
231
661
  * @property table
@@ -233,7 +663,7 @@ TableTools = function( oDT, oOpts )
233
663
  * @default null
234
664
  */
235
665
  "table": null,
236
-
666
+
237
667
  /**
238
668
  * @namespace Nodes used for the print display
239
669
  */
@@ -242,19 +672,19 @@ TableTools = function( oDT, oOpts )
242
672
  * Nodes which have been removed from the display by setting them to display none
243
673
  * @property hidden
244
674
  * @type array
245
- * @default []
675
+ * @default []
246
676
  */
247
- "hidden": [],
248
-
677
+ "hidden": [],
678
+
249
679
  /**
250
680
  * The information display saying telling the user about the print display
251
681
  * @property message
252
682
  * @type node
253
- * @default null
683
+ * @default null
254
684
  */
255
- "message": null
685
+ "message": null
256
686
  },
257
-
687
+
258
688
  /**
259
689
  * @namespace Nodes used for a collection display. This contains the currently used collection
260
690
  */
@@ -263,15 +693,15 @@ TableTools = function( oDT, oOpts )
263
693
  * The div wrapper containing the buttons in the collection (i.e. the menu)
264
694
  * @property collection
265
695
  * @type node
266
- * @default null
696
+ * @default null
267
697
  */
268
698
  "collection": null,
269
-
699
+
270
700
  /**
271
701
  * Background display to provide focus and capture events
272
702
  * @property background
273
703
  * @type node
274
- * @default null
704
+ * @default null
275
705
  */
276
706
  "background": null
277
707
  }
@@ -286,12 +716,12 @@ TableTools = function( oDT, oOpts )
286
716
  {
287
717
  $.extend( true, this.classes, TableTools.classes_themeroller );
288
718
  }
289
-
290
-
719
+
720
+
291
721
  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
292
722
  * Public class methods
293
723
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
294
-
724
+
295
725
  /**
296
726
  * Retreieve the settings object from an instance
297
727
  * @method fnSettings
@@ -300,16 +730,16 @@ TableTools = function( oDT, oOpts )
300
730
  this.fnSettings = function () {
301
731
  return this.s;
302
732
  };
303
-
304
-
733
+
734
+
305
735
  /* Constructor logic */
306
736
  if ( typeof oOpts == 'undefined' )
307
737
  {
308
738
  oOpts = {};
309
739
  }
310
-
740
+
311
741
  this._fnConstruct( oOpts );
312
-
742
+
313
743
  return this;
314
744
  };
315
745
 
@@ -319,7 +749,7 @@ TableTools.prototype = {
319
749
  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
320
750
  * Public methods
321
751
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
322
-
752
+
323
753
  /**
324
754
  * Retreieve the settings object from an instance
325
755
  * @returns {array} List of TR nodes which are currently selected
@@ -384,8 +814,8 @@ TableTools.prototype = {
384
814
 
385
815
  return out;
386
816
  },
387
-
388
-
817
+
818
+
389
819
  /**
390
820
  * Check to see if a current row is selected or not
391
821
  * @param {Node} n TR node to check if it is currently selected or not
@@ -397,7 +827,7 @@ TableTools.prototype = {
397
827
  return (this.s.dt.aoData[pos]._DTTT_selected===true) ? true : false;
398
828
  },
399
829
 
400
-
830
+
401
831
  /**
402
832
  * Select all rows in the table
403
833
  * @param {boolean} [filtered=false] Select only rows which are available
@@ -407,14 +837,14 @@ TableTools.prototype = {
407
837
  "fnSelectAll": function ( filtered )
408
838
  {
409
839
  var s = this._fnGetMasterSettings();
410
-
840
+
411
841
  this._fnRowSelect( (filtered === true) ?
412
842
  s.dt.aiDisplay :
413
843
  s.dt.aoData
414
844
  );
415
845
  },
416
846
 
417
-
847
+
418
848
  /**
419
849
  * Deselect all rows in the table
420
850
  * @param {boolean} [filtered=false] Deselect only rows which are available
@@ -428,7 +858,7 @@ TableTools.prototype = {
428
858
  this._fnRowDeselect( this.fnGetSelected(filtered) );
429
859
  },
430
860
 
431
-
861
+
432
862
  /**
433
863
  * Select row(s)
434
864
  * @param {node|object|array} n The row(s) to select. Can be a single DOM
@@ -441,13 +871,13 @@ TableTools.prototype = {
441
871
  this.fnSelectNone();
442
872
  this._fnRowSelect( n );
443
873
  }
444
- else if ( this.s.select.type == "multi" )
874
+ else
445
875
  {
446
876
  this._fnRowSelect( n );
447
877
  }
448
878
  },
449
879
 
450
-
880
+
451
881
  /**
452
882
  * Deselect row(s)
453
883
  * @param {node|object|array} n The row(s) to deselect. Can be a single DOM
@@ -457,8 +887,8 @@ TableTools.prototype = {
457
887
  {
458
888
  this._fnRowDeselect( n );
459
889
  },
460
-
461
-
890
+
891
+
462
892
  /**
463
893
  * Get the title of the document - useful for file names. The title is retrieved from either
464
894
  * the configuration object's 'title' parameter, or the HTML document title
@@ -477,7 +907,7 @@ TableTools.prototype = {
477
907
  sTitle = anTitle[0].innerHTML;
478
908
  }
479
909
  }
480
-
910
+
481
911
  /* Strip characters which the OS will object to - checking for UTF8 support in the scripting
482
912
  * engine
483
913
  */
@@ -487,8 +917,8 @@ TableTools.prototype = {
487
917
  return sTitle.replace(/[^a-zA-Z0-9_\.,\-_ !\(\)]/g, "");
488
918
  }
489
919
  },
490
-
491
-
920
+
921
+
492
922
  /**
493
923
  * Calculate a unity array with the column width by proportion for a set of columns to be
494
924
  * included for a button. This is particularly useful for PDF creation, where we can use the
@@ -503,7 +933,7 @@ TableTools.prototype = {
503
933
  aColumnsInc = this._fnColumnTargets( oConfig.mColumns ),
504
934
  aColWidths = [],
505
935
  iWidth = 0, iTotal = 0, i, iLen;
506
-
936
+
507
937
  for ( i=0, iLen=aColumnsInc.length ; i<iLen ; i++ )
508
938
  {
509
939
  if ( aColumnsInc[i] )
@@ -513,16 +943,16 @@ TableTools.prototype = {
513
943
  aColWidths.push( iWidth );
514
944
  }
515
945
  }
516
-
946
+
517
947
  for ( i=0, iLen=aColWidths.length ; i<iLen ; i++ )
518
948
  {
519
949
  aColWidths[i] = aColWidths[i] / iTotal;
520
950
  }
521
-
951
+
522
952
  return aColWidths.join('\t');
523
953
  },
524
-
525
-
954
+
955
+
526
956
  /**
527
957
  * Get the information contained in a table as a string
528
958
  * @param {Object} oConfig Button configuration object
@@ -536,8 +966,8 @@ TableTools.prototype = {
536
966
  return this._fnGetDataTablesData( oConfig );
537
967
  }
538
968
  },
539
-
540
-
969
+
970
+
541
971
  /**
542
972
  * Pass text to a flash button instance, which will be used on the button's click handler
543
973
  * @param {Object} clip Flash button object
@@ -547,8 +977,8 @@ TableTools.prototype = {
547
977
  {
548
978
  this._fnFlashSetText( clip, text );
549
979
  },
550
-
551
-
980
+
981
+
552
982
  /**
553
983
  * Resize the flash elements of the buttons attached to this TableTools instance - this is
554
984
  * useful for when initialising TableTools when it is hidden (display:none) since sizes can't
@@ -569,8 +999,8 @@ TableTools.prototype = {
569
999
  }
570
1000
  }
571
1001
  },
572
-
573
-
1002
+
1003
+
574
1004
  /**
575
1005
  * Check to see if any of the ZeroClipboard client's attached need to be resized
576
1006
  */
@@ -591,8 +1021,8 @@ TableTools.prototype = {
591
1021
  }
592
1022
  return false;
593
1023
  },
594
-
595
-
1024
+
1025
+
596
1026
  /**
597
1027
  * Programmatically enable or disable the print view
598
1028
  * @param {boolean} [bView=true] Show the print view if true or not given. If false, then
@@ -620,33 +1050,42 @@ TableTools.prototype = {
620
1050
  this._fnPrintEnd();
621
1051
  }
622
1052
  },
623
-
624
-
1053
+
1054
+
625
1055
  /**
626
1056
  * Show a message to the end user which is nicely styled
627
1057
  * @param {string} message The HTML string to show to the user
628
1058
  * @param {int} time The duration the message is to be shown on screen for (mS)
629
1059
  */
630
1060
  "fnInfo": function ( message, time ) {
631
- var nInfo = document.createElement( "div" );
632
- nInfo.className = this.classes.print.info;
633
- nInfo.innerHTML = message;
1061
+ var info = $('<div/>')
1062
+ .addClass( this.classes.print.info )
1063
+ .html( message )
1064
+ .appendTo( 'body' );
634
1065
 
635
- document.body.appendChild( nInfo );
636
-
637
1066
  setTimeout( function() {
638
- $(nInfo).fadeOut( "normal", function() {
639
- document.body.removeChild( nInfo );
1067
+ info.fadeOut( "normal", function() {
1068
+ info.remove();
640
1069
  } );
641
1070
  }, time );
642
1071
  },
643
-
644
-
645
-
1072
+
1073
+
1074
+
1075
+ /**
1076
+ * Get the container element of the instance for attaching to the DOM
1077
+ * @returns {node} DOM node
1078
+ */
1079
+ "fnContainer": function () {
1080
+ return this.dom.container;
1081
+ },
1082
+
1083
+
1084
+
646
1085
  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
647
1086
  * Private methods (they are of course public in JS, but recommended as private)
648
1087
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
649
-
1088
+
650
1089
  /**
651
1090
  * Constructor logic
652
1091
  * @method _fnConstruct
@@ -657,33 +1096,39 @@ TableTools.prototype = {
657
1096
  "_fnConstruct": function ( oOpts )
658
1097
  {
659
1098
  var that = this;
660
-
1099
+
661
1100
  this._fnCustomiseSettings( oOpts );
662
-
1101
+
663
1102
  /* Container element */
664
1103
  this.dom.container = document.createElement( this.s.tags.container );
665
1104
  this.dom.container.className = this.classes.container;
666
-
1105
+
667
1106
  /* Row selection config */
668
1107
  if ( this.s.select.type != 'none' )
669
1108
  {
670
1109
  this._fnRowSelectConfig();
671
1110
  }
672
-
1111
+
673
1112
  /* Buttons */
674
1113
  this._fnButtonDefinations( this.s.buttonSet, this.dom.container );
675
-
1114
+
676
1115
  /* Destructor */
677
1116
  this.s.dt.aoDestroyCallback.push( {
678
1117
  "sName": "TableTools",
679
1118
  "fn": function () {
680
1119
  $(that.s.dt.nTBody).off( 'click.DTTT_Select', 'tr' );
681
1120
  $(that.dom.container).empty();
1121
+
1122
+ // Remove the instance
1123
+ var idx = $.inArray( that, TableTools._aInstances );
1124
+ if ( idx !== -1 ) {
1125
+ TableTools._aInstances.splice( idx, 1 );
1126
+ }
682
1127
  }
683
1128
  } );
684
1129
  },
685
-
686
-
1130
+
1131
+
687
1132
  /**
688
1133
  * Take the user defined settings and the default settings and combine them.
689
1134
  * @method _fnCustomiseSettings
@@ -699,20 +1144,20 @@ TableTools.prototype = {
699
1144
  this.s.master = true;
700
1145
  this.s.dt._TableToolsInit = true;
701
1146
  }
702
-
1147
+
703
1148
  /* We can use the table node from comparisons to group controls */
704
1149
  this.dom.table = this.s.dt.nTable;
705
-
1150
+
706
1151
  /* Clone the defaults and then the user options */
707
1152
  this.s.custom = $.extend( {}, TableTools.DEFAULTS, oOpts );
708
-
1153
+
709
1154
  /* Flash file location */
710
1155
  this.s.swfPath = this.s.custom.sSwfPath;
711
1156
  if ( typeof ZeroClipboard_TableTools != 'undefined' )
712
1157
  {
713
1158
  ZeroClipboard_TableTools.moviePath = this.s.swfPath;
714
1159
  }
715
-
1160
+
716
1161
  /* Table row selecting */
717
1162
  this.s.select.type = this.s.custom.sRowSelect;
718
1163
  this.s.select.preRowSelect = this.s.custom.fnPreRowSelect;
@@ -730,8 +1175,8 @@ TableTools.prototype = {
730
1175
  /* Button set */
731
1176
  this.s.buttonSet = this.s.custom.aButtons;
732
1177
  },
733
-
734
-
1178
+
1179
+
735
1180
  /**
736
1181
  * Take the user input arrays and expand them to be fully defined, and then add them to a given
737
1182
  * DOM element
@@ -744,7 +1189,7 @@ TableTools.prototype = {
744
1189
  "_fnButtonDefinations": function ( buttonSet, wrapper )
745
1190
  {
746
1191
  var buttonDef;
747
-
1192
+
748
1193
  for ( var i=0, iLen=buttonSet.length ; i<iLen ; i++ )
749
1194
  {
750
1195
  if ( typeof buttonSet[i] == "string" )
@@ -766,15 +1211,15 @@ TableTools.prototype = {
766
1211
  var o = $.extend( {}, TableTools.BUTTONS[ buttonSet[i].sExtends ], true );
767
1212
  buttonDef = $.extend( o, buttonSet[i], true );
768
1213
  }
769
-
770
- wrapper.appendChild( this._fnCreateButton(
771
- buttonDef,
1214
+
1215
+ wrapper.appendChild( this._fnCreateButton(
1216
+ buttonDef,
772
1217
  $(wrapper).hasClass(this.classes.collection.container)
773
1218
  ) );
774
1219
  }
775
1220
  },
776
-
777
-
1221
+
1222
+
778
1223
  /**
779
1224
  * Create and configure a TableTools button
780
1225
  * @method _fnCreateButton
@@ -785,7 +1230,7 @@ TableTools.prototype = {
785
1230
  "_fnCreateButton": function ( oConfig, bCollectionButton )
786
1231
  {
787
1232
  var nButton = this._fnButtonBase( oConfig, bCollectionButton );
788
-
1233
+
789
1234
  if ( oConfig.sAction.match(/flash/) )
790
1235
  {
791
1236
  this._fnFlashConfig( nButton, oConfig );
@@ -803,17 +1248,17 @@ TableTools.prototype = {
803
1248
  this._fnTextConfig( nButton, oConfig );
804
1249
  this._fnCollectionConfig( nButton, oConfig );
805
1250
  }
806
-
1251
+
807
1252
  return nButton;
808
1253
  },
809
-
810
-
1254
+
1255
+
811
1256
  /**
812
1257
  * Create the DOM needed for the button and apply some base properties. All buttons start here
813
1258
  * @method _fnButtonBase
814
1259
  * @param {o} oConfig Button configuration object
815
1260
  * @returns {Node} DIV element for the button
816
- * @private
1261
+ * @private
817
1262
  */
818
1263
  "_fnButtonBase": function ( o, bCollectionButton )
819
1264
  {
@@ -821,14 +1266,14 @@ TableTools.prototype = {
821
1266
 
822
1267
  if ( bCollectionButton )
823
1268
  {
824
- sTag = o.sTag !== "default" ? o.sTag : this.s.tags.collection.button;
825
- sLiner = o.sLinerTag !== "default" ? o.sLiner : this.s.tags.collection.liner;
1269
+ sTag = o.sTag && o.sTag !== "default" ? o.sTag : this.s.tags.collection.button;
1270
+ sLiner = o.sLinerTag && o.sLinerTag !== "default" ? o.sLiner : this.s.tags.collection.liner;
826
1271
  sClass = this.classes.collection.buttons.normal;
827
1272
  }
828
1273
  else
829
1274
  {
830
- sTag = o.sTag !== "default" ? o.sTag : this.s.tags.button;
831
- sLiner = o.sLinerTag !== "default" ? o.sLiner : this.s.tags.liner;
1275
+ sTag = o.sTag && o.sTag !== "default" ? o.sTag : this.s.tags.button;
1276
+ sLiner = o.sLinerTag && o.sLinerTag !== "default" ? o.sLiner : this.s.tags.liner;
832
1277
  sClass = this.classes.buttons.normal;
833
1278
  }
834
1279
 
@@ -836,18 +1281,18 @@ TableTools.prototype = {
836
1281
  nButton = document.createElement( sTag ),
837
1282
  nSpan = document.createElement( sLiner ),
838
1283
  masterS = this._fnGetMasterSettings();
839
-
1284
+
840
1285
  nButton.className = sClass+" "+o.sButtonClass;
841
1286
  nButton.setAttribute('id', "ToolTables_"+this.s.dt.sInstance+"_"+masterS.buttonCounter );
842
1287
  nButton.appendChild( nSpan );
843
1288
  nSpan.innerHTML = o.sButtonText;
844
-
1289
+
845
1290
  masterS.buttonCounter++;
846
-
1291
+
847
1292
  return nButton;
848
1293
  },
849
-
850
-
1294
+
1295
+
851
1296
  /**
852
1297
  * Get the settings object for the master instance. When more than one TableTools instance is
853
1298
  * assigned to a DataTable, only one of them can be the 'master' (for the select rows). As such,
@@ -875,13 +1320,13 @@ TableTools.prototype = {
875
1320
  }
876
1321
  }
877
1322
  },
878
-
879
-
880
-
1323
+
1324
+
1325
+
881
1326
  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
882
1327
  * Button collection functions
883
1328
  */
884
-
1329
+
885
1330
  /**
886
1331
  * Create a collection button, when activated will present a drop down list of other buttons
887
1332
  * @param {Node} nButton Button to use for the collection activation
@@ -896,11 +1341,11 @@ TableTools.prototype = {
896
1341
  nHidden.className = this.classes.collection.container;
897
1342
  oConfig._collection = nHidden;
898
1343
  document.body.appendChild( nHidden );
899
-
1344
+
900
1345
  this._fnButtonDefinations( oConfig.aButtons, nHidden );
901
1346
  },
902
-
903
-
1347
+
1348
+
904
1349
  /**
905
1350
  * Show a button collection
906
1351
  * @param {Node} nButton Button to use for the collection
@@ -917,14 +1362,14 @@ TableTools.prototype = {
917
1362
  iDivX = oPos.left,
918
1363
  iDivY = oPos.top + $(nButton).outerHeight(),
919
1364
  iWinHeight = $(window).height(), iDocHeight = $(document).height(),
920
- iWinWidth = $(window).width(), iDocWidth = $(document).width();
921
-
1365
+ iWinWidth = $(window).width(), iDocWidth = $(document).width();
1366
+
922
1367
  nHidden.style.position = "absolute";
923
1368
  nHidden.style.left = iDivX+"px";
924
1369
  nHidden.style.top = iDivY+"px";
925
1370
  nHidden.style.display = "block";
926
1371
  $(nHidden).css('opacity',0);
927
-
1372
+
928
1373
  var nBackground = document.createElement('div');
929
1374
  nBackground.style.position = "absolute";
930
1375
  nBackground.style.left = "0px";
@@ -933,27 +1378,27 @@ TableTools.prototype = {
933
1378
  nBackground.style.width = ((iWinWidth>iDocWidth)? iWinWidth : iDocWidth) +"px";
934
1379
  nBackground.className = this.classes.collection.background;
935
1380
  $(nBackground).css('opacity',0);
936
-
1381
+
937
1382
  document.body.appendChild( nBackground );
938
1383
  document.body.appendChild( nHidden );
939
-
1384
+
940
1385
  /* Visual corrections to try and keep the collection visible */
941
1386
  var iDivWidth = $(nHidden).outerWidth();
942
1387
  var iDivHeight = $(nHidden).outerHeight();
943
-
1388
+
944
1389
  if ( iDivX + iDivWidth > iDocWidth )
945
1390
  {
946
1391
  nHidden.style.left = (iDocWidth-iDivWidth)+"px";
947
1392
  }
948
-
1393
+
949
1394
  if ( iDivY + iDivHeight > iDocHeight )
950
1395
  {
951
1396
  nHidden.style.top = (iDivY-iDivHeight-$(nButton).outerHeight())+"px";
952
1397
  }
953
-
1398
+
954
1399
  this.dom.collection.collection = nHidden;
955
1400
  this.dom.collection.background = nBackground;
956
-
1401
+
957
1402
  /* This results in a very small delay for the end user but it allows the animation to be
958
1403
  * much smoother. If you don't want the animation, then the setTimeout can be removed
959
1404
  */
@@ -964,14 +1409,14 @@ TableTools.prototype = {
964
1409
 
965
1410
  /* Resize the buttons to the Flash contents fit */
966
1411
  this.fnResizeButtons();
967
-
1412
+
968
1413
  /* Event handler to remove the collection display */
969
1414
  $(nBackground).click( function () {
970
1415
  that._fnCollectionHide.call( that, null, null );
971
1416
  } );
972
1417
  },
973
-
974
-
1418
+
1419
+
975
1420
  /**
976
1421
  * Hide a button collection
977
1422
  * @param {Node} nButton Button to use for the collection
@@ -985,28 +1430,28 @@ TableTools.prototype = {
985
1430
  {
986
1431
  return;
987
1432
  }
988
-
1433
+
989
1434
  if ( this.dom.collection.collection !== null )
990
1435
  {
991
1436
  $(this.dom.collection.collection).animate({"opacity": 0}, 500, function (e) {
992
1437
  this.style.display = "none";
993
1438
  } );
994
-
1439
+
995
1440
  $(this.dom.collection.background).animate({"opacity": 0}, 500, function (e) {
996
1441
  this.parentNode.removeChild( this );
997
1442
  } );
998
-
1443
+
999
1444
  this.dom.collection.collection = null;
1000
1445
  this.dom.collection.background = null;
1001
1446
  }
1002
1447
  },
1003
-
1004
-
1005
-
1448
+
1449
+
1450
+
1006
1451
  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1007
1452
  * Row selection functions
1008
1453
  */
1009
-
1454
+
1010
1455
  /**
1011
1456
  * Add event handlers to a table to allow for row selection
1012
1457
  * @method _fnRowSelectConfig
@@ -1018,40 +1463,123 @@ TableTools.prototype = {
1018
1463
  if ( this.s.master )
1019
1464
  {
1020
1465
  var
1021
- that = this,
1022
- i, iLen,
1466
+ that = this,
1467
+ i, iLen,
1023
1468
  dt = this.s.dt,
1024
1469
  aoOpenRows = this.s.dt.aoOpenRows;
1025
-
1470
+
1026
1471
  $(dt.nTable).addClass( this.classes.select.table );
1027
-
1028
- $(dt.nTBody).on( 'click.DTTT_Select', 'tr', function(e) {
1472
+
1473
+ // When using OS style selection, we want to cancel the shift text
1474
+ // selection, but only when the shift key is used (so you can
1475
+ // actually still select text in the table)
1476
+ if ( this.s.select.type === 'os' ) {
1477
+ $(dt.nTBody).on( 'mousedown.DTTT_Select', 'tr', function(e) {
1478
+ if ( e.shiftKey ) {
1479
+
1480
+ $(dt.nTBody)
1481
+ .css( '-moz-user-select', 'none' )
1482
+ .one('selectstart.DTTT_Select', 'tr', function () {
1483
+ return false;
1484
+ } );
1485
+ }
1486
+ } );
1487
+
1488
+ $(dt.nTBody).on( 'mouseup.DTTT_Select', 'tr', function(e) {
1489
+ $(dt.nTBody).css( '-moz-user-select', '' );
1490
+ } );
1491
+ }
1492
+
1493
+ // Row selection
1494
+ $(dt.nTBody).on( 'click.DTTT_Select', this.s.custom.sRowSelector, function(e) {
1495
+ var row = this.nodeName.toLowerCase() === 'tr' ?
1496
+ this :
1497
+ $(this).parents('tr')[0];
1498
+
1499
+ var select = that.s.select;
1500
+ var pos = that.s.dt.oInstance.fnGetPosition( row );
1501
+
1029
1502
  /* Sub-table must be ignored (odd that the selector won't do this with >) */
1030
- if ( this.parentNode != dt.nTBody )
1031
- {
1503
+ if ( row.parentNode != dt.nTBody ) {
1032
1504
  return;
1033
1505
  }
1034
-
1506
+
1035
1507
  /* Check that we are actually working with a DataTables controlled row */
1036
- if ( dt.oInstance.fnGetData(this) === null )
1037
- {
1508
+ if ( dt.oInstance.fnGetData(row) === null ) {
1038
1509
  return;
1039
1510
  }
1040
1511
 
1041
- if ( that.fnIsSelected( this ) )
1042
- {
1043
- that._fnRowDeselect( this, e );
1512
+ // Shift click, ctrl click and simple click handling to make
1513
+ // row selection a lot like a file system in desktop OSs
1514
+ if ( select.type == 'os' ) {
1515
+ if ( e.ctrlKey || e.metaKey ) {
1516
+ // Add or remove from the selection
1517
+ if ( that.fnIsSelected( row ) ) {
1518
+ that._fnRowDeselect( row, e );
1519
+ }
1520
+ else {
1521
+ that._fnRowSelect( row, e );
1522
+ }
1523
+ }
1524
+ else if ( e.shiftKey ) {
1525
+ // Add a range of rows, from the last selected row to
1526
+ // this one
1527
+ var rowIdxs = that.s.dt.aiDisplay.slice(); // visible rows
1528
+ var idx1 = $.inArray( select.lastRow, rowIdxs );
1529
+ var idx2 = $.inArray( pos, rowIdxs );
1530
+
1531
+ if ( that.fnGetSelected().length === 0 || idx1 === -1 ) {
1532
+ // select from top to here - slightly odd, but both
1533
+ // Windows and Mac OS do this
1534
+ rowIdxs.splice( $.inArray( pos, rowIdxs )+1, rowIdxs.length );
1535
+ }
1536
+ else {
1537
+ // reverse so we can shift click 'up' as well as down
1538
+ if ( idx1 > idx2 ) {
1539
+ var tmp = idx2;
1540
+ idx2 = idx1;
1541
+ idx1 = tmp;
1542
+ }
1543
+
1544
+ rowIdxs.splice( idx2+1, rowIdxs.length );
1545
+ rowIdxs.splice( 0, idx1 );
1546
+ }
1547
+
1548
+ if ( ! that.fnIsSelected( row ) ) {
1549
+ // Select range
1550
+ that._fnRowSelect( rowIdxs, e );
1551
+ }
1552
+ else {
1553
+ // Deselect range - need to keep the clicked on row selected
1554
+ rowIdxs.splice( $.inArray( pos, rowIdxs ), 1 );
1555
+ that._fnRowDeselect( rowIdxs, e );
1556
+ }
1557
+ }
1558
+ else {
1559
+ // No cmd or shift click. Deselect current if selected,
1560
+ // or select this row only
1561
+ if ( that.fnIsSelected( row ) && that.fnGetSelected().length === 1 ) {
1562
+ that._fnRowDeselect( row, e );
1563
+ }
1564
+ else {
1565
+ that.fnSelectNone();
1566
+ that._fnRowSelect( row, e );
1567
+ }
1568
+ }
1044
1569
  }
1045
- else if ( that.s.select.type == "single" )
1046
- {
1570
+ else if ( that.fnIsSelected( row ) ) {
1571
+ that._fnRowDeselect( row, e );
1572
+ }
1573
+ else if ( select.type == "single" ) {
1047
1574
  that.fnSelectNone();
1048
- that._fnRowSelect( this, e );
1575
+ that._fnRowSelect( row, e );
1049
1576
  }
1050
- else if ( that.s.select.type == "multi" )
1051
- {
1052
- that._fnRowSelect( this, e );
1577
+ else if ( select.type == "multi" ) {
1578
+ that._fnRowSelect( row, e );
1053
1579
  }
1054
- } );
1580
+
1581
+ select.lastRow = pos;
1582
+ } );//.on('selectstart', function () { return false; } );
1055
1583
 
1056
1584
  // Bind a listener to the DataTable for when new rows are created.
1057
1585
  // This allows rows to be visually selected when they should be and
@@ -1086,7 +1614,7 @@ TableTools.prototype = {
1086
1614
  anSelected.push( data[i].nTr );
1087
1615
  }
1088
1616
  }
1089
-
1617
+
1090
1618
  // User defined pre-selection function
1091
1619
  if ( this.s.select.preRowSelect !== null && !this.s.select.preRowSelect.call(this, e, anSelected, true) )
1092
1620
  {
@@ -1161,7 +1689,7 @@ TableTools.prototype = {
1161
1689
 
1162
1690
  TableTools._fnEventDispatch( this, 'select', anDeselectedTrs, false );
1163
1691
  },
1164
-
1692
+
1165
1693
  /**
1166
1694
  * Take a data source for row selection and convert it into aoData points for the DT
1167
1695
  * @param {*} src Can be a single DOM TR node, an array of TR nodes (including a
@@ -1209,12 +1737,12 @@ TableTools.prototype = {
1209
1737
 
1210
1738
  return out;
1211
1739
  },
1212
-
1213
-
1740
+
1741
+
1214
1742
  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1215
1743
  * Text button functions
1216
1744
  */
1217
-
1745
+
1218
1746
  /**
1219
1747
  * Configure a text based button for interaction events
1220
1748
  * @method _fnTextConfig
@@ -1226,17 +1754,17 @@ TableTools.prototype = {
1226
1754
  "_fnTextConfig": function ( nButton, oConfig )
1227
1755
  {
1228
1756
  var that = this;
1229
-
1757
+
1230
1758
  if ( oConfig.fnInit !== null )
1231
1759
  {
1232
1760
  oConfig.fnInit.call( this, nButton, oConfig );
1233
1761
  }
1234
-
1762
+
1235
1763
  if ( oConfig.sToolTip !== "" )
1236
1764
  {
1237
1765
  nButton.title = oConfig.sToolTip;
1238
1766
  }
1239
-
1767
+
1240
1768
  $(nButton).hover( function () {
1241
1769
  if ( oConfig.fnMouseover !== null )
1242
1770
  {
@@ -1248,38 +1776,38 @@ TableTools.prototype = {
1248
1776
  oConfig.fnMouseout.call( this, nButton, oConfig, null );
1249
1777
  }
1250
1778
  } );
1251
-
1779
+
1252
1780
  if ( oConfig.fnSelect !== null )
1253
1781
  {
1254
1782
  TableTools._fnEventListen( this, 'select', function (n) {
1255
1783
  oConfig.fnSelect.call( that, nButton, oConfig, n );
1256
1784
  } );
1257
1785
  }
1258
-
1786
+
1259
1787
  $(nButton).click( function (e) {
1260
1788
  //e.preventDefault();
1261
-
1789
+
1262
1790
  if ( oConfig.fnClick !== null )
1263
1791
  {
1264
1792
  oConfig.fnClick.call( that, nButton, oConfig, null, e );
1265
1793
  }
1266
-
1794
+
1267
1795
  /* Provide a complete function to match the behaviour of the flash elements */
1268
1796
  if ( oConfig.fnComplete !== null )
1269
1797
  {
1270
1798
  oConfig.fnComplete.call( that, nButton, oConfig, null, null );
1271
1799
  }
1272
-
1800
+
1273
1801
  that._fnCollectionHide( nButton, oConfig );
1274
1802
  } );
1275
1803
  },
1276
-
1277
-
1278
-
1804
+
1805
+
1806
+
1279
1807
  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1280
1808
  * Flash button functions
1281
1809
  */
1282
-
1810
+
1283
1811
  /**
1284
1812
  * Configure a flash based button for interaction events
1285
1813
  * @method _fnFlashConfig
@@ -1292,14 +1820,14 @@ TableTools.prototype = {
1292
1820
  {
1293
1821
  var that = this;
1294
1822
  var flash = new ZeroClipboard_TableTools.Client();
1295
-
1823
+
1296
1824
  if ( oConfig.fnInit !== null )
1297
1825
  {
1298
1826
  oConfig.fnInit.call( this, nButton, oConfig );
1299
1827
  }
1300
-
1828
+
1301
1829
  flash.setHandCursor( true );
1302
-
1830
+
1303
1831
  if ( oConfig.sAction == "flash_save" )
1304
1832
  {
1305
1833
  flash.setAction( 'save' );
@@ -1316,28 +1844,28 @@ TableTools.prototype = {
1316
1844
  {
1317
1845
  flash.setAction( 'copy' );
1318
1846
  }
1319
-
1847
+
1320
1848
  flash.addEventListener('mouseOver', function(client) {
1321
1849
  if ( oConfig.fnMouseover !== null )
1322
1850
  {
1323
1851
  oConfig.fnMouseover.call( that, nButton, oConfig, flash );
1324
1852
  }
1325
1853
  } );
1326
-
1854
+
1327
1855
  flash.addEventListener('mouseOut', function(client) {
1328
1856
  if ( oConfig.fnMouseout !== null )
1329
1857
  {
1330
1858
  oConfig.fnMouseout.call( that, nButton, oConfig, flash );
1331
1859
  }
1332
1860
  } );
1333
-
1861
+
1334
1862
  flash.addEventListener('mouseDown', function(client) {
1335
1863
  if ( oConfig.fnClick !== null )
1336
1864
  {
1337
1865
  oConfig.fnClick.call( that, nButton, oConfig, flash );
1338
1866
  }
1339
1867
  } );
1340
-
1868
+
1341
1869
  flash.addEventListener('complete', function (client, text) {
1342
1870
  if ( oConfig.fnComplete !== null )
1343
1871
  {
@@ -1345,11 +1873,11 @@ TableTools.prototype = {
1345
1873
  }
1346
1874
  that._fnCollectionHide( nButton, oConfig );
1347
1875
  } );
1348
-
1876
+
1349
1877
  this._fnFlashGlue( flash, nButton, oConfig.sToolTip );
1350
1878
  },
1351
-
1352
-
1879
+
1880
+
1353
1881
  /**
1354
1882
  * Wait until the id is in the DOM before we "glue" the swf. Note that this function will call
1355
1883
  * itself (using setTimeout) until it completes successfully
@@ -1364,7 +1892,7 @@ TableTools.prototype = {
1364
1892
  {
1365
1893
  var that = this;
1366
1894
  var id = node.getAttribute('id');
1367
-
1895
+
1368
1896
  if ( document.getElementById(id) )
1369
1897
  {
1370
1898
  flash.glue( node, text );
@@ -1376,8 +1904,8 @@ TableTools.prototype = {
1376
1904
  }, 100 );
1377
1905
  }
1378
1906
  },
1379
-
1380
-
1907
+
1908
+
1381
1909
  /**
1382
1910
  * Set the text for the flash clip to deal with
1383
1911
  *
@@ -1395,20 +1923,20 @@ TableTools.prototype = {
1395
1923
  "_fnFlashSetText": function ( clip, sData )
1396
1924
  {
1397
1925
  var asData = this._fnChunkData( sData, 8192 );
1398
-
1926
+
1399
1927
  clip.clearText();
1400
1928
  for ( var i=0, iLen=asData.length ; i<iLen ; i++ )
1401
1929
  {
1402
1930
  clip.appendText( asData[i] );
1403
1931
  }
1404
1932
  },
1405
-
1406
-
1407
-
1933
+
1934
+
1935
+
1408
1936
  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1409
1937
  * Data retrieval functions
1410
1938
  */
1411
-
1939
+
1412
1940
  /**
1413
1941
  * Convert the mixed columns variable into a boolean array the same size as the columns, which
1414
1942
  * indicates which columns we want to include
@@ -1424,14 +1952,15 @@ TableTools.prototype = {
1424
1952
  {
1425
1953
  var aColumns = [];
1426
1954
  var dt = this.s.dt;
1427
-
1955
+ var i, iLen;
1956
+
1428
1957
  if ( typeof mColumns == "object" )
1429
1958
  {
1430
1959
  for ( i=0, iLen=dt.aoColumns.length ; i<iLen ; i++ )
1431
1960
  {
1432
1961
  aColumns.push( false );
1433
1962
  }
1434
-
1963
+
1435
1964
  for ( i=0, iLen=mColumns.length ; i<iLen ; i++ )
1436
1965
  {
1437
1966
  aColumns[ mColumns[i] ] = true;
@@ -1465,11 +1994,11 @@ TableTools.prototype = {
1465
1994
  aColumns.push( true );
1466
1995
  }
1467
1996
  }
1468
-
1997
+
1469
1998
  return aColumns;
1470
1999
  },
1471
-
1472
-
2000
+
2001
+
1473
2002
  /**
1474
2003
  * New line character(s) depend on the platforms
1475
2004
  * @method method
@@ -1487,8 +2016,8 @@ TableTools.prototype = {
1487
2016
  return oConfig.sNewLine;
1488
2017
  }
1489
2018
  },
1490
-
1491
-
2019
+
2020
+
1492
2021
  /**
1493
2022
  * Get data from DataTables' internals and format it for output
1494
2023
  * @method _fnGetDataTablesData
@@ -1511,47 +2040,49 @@ TableTools.prototype = {
1511
2040
  var regex = new RegExp(oConfig.sFieldBoundary, "g"); /* Do it here for speed */
1512
2041
  var aColumnsInc = this._fnColumnTargets( oConfig.mColumns );
1513
2042
  var bSelectedOnly = (typeof oConfig.bSelectedOnly != 'undefined') ? oConfig.bSelectedOnly : false;
1514
-
2043
+
1515
2044
  /*
1516
2045
  * Header
1517
2046
  */
1518
2047
  if ( oConfig.bHeader )
1519
2048
  {
1520
2049
  aRow = [];
1521
-
2050
+
1522
2051
  for ( i=0, iLen=dt.aoColumns.length ; i<iLen ; i++ )
1523
2052
  {
1524
2053
  if ( aColumnsInc[i] )
1525
2054
  {
1526
2055
  sLoopData = dt.aoColumns[i].sTitle.replace(/\n/g," ").replace( /<.*?>/g, "" ).replace(/^\s+|\s+$/g,"");
1527
2056
  sLoopData = this._fnHtmlDecode( sLoopData );
1528
-
2057
+
1529
2058
  aRow.push( this._fnBoundData( sLoopData, oConfig.sFieldBoundary, regex ) );
1530
2059
  }
1531
2060
  }
1532
2061
 
1533
2062
  aData.push( aRow.join(oConfig.sFieldSeperator) );
1534
2063
  }
1535
-
2064
+
1536
2065
  /*
1537
2066
  * Body
1538
2067
  */
1539
- var aDataIndex = dt.aiDisplay;
1540
2068
  var aSelected = this.fnGetSelected();
1541
- if ( this.s.select.type !== "none" && bSelectedOnly && aSelected.length !== 0 )
1542
- {
1543
- aDataIndex = [];
1544
- for ( i=0, iLen=aSelected.length ; i<iLen ; i++ )
1545
- {
1546
- aDataIndex.push( dt.oInstance.fnGetPosition( aSelected[i] ) );
1547
- }
1548
- }
1549
-
2069
+ bSelectedOnly = this.s.select.type !== "none" && bSelectedOnly && aSelected.length !== 0;
2070
+
2071
+ var aDataIndex = dt.oInstance
2072
+ .$('tr', oConfig.oSelectorOpts)
2073
+ .map( function (id, row) {
2074
+ // If "selected only", then ensure that the row is in the selected list
2075
+ return bSelectedOnly && $.inArray( row, aSelected ) === -1 ?
2076
+ null :
2077
+ dt.oInstance.fnGetPosition( row );
2078
+ } )
2079
+ .get();
2080
+
1550
2081
  for ( j=0, jLen=aDataIndex.length ; j<jLen ; j++ )
1551
2082
  {
1552
2083
  tr = dt.aoData[ aDataIndex[j] ].nTr;
1553
2084
  aRow = [];
1554
-
2085
+
1555
2086
  /* Columns */
1556
2087
  for ( i=0, iLen=dt.aoColumns.length ; i<iLen ; i++ )
1557
2088
  {
@@ -1568,31 +2099,31 @@ TableTools.prototype = {
1568
2099
  /* Strip newlines, replace img tags with alt attr. and finally strip html... */
1569
2100
  sLoopData = mTypeData.replace(/\n/g," ");
1570
2101
  sLoopData =
1571
- sLoopData.replace(/<img.*?\s+alt\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s>]+)).*?>/gi,
1572
- '$1$2$3');
2102
+ sLoopData.replace(/<img.*?\s+alt\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s>]+)).*?>/gi,
2103
+ '$1$2$3');
1573
2104
  sLoopData = sLoopData.replace( /<.*?>/g, "" );
1574
2105
  }
1575
2106
  else
1576
2107
  {
1577
2108
  sLoopData = mTypeData+"";
1578
2109
  }
1579
-
2110
+
1580
2111
  /* Trim and clean the data */
1581
2112
  sLoopData = sLoopData.replace(/^\s+/, '').replace(/\s+$/, '');
1582
2113
  sLoopData = this._fnHtmlDecode( sLoopData );
1583
-
2114
+
1584
2115
  /* Bound it and add it to the total data */
1585
2116
  aRow.push( this._fnBoundData( sLoopData, oConfig.sFieldBoundary, regex ) );
1586
2117
  }
1587
2118
  }
1588
-
2119
+
1589
2120
  aData.push( aRow.join(oConfig.sFieldSeperator) );
1590
-
2121
+
1591
2122
  /* Details rows from fnOpen */
1592
2123
  if ( oConfig.bOpenRows )
1593
2124
  {
1594
2125
  arr = $.grep(dt.aoOpenRows, function(o) { return o.nParent === tr; });
1595
-
2126
+
1596
2127
  if ( arr.length === 1 )
1597
2128
  {
1598
2129
  sLoopData = this._fnBoundData( $('td', arr[0].nTr).html(), oConfig.sFieldBoundary, regex );
@@ -1600,33 +2131,33 @@ TableTools.prototype = {
1600
2131
  }
1601
2132
  }
1602
2133
  }
1603
-
2134
+
1604
2135
  /*
1605
2136
  * Footer
1606
2137
  */
1607
2138
  if ( oConfig.bFooter && dt.nTFoot !== null )
1608
2139
  {
1609
2140
  aRow = [];
1610
-
2141
+
1611
2142
  for ( i=0, iLen=dt.aoColumns.length ; i<iLen ; i++ )
1612
2143
  {
1613
2144
  if ( aColumnsInc[i] && dt.aoColumns[i].nTf !== null )
1614
2145
  {
1615
2146
  sLoopData = dt.aoColumns[i].nTf.innerHTML.replace(/\n/g," ").replace( /<.*?>/g, "" );
1616
2147
  sLoopData = this._fnHtmlDecode( sLoopData );
1617
-
2148
+
1618
2149
  aRow.push( this._fnBoundData( sLoopData, oConfig.sFieldBoundary, regex ) );
1619
2150
  }
1620
2151
  }
1621
-
2152
+
1622
2153
  aData.push( aRow.join(oConfig.sFieldSeperator) );
1623
2154
  }
1624
-
1625
- _sLastData = aData.join( this._fnNewline(oConfig) );
2155
+
2156
+ var _sLastData = aData.join( this._fnNewline(oConfig) );
1626
2157
  return _sLastData;
1627
2158
  },
1628
-
1629
-
2159
+
2160
+
1630
2161
  /**
1631
2162
  * Wrap data up with a boundary string
1632
2163
  * @method _fnBoundData
@@ -1648,8 +2179,8 @@ TableTools.prototype = {
1648
2179
  return sBoundary + sData.replace(regex, sBoundary+sBoundary) + sBoundary;
1649
2180
  }
1650
2181
  },
1651
-
1652
-
2182
+
2183
+
1653
2184
  /**
1654
2185
  * Break a string up into an array of smaller strings
1655
2186
  * @method _fnChunkData
@@ -1662,7 +2193,7 @@ TableTools.prototype = {
1662
2193
  {
1663
2194
  var asReturn = [];
1664
2195
  var iStrlen = sData.length;
1665
-
2196
+
1666
2197
  for ( var i=0 ; i<iStrlen ; i+=iSize )
1667
2198
  {
1668
2199
  if ( i+iSize < iStrlen )
@@ -1674,11 +2205,11 @@ TableTools.prototype = {
1674
2205
  asReturn.push( sData.substring( i, iStrlen ) );
1675
2206
  }
1676
2207
  }
1677
-
2208
+
1678
2209
  return asReturn;
1679
2210
  },
1680
-
1681
-
2211
+
2212
+
1682
2213
  /**
1683
2214
  * Decode HTML entities
1684
2215
  * @method _fnHtmlDecode
@@ -1692,7 +2223,7 @@ TableTools.prototype = {
1692
2223
  {
1693
2224
  return sData;
1694
2225
  }
1695
-
2226
+
1696
2227
  var n = document.createElement('div');
1697
2228
 
1698
2229
  return sData.replace( /&([^\s]*);/g, function( match, match2 ) {
@@ -1707,13 +2238,13 @@ TableTools.prototype = {
1707
2238
  }
1708
2239
  } );
1709
2240
  },
1710
-
1711
-
1712
-
2241
+
2242
+
2243
+
1713
2244
  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1714
2245
  * Printing functions
1715
2246
  */
1716
-
2247
+
1717
2248
  /**
1718
2249
  * Show print display
1719
2250
  * @method _fnPrintStart
@@ -1726,10 +2257,10 @@ TableTools.prototype = {
1726
2257
  {
1727
2258
  var that = this;
1728
2259
  var oSetDT = this.s.dt;
1729
-
2260
+
1730
2261
  /* Parse through the DOM hiding everything that isn't needed for the table */
1731
2262
  this._fnPrintHideNodes( oSetDT.nTable );
1732
-
2263
+
1733
2264
  /* Show the whole table */
1734
2265
  this.s.print.saveStart = oSetDT._iDisplayStart;
1735
2266
  this.s.print.saveLength = oSetDT._iDisplayLength;
@@ -1738,10 +2269,12 @@ TableTools.prototype = {
1738
2269
  {
1739
2270
  oSetDT._iDisplayStart = 0;
1740
2271
  oSetDT._iDisplayLength = -1;
1741
- oSetDT.oApi._fnCalculateEnd( oSetDT );
2272
+ if ( oSetDT.oApi._fnCalculateEnd ) {
2273
+ oSetDT.oApi._fnCalculateEnd( oSetDT );
2274
+ }
1742
2275
  oSetDT.oApi._fnDraw( oSetDT );
1743
2276
  }
1744
-
2277
+
1745
2278
  /* Adjust the display for scrolling which might be done by DataTables */
1746
2279
  if ( oSetDT.oScroll.sX !== "" || oSetDT.oScroll.sY !== "" )
1747
2280
  {
@@ -1753,7 +2286,7 @@ TableTools.prototype = {
1753
2286
  that._fnPrintScrollStart( oSetDT );
1754
2287
  } );
1755
2288
  }
1756
-
2289
+
1757
2290
  /* Remove the other DataTables feature nodes - but leave the table! and info div */
1758
2291
  var anFeature = oSetDT.aanFeatures;
1759
2292
  for ( var cFeature in anFeature )
@@ -1770,7 +2303,7 @@ TableTools.prototype = {
1770
2303
  }
1771
2304
  }
1772
2305
  }
1773
-
2306
+
1774
2307
  /* Print class can be used for styling */
1775
2308
  $(document.body).addClass( this.classes.print.body );
1776
2309
 
@@ -1783,12 +2316,12 @@ TableTools.prototype = {
1783
2316
  /* Add a message at the top of the page */
1784
2317
  if ( oConfig.sMessage )
1785
2318
  {
1786
- this.dom.print.message = document.createElement( "div" );
1787
- this.dom.print.message.className = this.classes.print.message;
1788
- this.dom.print.message.innerHTML = oConfig.sMessage;
1789
- document.body.insertBefore( this.dom.print.message, document.body.childNodes[0] );
2319
+ $('<div/>')
2320
+ .addClass( this.classes.print.message )
2321
+ .html( oConfig.sMessage )
2322
+ .prependTo( 'body' );
1790
2323
  }
1791
-
2324
+
1792
2325
  /* Cache the scrolling and the jump to the top of the page */
1793
2326
  this.s.print.saveScroll = $(window).scrollTop();
1794
2327
  window.scrollTo( 0, 0 );
@@ -1805,8 +2338,8 @@ TableTools.prototype = {
1805
2338
  }
1806
2339
  } );
1807
2340
  },
1808
-
1809
-
2341
+
2342
+
1810
2343
  /**
1811
2344
  * Printing is finished, resume normal display
1812
2345
  * @method _fnPrintEnd
@@ -1820,10 +2353,10 @@ TableTools.prototype = {
1820
2353
  var oSetDT = this.s.dt;
1821
2354
  var oSetPrint = this.s.print;
1822
2355
  var oDomPrint = this.dom.print;
1823
-
2356
+
1824
2357
  /* Show all hidden nodes */
1825
2358
  this._fnPrintShowNodes();
1826
-
2359
+
1827
2360
  /* Restore DataTables' scrolling */
1828
2361
  if ( oSetDT.oScroll.sX !== "" || oSetDT.oScroll.sY !== "" )
1829
2362
  {
@@ -1831,30 +2364,28 @@ TableTools.prototype = {
1831
2364
 
1832
2365
  this._fnPrintScrollEnd();
1833
2366
  }
1834
-
2367
+
1835
2368
  /* Restore the scroll */
1836
2369
  window.scrollTo( 0, oSetPrint.saveScroll );
1837
-
2370
+
1838
2371
  /* Drop the print message */
1839
- if ( oDomPrint.message !== null )
1840
- {
1841
- document.body.removeChild( oDomPrint.message );
1842
- oDomPrint.message = null;
1843
- }
1844
-
2372
+ $('div.'+this.classes.print.message).remove();
2373
+
1845
2374
  /* Styling class */
1846
2375
  $(document.body).removeClass( 'DTTT_Print' );
1847
-
2376
+
1848
2377
  /* Restore the table length */
1849
2378
  oSetDT._iDisplayStart = oSetPrint.saveStart;
1850
2379
  oSetDT._iDisplayLength = oSetPrint.saveLength;
1851
- oSetDT.oApi._fnCalculateEnd( oSetDT );
2380
+ if ( oSetDT.oApi._fnCalculateEnd ) {
2381
+ oSetDT.oApi._fnCalculateEnd( oSetDT );
2382
+ }
1852
2383
  oSetDT.oApi._fnDraw( oSetDT );
1853
-
2384
+
1854
2385
  $(document).unbind( "keydown.DTTT" );
1855
2386
  },
1856
-
1857
-
2387
+
2388
+
1858
2389
  /**
1859
2390
  * Take account of scrolling in DataTables by showing the full table
1860
2391
  * @returns void
@@ -1862,39 +2393,40 @@ TableTools.prototype = {
1862
2393
  */
1863
2394
  "_fnPrintScrollStart": function ()
1864
2395
  {
1865
- var
2396
+ var
1866
2397
  oSetDT = this.s.dt,
1867
2398
  nScrollHeadInner = oSetDT.nScrollHead.getElementsByTagName('div')[0],
1868
2399
  nScrollHeadTable = nScrollHeadInner.getElementsByTagName('table')[0],
1869
- nScrollBody = oSetDT.nTable.parentNode;
2400
+ nScrollBody = oSetDT.nTable.parentNode,
2401
+ nTheadSize, nTfootSize;
1870
2402
 
1871
2403
  /* Copy the header in the thead in the body table, this way we show one single table when
1872
2404
  * in print view. Note that this section of code is more or less verbatim from DT 1.7.0
1873
2405
  */
1874
- var nTheadSize = oSetDT.nTable.getElementsByTagName('thead');
2406
+ nTheadSize = oSetDT.nTable.getElementsByTagName('thead');
1875
2407
  if ( nTheadSize.length > 0 )
1876
2408
  {
1877
2409
  oSetDT.nTable.removeChild( nTheadSize[0] );
1878
2410
  }
1879
-
2411
+
1880
2412
  if ( oSetDT.nTFoot !== null )
1881
2413
  {
1882
- var nTfootSize = oSetDT.nTable.getElementsByTagName('tfoot');
2414
+ nTfootSize = oSetDT.nTable.getElementsByTagName('tfoot');
1883
2415
  if ( nTfootSize.length > 0 )
1884
2416
  {
1885
2417
  oSetDT.nTable.removeChild( nTfootSize[0] );
1886
2418
  }
1887
2419
  }
1888
-
2420
+
1889
2421
  nTheadSize = oSetDT.nTHead.cloneNode(true);
1890
2422
  oSetDT.nTable.insertBefore( nTheadSize, oSetDT.nTable.childNodes[0] );
1891
-
2423
+
1892
2424
  if ( oSetDT.nTFoot !== null )
1893
2425
  {
1894
2426
  nTfootSize = oSetDT.nTFoot.cloneNode(true);
1895
2427
  oSetDT.nTable.insertBefore( nTfootSize, oSetDT.nTable.childNodes[1] );
1896
2428
  }
1897
-
2429
+
1898
2430
  /* Now adjust the table's viewport so we can actually see it */
1899
2431
  if ( oSetDT.oScroll.sX !== "" )
1900
2432
  {
@@ -1902,15 +2434,15 @@ TableTools.prototype = {
1902
2434
  nScrollBody.style.width = $(oSetDT.nTable).outerWidth()+"px";
1903
2435
  nScrollBody.style.overflow = "visible";
1904
2436
  }
1905
-
2437
+
1906
2438
  if ( oSetDT.oScroll.sY !== "" )
1907
2439
  {
1908
2440
  nScrollBody.style.height = $(oSetDT.nTable).outerHeight()+"px";
1909
2441
  nScrollBody.style.overflow = "visible";
1910
2442
  }
1911
2443
  },
1912
-
1913
-
2444
+
2445
+
1914
2446
  /**
1915
2447
  * Take account of scrolling in DataTables by showing the full table. Note that the redraw of
1916
2448
  * the DataTable that we do will actually deal with the majority of the hard work here
@@ -1919,24 +2451,24 @@ TableTools.prototype = {
1919
2451
  */
1920
2452
  "_fnPrintScrollEnd": function ()
1921
2453
  {
1922
- var
2454
+ var
1923
2455
  oSetDT = this.s.dt,
1924
2456
  nScrollBody = oSetDT.nTable.parentNode;
1925
-
2457
+
1926
2458
  if ( oSetDT.oScroll.sX !== "" )
1927
2459
  {
1928
2460
  nScrollBody.style.width = oSetDT.oApi._fnStringToCss( oSetDT.oScroll.sX );
1929
2461
  nScrollBody.style.overflow = "auto";
1930
2462
  }
1931
-
2463
+
1932
2464
  if ( oSetDT.oScroll.sY !== "" )
1933
2465
  {
1934
2466
  nScrollBody.style.height = oSetDT.oApi._fnStringToCss( oSetDT.oScroll.sY );
1935
2467
  nScrollBody.style.overflow = "auto";
1936
2468
  }
1937
2469
  },
1938
-
1939
-
2470
+
2471
+
1940
2472
  /**
1941
2473
  * Resume the display of all TableTools hidden nodes
1942
2474
  * @method _fnPrintShowNodes
@@ -1946,15 +2478,15 @@ TableTools.prototype = {
1946
2478
  "_fnPrintShowNodes": function ( )
1947
2479
  {
1948
2480
  var anHidden = this.dom.print.hidden;
1949
-
2481
+
1950
2482
  for ( var i=0, iLen=anHidden.length ; i<iLen ; i++ )
1951
2483
  {
1952
2484
  anHidden[i].node.style.display = anHidden[i].display;
1953
2485
  }
1954
2486
  anHidden.splice( 0, anHidden.length );
1955
2487
  },
1956
-
1957
-
2488
+
2489
+
1958
2490
  /**
1959
2491
  * Hide nodes which are not needed in order to display the table. Note that this function is
1960
2492
  * recursive
@@ -1965,8 +2497,8 @@ TableTools.prototype = {
1965
2497
  */
1966
2498
  "_fnPrintHideNodes": function ( nNode )
1967
2499
  {
1968
- var anHidden = this.dom.print.hidden;
1969
-
2500
+ var anHidden = this.dom.print.hidden;
2501
+
1970
2502
  var nParent = nNode.parentNode;
1971
2503
  var nChildren = nParent.childNodes;
1972
2504
  for ( var i=0, iLen=nChildren.length ; i<iLen ; i++ )
@@ -1975,7 +2507,7 @@ TableTools.prototype = {
1975
2507
  {
1976
2508
  /* If our node is shown (don't want to show nodes which were previously hidden) */
1977
2509
  var sDisplay = $(nChildren[i]).css("display");
1978
- if ( sDisplay != "none" )
2510
+ if ( sDisplay != "none" )
1979
2511
  {
1980
2512
  /* Cache the node and it's previous state so we can restore it */
1981
2513
  anHidden.push( {
@@ -1986,8 +2518,8 @@ TableTools.prototype = {
1986
2518
  }
1987
2519
  }
1988
2520
  }
1989
-
1990
- if ( nParent.nodeName != "BODY" )
2521
+
2522
+ if ( nParent.nodeName.toUpperCase() != "BODY" )
1991
2523
  {
1992
2524
  this._fnPrintHideNodes( nParent );
1993
2525
  }
@@ -2056,7 +2588,7 @@ TableTools.fnGetInstance = function ( node )
2056
2588
  {
2057
2589
  node = document.getElementById(node);
2058
2590
  }
2059
-
2591
+
2060
2592
  for ( var i=0, iLen=TableTools._aInstances.length ; i<iLen ; i++ )
2061
2593
  {
2062
2594
  if ( TableTools._aInstances[i].s.master && TableTools._aInstances[i].dom.table == node )
@@ -2086,7 +2618,7 @@ TableTools._fnEventListen = function ( that, type, fn )
2086
2618
  "fn": fn
2087
2619
  } );
2088
2620
  };
2089
-
2621
+
2090
2622
 
2091
2623
  /**
2092
2624
  * An event has occurred - look up every listener and fire it off. We check that the event we are
@@ -2145,6 +2677,7 @@ TableTools.buttonBase = {
2145
2677
  "bFooter": true,
2146
2678
  "bOpenRows": false,
2147
2679
  "bSelectedOnly": false,
2680
+ "oSelectorOpts": undefined, // See http://datatables.net/docs/DataTables/1.9.4/#$ for full options
2148
2681
 
2149
2682
  // Callbacks
2150
2683
  "fnMouseover": null,
@@ -2212,7 +2745,7 @@ TableTools.BUTTONS = {
2212
2745
  "sPdfSize": "A4",
2213
2746
  "sPdfMessage": "",
2214
2747
  "fnClick": function( nButton, oConfig, flash ) {
2215
- this.fnSetText( flash,
2748
+ this.fnSetText( flash,
2216
2749
  "title:"+ this.fnGetTitle(oConfig) +"\n"+
2217
2750
  "message:"+ oConfig.sPdfMessage +"\n"+
2218
2751
  "colWidth:"+ this.fnCalcColRatios(oConfig) +"\n"+
@@ -2226,7 +2759,7 @@ TableTools.BUTTONS = {
2226
2759
 
2227
2760
  "print": $.extend( {}, TableTools.buttonBase, {
2228
2761
  "sInfo": "<h6>Print view</h6><p>Please use your browser's print function to "+
2229
- "print this table. Press escape when finished.",
2762
+ "print this table. Press escape when finished.</p>",
2230
2763
  "sMessage": null,
2231
2764
  "bShowAll": true,
2232
2765
  "sToolTip": "View print view",
@@ -2311,7 +2844,7 @@ TableTools.BUTTONS = {
2311
2844
  ],
2312
2845
  "success": oConfig.fnAjaxComplete,
2313
2846
  "dataType": "json",
2314
- "type": "POST",
2847
+ "type": "POST",
2315
2848
  "cache": false,
2316
2849
  "error": function () {
2317
2850
  alert( "Error detected when sending table data to server" );
@@ -2341,12 +2874,14 @@ TableTools.BUTTONS = {
2341
2874
  };
2342
2875
  /*
2343
2876
  * on* callback parameters:
2344
- * 1. node - button element
2345
- * 2. object - configuration object for this button
2346
- * 3. object - ZeroClipboard reference (flash button only)
2347
- * 4. string - Returned string from Flash (flash button only - and only on 'complete')
2877
+ * 1. node - button element
2878
+ * 2. object - configuration object for this button
2879
+ * 3. object - ZeroClipboard reference (flash button only)
2880
+ * 4. string - Returned string from Flash (flash button only - and only on 'complete')
2348
2881
  */
2349
2882
 
2883
+ // Alias to match the other plug-ins styling
2884
+ TableTools.buttons = TableTools.BUTTONS;
2350
2885
 
2351
2886
 
2352
2887
  /**
@@ -2370,7 +2905,7 @@ TableTools.classes = {
2370
2905
  },
2371
2906
  "select": {
2372
2907
  "table": "DTTT_selectable",
2373
- "row": "DTTT_selected"
2908
+ "row": "DTTT_selected selected"
2374
2909
  },
2375
2910
  "print": {
2376
2911
  "body": "DTTT_Print",
@@ -2399,8 +2934,9 @@ TableTools.classes_themeroller = {
2399
2934
  * @namespace TableTools default settings for initialisation
2400
2935
  */
2401
2936
  TableTools.DEFAULTS = {
2402
- "sSwfPath": "media/swf/copy_csv_xls_pdf.swf",
2937
+ "sSwfPath": "../swf/copy_csv_xls_pdf.swf",
2403
2938
  "sRowSelect": "none",
2939
+ "sRowSelector": "tr",
2404
2940
  "sSelectedClass": null,
2405
2941
  "fnPreRowSelect": null,
2406
2942
  "fnRowSelected": null,
@@ -2419,6 +2955,9 @@ TableTools.DEFAULTS = {
2419
2955
  }
2420
2956
  };
2421
2957
 
2958
+ // Alias to match the other plug-ins
2959
+ TableTools.defaults = TableTools.DEFAULTS;
2960
+
2422
2961
 
2423
2962
  /**
2424
2963
  * Name of this class
@@ -2435,8 +2974,27 @@ TableTools.prototype.CLASS = "TableTools";
2435
2974
  * @type String
2436
2975
  * @default See code
2437
2976
  */
2438
- TableTools.VERSION = "2.1.5";
2439
- TableTools.prototype.VERSION = TableTools.VERSION;
2977
+ TableTools.version = "2.2.1";
2978
+
2979
+
2980
+
2981
+ // DataTables 1.10 API
2982
+ //
2983
+ // This will be extended in a big way in in TableTools 3 to provide API methods
2984
+ // such as rows().select() and rows.selected() etc, but for the moment the
2985
+ // tabletools() method simply returns the instance.
2986
+
2987
+ if ( $.fn.dataTable.Api ) {
2988
+ $.fn.dataTable.Api.register( 'tabletools()', function () {
2989
+ var tt = null;
2990
+
2991
+ if ( this.context.length > 0 ) {
2992
+ tt = TableTools.fnGetInstance( this.context[0].nTable );
2993
+ }
2994
+
2995
+ return tt;
2996
+ } );
2997
+ }
2440
2998
 
2441
2999
 
2442
3000
 
@@ -2454,12 +3012,44 @@ if ( typeof $.fn.dataTable == "function" &&
2454
3012
  {
2455
3013
  $.fn.dataTableExt.aoFeatures.push( {
2456
3014
  "fnInit": function( oDTSettings ) {
2457
- var oOpts = typeof oDTSettings.oInit.oTableTools != 'undefined' ?
3015
+ var init = oDTSettings.oInit;
3016
+ var opts = init ?
3017
+ init.tableTools || init.oTableTools || {} :
3018
+ {};
3019
+
3020
+ var oTT = new TableTools( oDTSettings.oInstance, opts );
3021
+ TableTools._aInstances.push( oTT );
3022
+
3023
+ return oTT.dom.container;
3024
+ },
3025
+ "cFeature": "T",
3026
+ "sFeature": "TableTools"
3027
+ } );
3028
+ }
3029
+ else
3030
+ {
3031
+ alert( "Warning: TableTools requires DataTables 1.9.0 or newer - www.datatables.net/download");
3032
+ }
3033
+
3034
+ $.fn.DataTable.TableTools = TableTools;
3035
+
3036
+ })(jQuery, window, document);
3037
+
3038
+ /*
3039
+ * Register a new feature with DataTables
3040
+ */
3041
+ if ( typeof $.fn.dataTable == "function" &&
3042
+ typeof $.fn.dataTableExt.fnVersionCheck == "function" &&
3043
+ $.fn.dataTableExt.fnVersionCheck('1.9.0') )
3044
+ {
3045
+ $.fn.dataTableExt.aoFeatures.push( {
3046
+ "fnInit": function( oDTSettings ) {
3047
+ var oOpts = typeof oDTSettings.oInit.oTableTools != 'undefined' ?
2458
3048
  oDTSettings.oInit.oTableTools : {};
2459
-
3049
+
2460
3050
  var oTT = new TableTools( oDTSettings.oInstance, oOpts );
2461
3051
  TableTools._aInstances.push( oTT );
2462
-
3052
+
2463
3053
  return oTT.dom.container;
2464
3054
  },
2465
3055
  "cFeature": "T",
@@ -2471,6 +3061,24 @@ else
2471
3061
  alert( "Warning: TableTools 2 requires DataTables 1.9.0 or newer - www.datatables.net/download");
2472
3062
  }
2473
3063
 
3064
+
3065
+ $.fn.dataTable.TableTools = TableTools;
2474
3066
  $.fn.DataTable.TableTools = TableTools;
2475
3067
 
2476
- })(jQuery, window, document);
3068
+
3069
+ return TableTools;
3070
+ }; // /factory
3071
+
3072
+
3073
+ // Define as an AMD module if possible
3074
+ if ( typeof define === 'function' && define.amd ) {
3075
+ define( 'datatables-tabletools', ['jquery', 'datatables'], factory );
3076
+ }
3077
+ else if ( jQuery && !jQuery.fn.dataTable.TableTools ) {
3078
+ // Otherwise simply initialise as normal, stopping multiple evaluation
3079
+ factory( jQuery, jQuery.fn.dataTable );
3080
+ }
3081
+
3082
+
3083
+ })(window, document);
3084
+