effective_datatables 2.1.20 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -11
  3. data/app/assets/javascripts/dataTables/buttons/buttons.bootstrap.js +68 -0
  4. data/app/assets/javascripts/dataTables/buttons/buttons.colVis.js +197 -0
  5. data/app/assets/javascripts/dataTables/buttons/buttons.html5.js +828 -0
  6. data/app/assets/javascripts/dataTables/buttons/buttons.print.js +159 -0
  7. data/app/assets/javascripts/dataTables/buttons/dataTables.buttons.js +1607 -0
  8. data/app/assets/javascripts/dataTables/dataTables.colReorder.min.js +24 -24
  9. data/app/assets/javascripts/dataTables/{bootstrap/3/jquery.dataTables.bootstrap.js → jquery.dataTables.bootstrap.js} +69 -34
  10. data/app/assets/javascripts/dataTables/jquery.dataTables.min.js +164 -160
  11. data/app/assets/javascripts/dataTables/responsive/dataTables.responsive.min.js +23 -0
  12. data/app/assets/javascripts/dataTables/responsive/responsive.bootstrap.min.js +7 -0
  13. data/app/assets/javascripts/effective_datatables.js +15 -6
  14. data/app/assets/javascripts/effective_datatables/initialize.js.coffee.erb +118 -92
  15. data/app/assets/javascripts/vendor/jszip.min.js +14 -0
  16. data/app/assets/stylesheets/dataTables/buttons/buttons.bootstrap.min.css +102 -0
  17. data/app/assets/stylesheets/dataTables/buttons/buttons.dataTables.min.css +298 -0
  18. data/app/assets/stylesheets/dataTables/colReorder/colReorder.bootstrap.min.css +1 -0
  19. data/app/assets/stylesheets/dataTables/{dataTables.colReorder.min.css → colReorder/colReorder.dataTables.min.css} +0 -0
  20. data/app/assets/stylesheets/dataTables/dataTables.bootstrap.min.css +187 -0
  21. data/app/assets/stylesheets/dataTables/jquery.dataTables.min.css +24 -26
  22. data/app/assets/stylesheets/dataTables/responsive/responsive.bootstrap.min.css +1 -0
  23. data/app/assets/stylesheets/dataTables/responsive/responsive.dataTables.min.css +1 -0
  24. data/app/assets/stylesheets/effective_datatables.scss +10 -4
  25. data/app/assets/stylesheets/effective_datatables/_overrides.scss.erb +118 -103
  26. data/app/helpers/effective_datatables_helper.rb +25 -36
  27. data/app/models/effective/effective_datatable/dsl.rb +1 -0
  28. data/app/models/effective/effective_datatable/options.rb +1 -1
  29. data/app/views/effective/datatables/_datatable.html.haml +7 -20
  30. data/lib/effective_datatables/version.rb +1 -1
  31. metadata +18 -15
  32. data/app/assets/javascripts/dataTables/bootstrap/2/jquery.dataTables.bootstrap.js +0 -148
  33. data/app/assets/javascripts/dataTables/dataTables.colVis.min.js +0 -24
  34. data/app/assets/javascripts/dataTables/dataTables.fixedColumns.min.js +0 -30
  35. data/app/assets/javascripts/dataTables/dataTables.tableTools.min.js +0 -70
  36. data/app/assets/javascripts/effective_datatables.bootstrap2.js +0 -12
  37. data/app/assets/stylesheets/dataTables/bootstrap/2/jquery.dataTables.bootstrap.scss +0 -207
  38. data/app/assets/stylesheets/dataTables/bootstrap/3/jquery.dataTables.bootstrap.scss +0 -280
  39. data/app/assets/stylesheets/dataTables/dataTables.colVis.min.css +0 -1
  40. data/app/assets/stylesheets/dataTables/dataTables.fixedColumns.min.css +0 -1
  41. data/app/assets/stylesheets/dataTables/dataTables.tableTools.min.css +0 -1
  42. data/app/assets/stylesheets/effective_datatables.bootstrap2.scss +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 847c0ed1d8fc8baaa4d9b04bd05c4fabb2977b58
4
- data.tar.gz: 00f7e95ea5a7aff99706988ac4de8aba863ce59d
3
+ metadata.gz: a11a4152015f5e0e9ac464f327b5948c88e0ff1e
4
+ data.tar.gz: 0340d9dbfa87581de8316de5f4cae793d4a3f7bf
5
5
  SHA512:
6
- metadata.gz: 5ffed5c1e75cd1df2cfb446cf54b40f3373f5b0bbd1d30aea9e9eb828f99b5d8e8a904dcf74a4583d88009bfa075e38ccfe7da0cabe954e5779ba51dc5c32c94
7
- data.tar.gz: 6ed696dbfecc51a12e56b0272da8fff2ab1d2ea19cc5d761bb738dbe8b249a0c82e734395e335f4e6fa7298a41bdb2cfc6db70840364b5e5d4f7fa4ed7eff830
6
+ metadata.gz: e7f862762dc7adb0694cd5036455cdd022058a5c91aabaaeaf08baa441aa3ff7cbb23b20b395815d730b25de4008417c090febc563d41922e66877eb69f40bc8
7
+ data.tar.gz: 1c141fc85e8614b7a409ba632dc376ea369a306c03fa2b6ff94b41cccd8894667bc2527d549be13c472e569570c454bc00d887ffec95bfc0239ae7adb38a71f4
data/README.md CHANGED
@@ -6,7 +6,7 @@ Use a simple DSL in just one ruby file to implement all features
6
6
 
7
7
  Search raw database tables and ruby post-rendered results at the same time
8
8
 
9
- Packages the jQuery DataTables assets for use in a Rails 3.2.x & Rails 4.x application using Twitter Bootstrap 2 or 3
9
+ Packages the jQuery DataTables assets for use in a Rails 3.2.x & Rails 4.x application using Twitter Bootstrap 3
10
10
 
11
11
  Works with postgres, mysql, sqlite3 and arrays.
12
12
 
@@ -30,25 +30,16 @@ rails generate effective_datatables:install
30
30
 
31
31
  The generator will install an initializer which describes all configuration options.
32
32
 
33
-
34
33
  Require the javascript on the asset pipeline by adding the following to your application.js:
35
34
 
36
35
  ```ruby
37
- # For use with Bootstrap3 (which is not included in this gem):
38
36
  //= require effective_datatables
39
-
40
- # For use with Bootstrap2 (which is not includled in this gem):
41
- //= require effective_datatables.bootstrap2
42
37
  ```
43
38
 
44
39
  Require the stylesheet on the asset pipeline by adding the following to your application.css:
45
40
 
46
41
  ```ruby
47
- # For use with Bootstrap3 (which is not included in this gem):
48
42
  *= require effective_datatables
49
-
50
- # For use with Bootstrap2 (which is not not included in this gem):
51
- *= require effective_datatables.bootstrap2
52
43
  ```
53
44
 
54
45
  ## Usage
@@ -108,7 +99,6 @@ Here we just render the datatable:
108
99
  <%= render_datatable(@datatable) %>
109
100
  ```
110
101
 
111
-
112
102
  ## How It Works
113
103
 
114
104
  When the jQuery DataTable is first initialized on the front-end, it makes an AJAX request back to the server asking for data.
@@ -0,0 +1,68 @@
1
+ /*! Bootstrap integration for DataTables' Buttons
2
+ * ©2015 SpryMedia Ltd - datatables.net/license
3
+ */
4
+
5
+ (function( factory ){
6
+ if ( typeof define === 'function' && define.amd ) {
7
+ // AMD
8
+ define( ['jquery', 'datatables.net-bs', 'datatables.net-buttons'], function ( $ ) {
9
+ return factory( $, window, document );
10
+ } );
11
+ }
12
+ else if ( typeof exports === 'object' ) {
13
+ // CommonJS
14
+ module.exports = function (root, $) {
15
+ if ( ! root ) {
16
+ root = window;
17
+ }
18
+
19
+ if ( ! $ || ! $.fn.dataTable ) {
20
+ $ = require('datatables.net-bs')(root, $).$;
21
+ }
22
+
23
+ if ( ! $.fn.dataTable.Buttons ) {
24
+ require('datatables.net-buttons')(root, $);
25
+ }
26
+
27
+ return factory( $, root, root.document );
28
+ };
29
+ }
30
+ else {
31
+ // Browser
32
+ factory( jQuery, window, document );
33
+ }
34
+ }(function( $, window, document, undefined ) {
35
+ 'use strict';
36
+ var DataTable = $.fn.dataTable;
37
+
38
+
39
+ $.extend( true, DataTable.Buttons.defaults, {
40
+ dom: {
41
+ container: {
42
+ className: 'dt-buttons btn-group'
43
+ },
44
+ button: {
45
+ className: 'btn btn-default'
46
+ },
47
+ collection: {
48
+ tag: 'ul',
49
+ className: 'dt-button-collection dropdown-menu',
50
+ button: {
51
+ tag: 'li',
52
+ className: 'dt-button'
53
+ },
54
+ buttonLiner: {
55
+ tag: 'a',
56
+ className: ''
57
+ }
58
+ }
59
+ }
60
+ } );
61
+
62
+ DataTable.ext.buttons.collection.text = function ( dt ) {
63
+ return dt.i18n('buttons.collection', 'Collection <span class="caret"/>');
64
+ };
65
+
66
+
67
+ return DataTable.Buttons;
68
+ }));
@@ -0,0 +1,197 @@
1
+ /*!
2
+ * Column visibility buttons for Buttons and DataTables.
3
+ * 2015 SpryMedia Ltd - datatables.net/license
4
+ */
5
+
6
+ (function( factory ){
7
+ if ( typeof define === 'function' && define.amd ) {
8
+ // AMD
9
+ define( ['jquery', 'datatables.net', 'datatables.net-buttons'], function ( $ ) {
10
+ return factory( $, window, document );
11
+ } );
12
+ }
13
+ else if ( typeof exports === 'object' ) {
14
+ // CommonJS
15
+ module.exports = function (root, $) {
16
+ if ( ! root ) {
17
+ root = window;
18
+ }
19
+
20
+ if ( ! $ || ! $.fn.dataTable ) {
21
+ $ = require('datatables.net')(root, $).$;
22
+ }
23
+
24
+ if ( ! $.fn.dataTable.Buttons ) {
25
+ require('datatables.net-buttons')(root, $);
26
+ }
27
+
28
+ return factory( $, root, root.document );
29
+ };
30
+ }
31
+ else {
32
+ // Browser
33
+ factory( jQuery, window, document );
34
+ }
35
+ }(function( $, window, document, undefined ) {
36
+ 'use strict';
37
+ var DataTable = $.fn.dataTable;
38
+
39
+
40
+ $.extend( DataTable.ext.buttons, {
41
+ // A collection of column visibility buttons
42
+ colvis: function ( dt, conf ) {
43
+ return {
44
+ extend: 'collection',
45
+ text: function ( dt ) {
46
+ return dt.i18n( 'buttons.colvis', 'Column visibility' );
47
+ },
48
+ className: 'buttons-colvis',
49
+ buttons: [ {
50
+ extend: 'columnsToggle',
51
+ columns: conf.columns
52
+ } ]
53
+ };
54
+ },
55
+
56
+ // Selected columns with individual buttons - toggle column visibility
57
+ columnsToggle: function ( dt, conf ) {
58
+ var columns = dt.columns( conf.columns ).indexes().map( function ( idx ) {
59
+ return {
60
+ extend: 'columnToggle',
61
+ columns: idx
62
+ };
63
+ } ).toArray();
64
+
65
+ return columns;
66
+ },
67
+
68
+ // Single button to toggle column visibility
69
+ columnToggle: function ( dt, conf ) {
70
+ return {
71
+ extend: 'columnVisibility',
72
+ columns: conf.columns
73
+ };
74
+ },
75
+
76
+ // Selected columns with individual buttons - set column visibility
77
+ columnsVisibility: function ( dt, conf ) {
78
+ var columns = dt.columns( conf.columns ).indexes().map( function ( idx ) {
79
+ return {
80
+ extend: 'columnVisibility',
81
+ columns: idx,
82
+ visibility: conf.visibility
83
+ };
84
+ } ).toArray();
85
+
86
+ return columns;
87
+ },
88
+
89
+ // Single button to set column visibility
90
+ columnVisibility: {
91
+ columns: undefined, // column selector
92
+ text: function ( dt, button, conf ) {
93
+ return conf._columnText( dt, conf.columns );
94
+ },
95
+ className: 'buttons-columnVisibility',
96
+ action: function ( e, dt, button, conf ) {
97
+ var col = dt.columns( conf.columns );
98
+ var curr = col.visible();
99
+
100
+ col.visible( conf.visibility !== undefined ?
101
+ conf.visibility :
102
+ ! (curr.length ? curr[0] : false )
103
+ );
104
+ },
105
+ init: function ( dt, button, conf ) {
106
+ var that = this;
107
+ var col = dt.column( conf.columns );
108
+
109
+ dt
110
+ .on( 'column-visibility.dt'+conf.namespace, function (e, settings, column, state) {
111
+ if ( column === conf.columns ) {
112
+ that.active( state );
113
+ }
114
+ } )
115
+ .on( 'column-reorder.dt'+conf.namespace, function (e, settings, details) {
116
+ // Don't rename buttons based on column name if the button
117
+ // controls more than one column!
118
+ if ( dt.columns( conf.columns ).count() !== 1 ) {
119
+ return;
120
+ }
121
+
122
+ if ( typeof conf.columns === 'number' ) {
123
+ conf.columns = details.mapping[ conf.columns ];
124
+ }
125
+
126
+ var col = dt.column( conf.columns );
127
+
128
+ that.text( conf._columnText( dt, conf.columns ) );
129
+ that.active( col.visible() );
130
+ } );
131
+
132
+ this.active( col.visible() );
133
+ },
134
+ destroy: function ( dt, button, conf ) {
135
+ dt
136
+ .off( 'column-visibility.dt'+conf.namespace )
137
+ .off( 'column-reorder.dt'+conf.namespace );
138
+ },
139
+
140
+ _columnText: function ( dt, col ) {
141
+ // Use DataTables' internal data structure until this is presented
142
+ // is a public API. The other option is to use
143
+ // `$( column(col).node() ).text()` but the node might not have been
144
+ // populated when Buttons is constructed.
145
+ var idx = dt.column( col ).index();
146
+ return dt.settings()[0].aoColumns[ idx ].sTitle
147
+ .replace(/\n/g," ") // remove new lines
148
+ .replace( /<.*?>/g, "" ) // strip HTML
149
+ .replace(/^\s+|\s+$/g,""); // trim
150
+ }
151
+ },
152
+
153
+
154
+ colvisRestore: {
155
+ className: 'buttons-colvisRestore',
156
+
157
+ text: function ( dt ) {
158
+ return dt.i18n( 'buttons.colvisRestore', 'Restore visibility' );
159
+ },
160
+
161
+ init: function ( dt, button, conf ) {
162
+ conf._visOriginal = dt.columns().indexes().map( function ( idx ) {
163
+ return dt.column( idx ).visible();
164
+ } ).toArray();
165
+ },
166
+
167
+ action: function ( e, dt, button, conf ) {
168
+ dt.columns().every( function ( i ) {
169
+ // Take into account that ColReorder might have disrupted our
170
+ // indexes
171
+ var idx = dt.colReorder && dt.colReorder.transpose ?
172
+ dt.colReorder.transpose( i, 'toOriginal' ) :
173
+ i;
174
+
175
+ this.visible( conf._visOriginal[ idx ] );
176
+ } );
177
+ }
178
+ },
179
+
180
+
181
+ colvisGroup: {
182
+ className: 'buttons-colvisGroup',
183
+
184
+ action: function ( e, dt, button, conf ) {
185
+ dt.columns( conf.show ).visible( true );
186
+ dt.columns( conf.hide ).visible( false );
187
+ },
188
+
189
+ show: [],
190
+
191
+ hide: []
192
+ }
193
+ } );
194
+
195
+
196
+ return DataTable.Buttons;
197
+ }));
@@ -0,0 +1,828 @@
1
+ /*!
2
+ * HTML5 export buttons for Buttons and DataTables.
3
+ * 2015 SpryMedia Ltd - datatables.net/license
4
+ *
5
+ * FileSaver.js (2015-05-07.2) - MIT license
6
+ * Copyright © 2015 Eli Grey - http://eligrey.com
7
+ */
8
+
9
+ (function( factory ){
10
+ if ( typeof define === 'function' && define.amd ) {
11
+ // AMD
12
+ define( ['jquery', 'datatables.net', 'datatables.net-buttons'], function ( $ ) {
13
+ return factory( $, window, document );
14
+ } );
15
+ }
16
+ else if ( typeof exports === 'object' ) {
17
+ // CommonJS
18
+ module.exports = function (root, $) {
19
+ if ( ! root ) {
20
+ root = window;
21
+ }
22
+
23
+ if ( ! $ || ! $.fn.dataTable ) {
24
+ $ = require('datatables.net')(root, $).$;
25
+ }
26
+
27
+ if ( ! $.fn.dataTable.Buttons ) {
28
+ require('datatables.net-buttons')(root, $);
29
+ }
30
+
31
+ return factory( $, root, root.document );
32
+ };
33
+ }
34
+ else {
35
+ // Browser
36
+ factory( jQuery, window, document );
37
+ }
38
+ }(function( $, window, document, undefined ) {
39
+ 'use strict';
40
+ var DataTable = $.fn.dataTable;
41
+
42
+
43
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
44
+ * FileSaver.js dependency
45
+ */
46
+
47
+ /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
48
+
49
+ var _saveAs = (function(view) {
50
+ // IE <10 is explicitly unsupported
51
+ if (typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {
52
+ return;
53
+ }
54
+ var
55
+ doc = view.document
56
+ // only get URL when necessary in case Blob.js hasn't overridden it yet
57
+ , get_URL = function() {
58
+ return view.URL || view.webkitURL || view;
59
+ }
60
+ , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
61
+ , can_use_save_link = "download" in save_link
62
+ , click = function(node) {
63
+ var event = doc.createEvent("MouseEvents");
64
+ event.initMouseEvent(
65
+ "click", true, false, view, 0, 0, 0, 0, 0
66
+ , false, false, false, false, 0, null
67
+ );
68
+ node.dispatchEvent(event);
69
+ }
70
+ , webkit_req_fs = view.webkitRequestFileSystem
71
+ , req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
72
+ , throw_outside = function(ex) {
73
+ (view.setImmediate || view.setTimeout)(function() {
74
+ throw ex;
75
+ }, 0);
76
+ }
77
+ , force_saveable_type = "application/octet-stream"
78
+ , fs_min_size = 0
79
+ // See https://code.google.com/p/chromium/issues/detail?id=375297#c7 and
80
+ // https://github.com/eligrey/FileSaver.js/commit/485930a#commitcomment-8768047
81
+ // for the reasoning behind the timeout and revocation flow
82
+ , arbitrary_revoke_timeout = 500 // in ms
83
+ , revoke = function(file) {
84
+ var revoker = function() {
85
+ if (typeof file === "string") { // file is an object URL
86
+ get_URL().revokeObjectURL(file);
87
+ } else { // file is a File
88
+ file.remove();
89
+ }
90
+ };
91
+ if (view.chrome) {
92
+ revoker();
93
+ } else {
94
+ setTimeout(revoker, arbitrary_revoke_timeout);
95
+ }
96
+ }
97
+ , dispatch = function(filesaver, event_types, event) {
98
+ event_types = [].concat(event_types);
99
+ var i = event_types.length;
100
+ while (i--) {
101
+ var listener = filesaver["on" + event_types[i]];
102
+ if (typeof listener === "function") {
103
+ try {
104
+ listener.call(filesaver, event || filesaver);
105
+ } catch (ex) {
106
+ throw_outside(ex);
107
+ }
108
+ }
109
+ }
110
+ }
111
+ , auto_bom = function(blob) {
112
+ // prepend BOM for UTF-8 XML and text/* types (including HTML)
113
+ if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
114
+ return new Blob(["\ufeff", blob], {type: blob.type});
115
+ }
116
+ return blob;
117
+ }
118
+ , FileSaver = function(blob, name) {
119
+ blob = auto_bom(blob);
120
+ // First try a.download, then web filesystem, then object URLs
121
+ var
122
+ filesaver = this
123
+ , type = blob.type
124
+ , blob_changed = false
125
+ , object_url
126
+ , target_view
127
+ , dispatch_all = function() {
128
+ dispatch(filesaver, "writestart progress write writeend".split(" "));
129
+ }
130
+ // on any filesys errors revert to saving with object URLs
131
+ , fs_error = function() {
132
+ // don't create more object URLs than needed
133
+ if (blob_changed || !object_url) {
134
+ object_url = get_URL().createObjectURL(blob);
135
+ }
136
+ if (target_view) {
137
+ target_view.location.href = object_url;
138
+ } else {
139
+ var new_tab = view.open(object_url, "_blank");
140
+ if (new_tab === undefined && typeof safari !== "undefined") {
141
+ //Apple do not allow window.open, see http://bit.ly/1kZffRI
142
+ view.location.href = object_url;
143
+ }
144
+ }
145
+ filesaver.readyState = filesaver.DONE;
146
+ dispatch_all();
147
+ revoke(object_url);
148
+ }
149
+ , abortable = function(func) {
150
+ return function() {
151
+ if (filesaver.readyState !== filesaver.DONE) {
152
+ return func.apply(this, arguments);
153
+ }
154
+ };
155
+ }
156
+ , create_if_not_found = {create: true, exclusive: false}
157
+ , slice
158
+ ;
159
+ filesaver.readyState = filesaver.INIT;
160
+ if (!name) {
161
+ name = "download";
162
+ }
163
+ if (can_use_save_link) {
164
+ object_url = get_URL().createObjectURL(blob);
165
+ save_link.href = object_url;
166
+ save_link.download = name;
167
+ click(save_link);
168
+ filesaver.readyState = filesaver.DONE;
169
+ dispatch_all();
170
+ revoke(object_url);
171
+ return;
172
+ }
173
+ // Object and web filesystem URLs have a problem saving in Google Chrome when
174
+ // viewed in a tab, so I force save with application/octet-stream
175
+ // http://code.google.com/p/chromium/issues/detail?id=91158
176
+ // Update: Google errantly closed 91158, I submitted it again:
177
+ // https://code.google.com/p/chromium/issues/detail?id=389642
178
+ if (view.chrome && type && type !== force_saveable_type) {
179
+ slice = blob.slice || blob.webkitSlice;
180
+ blob = slice.call(blob, 0, blob.size, force_saveable_type);
181
+ blob_changed = true;
182
+ }
183
+ // Since I can't be sure that the guessed media type will trigger a download
184
+ // in WebKit, I append .download to the filename.
185
+ // https://bugs.webkit.org/show_bug.cgi?id=65440
186
+ if (webkit_req_fs && name !== "download") {
187
+ name += ".download";
188
+ }
189
+ if (type === force_saveable_type || webkit_req_fs) {
190
+ target_view = view;
191
+ }
192
+ if (!req_fs) {
193
+ fs_error();
194
+ return;
195
+ }
196
+ fs_min_size += blob.size;
197
+ req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
198
+ fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
199
+ var save = function() {
200
+ dir.getFile(name, create_if_not_found, abortable(function(file) {
201
+ file.createWriter(abortable(function(writer) {
202
+ writer.onwriteend = function(event) {
203
+ target_view.location.href = file.toURL();
204
+ filesaver.readyState = filesaver.DONE;
205
+ dispatch(filesaver, "writeend", event);
206
+ revoke(file);
207
+ };
208
+ writer.onerror = function() {
209
+ var error = writer.error;
210
+ if (error.code !== error.ABORT_ERR) {
211
+ fs_error();
212
+ }
213
+ };
214
+ "writestart progress write abort".split(" ").forEach(function(event) {
215
+ writer["on" + event] = filesaver["on" + event];
216
+ });
217
+ writer.write(blob);
218
+ filesaver.abort = function() {
219
+ writer.abort();
220
+ filesaver.readyState = filesaver.DONE;
221
+ };
222
+ filesaver.readyState = filesaver.WRITING;
223
+ }), fs_error);
224
+ }), fs_error);
225
+ };
226
+ dir.getFile(name, {create: false}, abortable(function(file) {
227
+ // delete file if it already exists
228
+ file.remove();
229
+ save();
230
+ }), abortable(function(ex) {
231
+ if (ex.code === ex.NOT_FOUND_ERR) {
232
+ save();
233
+ } else {
234
+ fs_error();
235
+ }
236
+ }));
237
+ }), fs_error);
238
+ }), fs_error);
239
+ }
240
+ , FS_proto = FileSaver.prototype
241
+ , saveAs = function(blob, name) {
242
+ return new FileSaver(blob, name);
243
+ }
244
+ ;
245
+ // IE 10+ (native saveAs)
246
+ if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
247
+ return function(blob, name) {
248
+ return navigator.msSaveOrOpenBlob(auto_bom(blob), name);
249
+ };
250
+ }
251
+
252
+ FS_proto.abort = function() {
253
+ var filesaver = this;
254
+ filesaver.readyState = filesaver.DONE;
255
+ dispatch(filesaver, "abort");
256
+ };
257
+ FS_proto.readyState = FS_proto.INIT = 0;
258
+ FS_proto.WRITING = 1;
259
+ FS_proto.DONE = 2;
260
+
261
+ FS_proto.error =
262
+ FS_proto.onwritestart =
263
+ FS_proto.onprogress =
264
+ FS_proto.onwrite =
265
+ FS_proto.onabort =
266
+ FS_proto.onerror =
267
+ FS_proto.onwriteend =
268
+ null;
269
+
270
+ return saveAs;
271
+ }(window));
272
+
273
+
274
+
275
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
276
+ * Local (private) functions
277
+ */
278
+
279
+ /**
280
+ * Get the file name for an exported file.
281
+ *
282
+ * @param {object} config Button configuration
283
+ * @param {boolean} incExtension Include the file name extension
284
+ */
285
+ var _filename = function ( config, incExtension )
286
+ {
287
+ // Backwards compatibility
288
+ var filename = config.filename === '*' && config.title !== '*' && config.title !== undefined ?
289
+ config.title :
290
+ config.filename;
291
+
292
+ if ( filename.indexOf( '*' ) !== -1 ) {
293
+ filename = filename.replace( '*', $('title').text() );
294
+ }
295
+
296
+ // Strip characters which the OS will object to
297
+ filename = filename.replace(/[^a-zA-Z0-9_\u00A1-\uFFFF\.,\-_ !\(\)]/g, "");
298
+
299
+ return incExtension === undefined || incExtension === true ?
300
+ filename+config.extension :
301
+ filename;
302
+ };
303
+
304
+ /**
305
+ * Get the title for an exported file.
306
+ *
307
+ * @param {object} config Button configuration
308
+ */
309
+ var _title = function ( config )
310
+ {
311
+ var title = config.title;
312
+
313
+ return title.indexOf( '*' ) !== -1 ?
314
+ title.replace( '*', $('title').text() ) :
315
+ title;
316
+ };
317
+
318
+ /**
319
+ * Get the newline character(s)
320
+ *
321
+ * @param {object} config Button configuration
322
+ * @return {string} Newline character
323
+ */
324
+ var _newLine = function ( config )
325
+ {
326
+ return config.newline ?
327
+ config.newline :
328
+ navigator.userAgent.match(/Windows/) ?
329
+ '\r\n' :
330
+ '\n';
331
+ };
332
+
333
+ /**
334
+ * Combine the data from the `buttons.exportData` method into a string that
335
+ * will be used in the export file.
336
+ *
337
+ * @param {DataTable.Api} dt DataTables API instance
338
+ * @param {object} config Button configuration
339
+ * @return {object} The data to export
340
+ */
341
+ var _exportData = function ( dt, config )
342
+ {
343
+ var newLine = _newLine( config );
344
+ var data = dt.buttons.exportData( config.exportOptions );
345
+ var boundary = config.fieldBoundary;
346
+ var separator = config.fieldSeparator;
347
+ var reBoundary = new RegExp( boundary, 'g' );
348
+ var escapeChar = config.escapeChar !== undefined ?
349
+ config.escapeChar :
350
+ '\\';
351
+ var join = function ( a ) {
352
+ var s = '';
353
+
354
+ // If there is a field boundary, then we might need to escape it in
355
+ // the source data
356
+ for ( var i=0, ien=a.length ; i<ien ; i++ ) {
357
+ if ( i > 0 ) {
358
+ s += separator;
359
+ }
360
+
361
+ s += boundary ?
362
+ boundary + ('' + a[i]).replace( reBoundary, escapeChar+boundary ) + boundary :
363
+ a[i];
364
+ }
365
+
366
+ return s;
367
+ };
368
+
369
+ var header = config.header ? join( data.header )+newLine : '';
370
+ var footer = config.footer ? newLine+join( data.footer ) : '';
371
+ var body = [];
372
+
373
+ for ( var i=0, ien=data.body.length ; i<ien ; i++ ) {
374
+ body.push( join( data.body[i] ) );
375
+ }
376
+
377
+ return {
378
+ str: header + body.join( newLine ) + footer,
379
+ rows: body.length
380
+ };
381
+ };
382
+
383
+ /**
384
+ * Safari's data: support for creating and downloading files is really poor, so
385
+ * various options need to be disabled in it. See
386
+ * https://bugs.webkit.org/show_bug.cgi?id=102914
387
+ *
388
+ * @return {Boolean} `true` if Safari
389
+ */
390
+ var _isSafari = function ()
391
+ {
392
+ return navigator.userAgent.indexOf('Safari') !== -1 &&
393
+ navigator.userAgent.indexOf('Chrome') === -1 &&
394
+ navigator.userAgent.indexOf('Opera') === -1;
395
+ };
396
+
397
+
398
+ // Excel - Pre-defined strings to build a minimal XLSX file
399
+ var excelStrings = {
400
+ "_rels/.rels": '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\
401
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">\
402
+ <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>\
403
+ </Relationships>',
404
+
405
+ "xl/_rels/workbook.xml.rels": '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\
406
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">\
407
+ <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>\
408
+ </Relationships>',
409
+
410
+ "[Content_Types].xml": '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\
411
+ <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">\
412
+ <Default Extension="xml" ContentType="application/xml"/>\
413
+ <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>\
414
+ <Default Extension="jpeg" ContentType="image/jpeg"/>\
415
+ <Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>\
416
+ <Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>\
417
+ </Types>',
418
+
419
+ "xl/workbook.xml": '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\
420
+ <workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">\
421
+ <fileVersion appName="xl" lastEdited="5" lowestEdited="5" rupBuild="24816"/>\
422
+ <workbookPr showInkAnnotation="0" autoCompressPictures="0"/>\
423
+ <bookViews>\
424
+ <workbookView xWindow="0" yWindow="0" windowWidth="25600" windowHeight="19020" tabRatio="500"/>\
425
+ </bookViews>\
426
+ <sheets>\
427
+ <sheet name="Sheet1" sheetId="1" r:id="rId1"/>\
428
+ </sheets>\
429
+ </workbook>',
430
+
431
+ "xl/worksheets/sheet1.xml": '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\
432
+ <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">\
433
+ <sheetData>\
434
+ __DATA__\
435
+ </sheetData>\
436
+ </worksheet>'
437
+ };
438
+
439
+
440
+
441
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
442
+ * Buttons
443
+ */
444
+
445
+ //
446
+ // Copy to clipboard
447
+ //
448
+ DataTable.ext.buttons.copyHtml5 = {
449
+ className: 'buttons-copy buttons-html5',
450
+
451
+ text: function ( dt ) {
452
+ return dt.i18n( 'buttons.copy', 'Copy' );
453
+ },
454
+
455
+ action: function ( e, dt, button, config ) {
456
+ var exportData = _exportData( dt, config );
457
+ var output = exportData.str;
458
+ var hiddenDiv = $('<div/>')
459
+ .css( {
460
+ height: 1,
461
+ width: 1,
462
+ overflow: 'hidden',
463
+ position: 'fixed',
464
+ top: 0,
465
+ left: 0
466
+ } );
467
+ var textarea = $('<textarea readonly/>')
468
+ .val( output )
469
+ .appendTo( hiddenDiv );
470
+
471
+ // For browsers that support the copy execCommand, try to use it
472
+ if ( document.queryCommandSupported('copy') ) {
473
+ hiddenDiv.appendTo( 'body' );
474
+ textarea[0].focus();
475
+ textarea[0].select();
476
+
477
+ try {
478
+ document.execCommand( 'copy' );
479
+ hiddenDiv.remove();
480
+
481
+ dt.buttons.info(
482
+ dt.i18n( 'buttons.copyTitle', 'Copy to clipboard' ),
483
+ dt.i18n( 'buttons.copySuccess', {
484
+ 1: "Copied one row to clipboard",
485
+ _: "Copied %d rows to clipboard"
486
+ }, exportData.rows ),
487
+ 2000
488
+ );
489
+
490
+ return;
491
+ }
492
+ catch (t) {}
493
+ }
494
+
495
+ // Otherwise we show the text box and instruct the user to use it
496
+ var message = $('<span>'+dt.i18n( 'buttons.copyKeys',
497
+ 'Press <i>ctrl</i> or <i>\u2318</i> + <i>C</i> to copy the table data<br>to your system clipboard.<br><br>'+
498
+ 'To cancel, click this message or press escape.' )+'</span>'
499
+ )
500
+ .append( hiddenDiv );
501
+
502
+ dt.buttons.info( dt.i18n( 'buttons.copyTitle', 'Copy to clipboard' ), message, 0 );
503
+
504
+ // Select the text so when the user activates their system clipboard
505
+ // it will copy that text
506
+ textarea[0].focus();
507
+ textarea[0].select();
508
+
509
+ // Event to hide the message when the user is done
510
+ var container = $(message).closest('.dt-button-info');
511
+ var close = function () {
512
+ container.off( 'click.buttons-copy' );
513
+ $(document).off( '.buttons-copy' );
514
+ dt.buttons.info( false );
515
+ };
516
+
517
+ container.on( 'click.buttons-copy', close );
518
+ $(document)
519
+ .on( 'keydown.buttons-copy', function (e) {
520
+ if ( e.keyCode === 27 ) { // esc
521
+ close();
522
+ }
523
+ } )
524
+ .on( 'copy.buttons-copy cut.buttons-copy', function () {
525
+ close();
526
+ } );
527
+ },
528
+
529
+ exportOptions: {},
530
+
531
+ fieldSeparator: '\t',
532
+
533
+ fieldBoundary: '',
534
+
535
+ header: true,
536
+
537
+ footer: false
538
+ };
539
+
540
+ //
541
+ // CSV export
542
+ //
543
+ DataTable.ext.buttons.csvHtml5 = {
544
+ className: 'buttons-csv buttons-html5',
545
+
546
+ available: function () {
547
+ return window.FileReader !== undefined && window.Blob;
548
+ },
549
+
550
+ text: function ( dt ) {
551
+ return dt.i18n( 'buttons.csv', 'CSV' );
552
+ },
553
+
554
+ action: function ( e, dt, button, config ) {
555
+ // Set the text
556
+ var newLine = _newLine( config );
557
+ var output = _exportData( dt, config ).str;
558
+ var charset = config.charset;
559
+
560
+ if ( charset !== false ) {
561
+ if ( ! charset ) {
562
+ charset = document.characterSet || document.charset;
563
+ }
564
+
565
+ if ( charset ) {
566
+ charset = ';charset='+charset;
567
+ }
568
+ }
569
+ else {
570
+ charset = '';
571
+ }
572
+
573
+ _saveAs(
574
+ new Blob( [output], {type: 'text/csv'+charset} ),
575
+ _filename( config )
576
+ );
577
+ },
578
+
579
+ filename: '*',
580
+
581
+ extension: '.csv',
582
+
583
+ exportOptions: {},
584
+
585
+ fieldSeparator: ',',
586
+
587
+ fieldBoundary: '"',
588
+
589
+ escapeChar: '"',
590
+
591
+ charset: null,
592
+
593
+ header: true,
594
+
595
+ footer: false
596
+ };
597
+
598
+ //
599
+ // Excel (xlsx) export
600
+ //
601
+ DataTable.ext.buttons.excelHtml5 = {
602
+ className: 'buttons-excel buttons-html5',
603
+
604
+ available: function () {
605
+ return window.FileReader !== undefined && window.JSZip !== undefined && ! _isSafari();
606
+ },
607
+
608
+ text: function ( dt ) {
609
+ return dt.i18n( 'buttons.excel', 'Excel' );
610
+ },
611
+
612
+ action: function ( e, dt, button, config ) {
613
+ // Set the text
614
+ var xml = '';
615
+ var data = dt.buttons.exportData( config.exportOptions );
616
+ var addRow = function ( row ) {
617
+ var cells = [];
618
+
619
+ for ( var i=0, ien=row.length ; i<ien ; i++ ) {
620
+ if ( row[i] === null || row[i] === undefined ) {
621
+ row[i] = '';
622
+ }
623
+
624
+ // Don't match numbers with leading zeros or a negative anywhere
625
+ // but the start
626
+ cells.push( typeof row[i] === 'number' || (row[i].match && row[i].match(/^-?[0-9\.]+$/) && row[i].charAt(0) !== '0') ?
627
+ '<c t="n"><v>'+row[i]+'</v></c>' :
628
+ '<c t="inlineStr"><is><t>'+(
629
+ ! row[i].replace ?
630
+ row[i] :
631
+ row[i]
632
+ .replace(/&(?!amp;)/g, '&amp;')
633
+ .replace(/[\x00-\x1F\x7F-\x9F]/g, ''))+ // remove control characters
634
+ '</t></is></c>' // they are not valid in XML
635
+ );
636
+ }
637
+
638
+ return '<row>'+cells.join('')+'</row>';
639
+ };
640
+
641
+ if ( config.header ) {
642
+ xml += addRow( data.header );
643
+ }
644
+
645
+ for ( var i=0, ien=data.body.length ; i<ien ; i++ ) {
646
+ xml += addRow( data.body[i] );
647
+ }
648
+
649
+ if ( config.footer ) {
650
+ xml += addRow( data.footer );
651
+ }
652
+
653
+ var zip = new window.JSZip();
654
+ var _rels = zip.folder("_rels");
655
+ var xl = zip.folder("xl");
656
+ var xl_rels = zip.folder("xl/_rels");
657
+ var xl_worksheets = zip.folder("xl/worksheets");
658
+
659
+ zip.file( '[Content_Types].xml', excelStrings['[Content_Types].xml'] );
660
+ _rels.file( '.rels', excelStrings['_rels/.rels'] );
661
+ xl.file( 'workbook.xml', excelStrings['xl/workbook.xml'] );
662
+ xl_rels.file( 'workbook.xml.rels', excelStrings['xl/_rels/workbook.xml.rels'] );
663
+ xl_worksheets.file( 'sheet1.xml', excelStrings['xl/worksheets/sheet1.xml'].replace( '__DATA__', xml ) );
664
+
665
+ _saveAs(
666
+ zip.generate( {type:"blob"} ),
667
+ _filename( config )
668
+ );
669
+ },
670
+
671
+ filename: '*',
672
+
673
+ extension: '.xlsx',
674
+
675
+ exportOptions: {},
676
+
677
+ header: true,
678
+
679
+ footer: false
680
+ };
681
+
682
+ //
683
+ // PDF export - using pdfMake - http://pdfmake.org
684
+ //
685
+ DataTable.ext.buttons.pdfHtml5 = {
686
+ className: 'buttons-pdf buttons-html5',
687
+
688
+ available: function () {
689
+ return window.FileReader !== undefined && window.pdfMake;
690
+ },
691
+
692
+ text: function ( dt ) {
693
+ return dt.i18n( 'buttons.pdf', 'PDF' );
694
+ },
695
+
696
+ action: function ( e, dt, button, config ) {
697
+ var newLine = _newLine( config );
698
+ var data = dt.buttons.exportData( config.exportOptions );
699
+ var rows = [];
700
+
701
+ if ( config.header ) {
702
+ rows.push( $.map( data.header, function ( d ) {
703
+ return {
704
+ text: typeof d === 'string' ? d : d+'',
705
+ style: 'tableHeader'
706
+ };
707
+ } ) );
708
+ }
709
+
710
+ for ( var i=0, ien=data.body.length ; i<ien ; i++ ) {
711
+ rows.push( $.map( data.body[i], function ( d ) {
712
+ return {
713
+ text: typeof d === 'string' ? d : d+'',
714
+ style: i % 2 ? 'tableBodyEven' : 'tableBodyOdd'
715
+ };
716
+ } ) );
717
+ }
718
+
719
+ if ( config.footer ) {
720
+ rows.push( $.map( data.footer, function ( d ) {
721
+ return {
722
+ text: typeof d === 'string' ? d : d+'',
723
+ style: 'tableFooter'
724
+ };
725
+ } ) );
726
+ }
727
+
728
+ var doc = {
729
+ pageSize: config.pageSize,
730
+ pageOrientation: config.orientation,
731
+ content: [
732
+ {
733
+ table: {
734
+ headerRows: 1,
735
+ body: rows
736
+ },
737
+ layout: 'noBorders'
738
+ }
739
+ ],
740
+ styles: {
741
+ tableHeader: {
742
+ bold: true,
743
+ fontSize: 11,
744
+ color: 'white',
745
+ fillColor: '#2d4154',
746
+ alignment: 'center'
747
+ },
748
+ tableBodyEven: {},
749
+ tableBodyOdd: {
750
+ fillColor: '#f3f3f3'
751
+ },
752
+ tableFooter: {
753
+ bold: true,
754
+ fontSize: 11,
755
+ color: 'white',
756
+ fillColor: '#2d4154'
757
+ },
758
+ title: {
759
+ alignment: 'center',
760
+ fontSize: 15
761
+ },
762
+ message: {}
763
+ },
764
+ defaultStyle: {
765
+ fontSize: 10
766
+ }
767
+ };
768
+
769
+ if ( config.message ) {
770
+ doc.content.unshift( {
771
+ text: config.message,
772
+ style: 'message',
773
+ margin: [ 0, 0, 0, 12 ]
774
+ } );
775
+ }
776
+
777
+ if ( config.title ) {
778
+ doc.content.unshift( {
779
+ text: _title( config, false ),
780
+ style: 'title',
781
+ margin: [ 0, 0, 0, 12 ]
782
+ } );
783
+ }
784
+
785
+ if ( config.customize ) {
786
+ config.customize( doc );
787
+ }
788
+
789
+ var pdf = window.pdfMake.createPdf( doc );
790
+
791
+ if ( config.download === 'open' && ! _isSafari() ) {
792
+ pdf.open();
793
+ }
794
+ else {
795
+ pdf.getBuffer( function (buffer) {
796
+ var blob = new Blob( [buffer], {type:'application/pdf'} );
797
+
798
+ _saveAs( blob, _filename( config ) );
799
+ } );
800
+ }
801
+ },
802
+
803
+ title: '*',
804
+
805
+ filename: '*',
806
+
807
+ extension: '.pdf',
808
+
809
+ exportOptions: {},
810
+
811
+ orientation: 'portrait',
812
+
813
+ pageSize: 'A4',
814
+
815
+ header: true,
816
+
817
+ footer: false,
818
+
819
+ message: null,
820
+
821
+ customize: null,
822
+
823
+ download: 'download'
824
+ };
825
+
826
+
827
+ return DataTable.Buttons;
828
+ }));