jquery-datatables-rails 1.12.2 → 2.1.10.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
+