effective_datatables 2.1.20 → 2.2.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 (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
+ }));