effective_datatables 2.6.19 → 2.6.20

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3bf1747d87d53b3fe01660cbecb432ee5b81b36c
4
- data.tar.gz: 07eaf935c9b534fc5afb7305da49adf0afc69c94
3
+ metadata.gz: 46fe407f06c151568668a2aa211c442393d9ecf8
4
+ data.tar.gz: 460205e93e92b89fec4827914b9c393de5d589dd
5
5
  SHA512:
6
- metadata.gz: 0f9cf77d9bf00bf8c9d98490bc06c1cf0ffc3a24ca1ca3c1c0a0c857034ce401fd99ede96cfc4d89a576b8749de0880f51423159ad135f1bad8cb12237527eb1
7
- data.tar.gz: 64e37b937a753df4949a281152962330ab1a158d693307eea0f389ca2eac22032f50a8d37ba1f3f130e160e2d42637b8995b69667bf0dadcca5df5d9505e8c91
6
+ metadata.gz: d3b1d6bcc145535b55e1428f1c75a23f78f0ac6d0570cddd429efbedab459d611df8d98a45326ffab54d76817d93e1d3c18ce1001bb4d6fedb4110200e5b5015
7
+ data.tar.gz: 83da2377c96fe023f26b77e28186767a4de926e16b80a03903ec1451c21648f497de8ef7f2db52bc3977c5ee39986a7a13c64cd8c58ae31765b85b3d08cc675b
@@ -1,4 +1,5 @@
1
1
  //= require vendor/jquery.delayedChange
2
+ //= require vendor/jquery.fileDownload
2
3
  //= require dataTables/jszip/jszip
3
4
 
4
5
  //= require dataTables/jquery.dataTables
@@ -39,6 +39,7 @@ $(document).on 'click', '.buttons-bulk-actions a', (event) ->
39
39
  url = $bulkAction.attr('href')
40
40
  title = $bulkAction.text()
41
41
  values = $.map($selected, (input) -> input.getAttribute('value'))
42
+ token = $bulkAction.parent('li').data('authenticity-token')
42
43
 
43
44
  return unless url && values
44
45
 
@@ -48,16 +49,33 @@ $(document).on 'click', '.buttons-bulk-actions a', (event) ->
48
49
  # Show Processing...
49
50
  $processing.show().data('bulk-actions-processing', true)
50
51
 
51
- $.post(
52
- url, { ids: values }
53
- ).done((response) ->
54
- success = response['message'] || "Successfully completed #{title} bulk action"
55
- $processing.html(success)
56
- ).fail((response) ->
57
- error = response['message'] || "An error occured while attempting #{title} bulk action: #{response.statusText}"
58
- $processing.html(error)
59
- alert(error)
60
- ).always((response) ->
61
- $table.dataTable().data('bulk-actions-restore-selected-values', values)
62
- $table.DataTable().draw()
63
- )
52
+ if token # This is a file download
53
+ $.fileDownload(url,
54
+ httpMethod: 'POST',
55
+ data: { ids: values, authenticity_token: token }
56
+ successCallback: ->
57
+ success = "Successfully completed #{title} bulk action"
58
+ $processing.html(success)
59
+ $table.dataTable().data('bulk-actions-restore-selected-values', values)
60
+ $table.DataTable().draw()
61
+ failCallback: ->
62
+ error = "An error occured while attempting #{title} bulk action"
63
+ $processing.html(error)
64
+ alert(error)
65
+ $table.dataTable().data('bulk-actions-restore-selected-values', values)
66
+ $table.DataTable().draw()
67
+ )
68
+ else # Normal AJAX post
69
+ $.post(
70
+ url, { ids: values }
71
+ ).done((response) ->
72
+ success = response['message'] || "Successfully completed #{title} bulk action"
73
+ $processing.html(success)
74
+ ).fail((response) ->
75
+ error = response['message'] || "An error occured while attempting #{title} bulk action: #{response.statusText}"
76
+ $processing.html(error)
77
+ alert(error)
78
+ ).always((response) ->
79
+ $table.dataTable().data('bulk-actions-restore-selected-values', values)
80
+ $table.DataTable().draw()
81
+ )
@@ -0,0 +1,493 @@
1
+ /*
2
+ * jQuery File Download Plugin v1.4.5
3
+ *
4
+ * http://www.johnculviner.com
5
+ *
6
+ * Copyright (c) 2013 - John Culviner
7
+ *
8
+ * Licensed under the MIT license:
9
+ * http://www.opensource.org/licenses/mit-license.php
10
+ *
11
+ * !!!!NOTE!!!!
12
+ * You must also write a cookie in conjunction with using this plugin as mentioned in the orignal post:
13
+ * http://johnculviner.com/jquery-file-download-plugin-for-ajax-like-feature-rich-file-downloads/
14
+ * !!!!NOTE!!!!
15
+ */
16
+
17
+ (function($, window){
18
+ // i'll just put them here to get evaluated on script load
19
+ var htmlSpecialCharsRegEx = /[<>&\r\n"']/gm;
20
+ var htmlSpecialCharsPlaceHolders = {
21
+ '<': 'lt;',
22
+ '>': 'gt;',
23
+ '&': 'amp;',
24
+ '\r': "#13;",
25
+ '\n': "#10;",
26
+ '"': 'quot;',
27
+ "'": '#39;' /*single quotes just to be safe, IE8 doesn't support &apos;, so use &#39; instead */
28
+ };
29
+
30
+ $.extend({
31
+ //
32
+ //$.fileDownload('/path/to/url/', options)
33
+ // see directly below for possible 'options'
34
+ fileDownload: function (fileUrl, options) {
35
+
36
+ //provide some reasonable defaults to any unspecified options below
37
+ var settings = $.extend({
38
+
39
+ //
40
+ //Requires jQuery UI: provide a message to display to the user when the file download is being prepared before the browser's dialog appears
41
+ //
42
+ preparingMessageHtml: null,
43
+
44
+ //
45
+ //Requires jQuery UI: provide a message to display to the user when a file download fails
46
+ //
47
+ failMessageHtml: null,
48
+
49
+ //
50
+ //the stock android browser straight up doesn't support file downloads initiated by a non GET: http://code.google.com/p/android/issues/detail?id=1780
51
+ //specify a message here to display if a user tries with an android browser
52
+ //if jQuery UI is installed this will be a dialog, otherwise it will be an alert
53
+ //Set to null to disable the message and attempt to download anyway
54
+ //
55
+ androidPostUnsupportedMessageHtml: "Unfortunately your Android browser doesn't support this type of file download. Please try again with a different browser.",
56
+
57
+ //
58
+ //Requires jQuery UI: options to pass into jQuery UI Dialog
59
+ //
60
+ dialogOptions: { modal: true },
61
+
62
+ //
63
+ //a function to call while the dowload is being prepared before the browser's dialog appears
64
+ //Args:
65
+ // url - the original url attempted
66
+ //
67
+ prepareCallback: function (url) { },
68
+
69
+ //
70
+ //a function to call after a file download successfully completed
71
+ //Args:
72
+ // url - the original url attempted
73
+ //
74
+ successCallback: function (url) { },
75
+
76
+ //
77
+ //a function to call after a file download request was canceled
78
+ //Args:
79
+ // url - the original url attempted
80
+ //
81
+ abortCallback: function (url) { },
82
+
83
+ //
84
+ //a function to call after a file download failed
85
+ //Args:
86
+ // responseHtml - the html that came back in response to the file download. this won't necessarily come back depending on the browser.
87
+ // in less than IE9 a cross domain error occurs because 500+ errors cause a cross domain issue due to IE subbing out the
88
+ // server's error message with a "helpful" IE built in message
89
+ // url - the original url attempted
90
+ // error - original error cautch from exception
91
+ //
92
+ failCallback: function (responseHtml, url, error) { },
93
+
94
+ //
95
+ // the HTTP method to use. Defaults to "GET".
96
+ //
97
+ httpMethod: "GET",
98
+
99
+ //
100
+ // if specified will perform a "httpMethod" request to the specified 'fileUrl' using the specified data.
101
+ // data must be an object (which will be $.param serialized) or already a key=value param string
102
+ //
103
+ data: null,
104
+
105
+ //
106
+ //a period in milliseconds to poll to determine if a successful file download has occured or not
107
+ //
108
+ checkInterval: 100,
109
+
110
+ //
111
+ //the cookie name to indicate if a file download has occured
112
+ //
113
+ cookieName: "fileDownload",
114
+
115
+ //
116
+ //the cookie value for the above name to indicate that a file download has occured
117
+ //
118
+ cookieValue: "true",
119
+
120
+ //
121
+ //the cookie path for above name value pair
122
+ //
123
+ cookiePath: "/",
124
+
125
+ //
126
+ //if specified it will be used when attempting to clear the above name value pair
127
+ //useful for when downloads are being served on a subdomain (e.g. downloads.example.com)
128
+ //
129
+ cookieDomain: null,
130
+
131
+ //
132
+ //the title for the popup second window as a download is processing in the case of a mobile browser
133
+ //
134
+ popupWindowTitle: "Initiating file download...",
135
+
136
+ //
137
+ //Functionality to encode HTML entities for a POST, need this if data is an object with properties whose values contains strings with quotation marks.
138
+ //HTML entity encoding is done by replacing all &,<,>,',",\r,\n characters.
139
+ //Note that some browsers will POST the string htmlentity-encoded whilst others will decode it before POSTing.
140
+ //It is recommended that on the server, htmlentity decoding is done irrespective.
141
+ //
142
+ encodeHTMLEntities: true
143
+
144
+ }, options);
145
+
146
+ var deferred = new $.Deferred();
147
+
148
+ //Setup mobile browser detection: Partial credit: http://detectmobilebrowser.com/
149
+ var userAgent = (navigator.userAgent || navigator.vendor || window.opera).toLowerCase();
150
+
151
+ var isIos; //has full support of features in iOS 4.0+, uses a new window to accomplish this.
152
+ var isAndroid; //has full support of GET features in 4.0+ by using a new window. Non-GET is completely unsupported by the browser. See above for specifying a message.
153
+ var isOtherMobileBrowser; //there is no way to reliably guess here so all other mobile devices will GET and POST to the current window.
154
+
155
+ if (/ip(ad|hone|od)/.test(userAgent)) {
156
+
157
+ isIos = true;
158
+
159
+ } else if (userAgent.indexOf('android') !== -1) {
160
+
161
+ isAndroid = true;
162
+
163
+ } else {
164
+
165
+ isOtherMobileBrowser = /avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|playbook|silk|iemobile|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(userAgent) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-/i.test(userAgent.substr(0, 4));
166
+
167
+ }
168
+
169
+ var httpMethodUpper = settings.httpMethod.toUpperCase();
170
+
171
+ if (isAndroid && httpMethodUpper !== "GET" && settings.androidPostUnsupportedMessageHtml) {
172
+ //the stock android browser straight up doesn't support file downloads initiated by non GET requests: http://code.google.com/p/android/issues/detail?id=1780
173
+
174
+ if ($().dialog) {
175
+ $("<div>").html(settings.androidPostUnsupportedMessageHtml).dialog(settings.dialogOptions);
176
+ } else {
177
+ alert(settings.androidPostUnsupportedMessageHtml);
178
+ }
179
+
180
+ return deferred.reject();
181
+ }
182
+
183
+ var $preparingDialog = null;
184
+
185
+ var internalCallbacks = {
186
+
187
+ onPrepare: function (url) {
188
+
189
+ //wire up a jquery dialog to display the preparing message if specified
190
+ if (settings.preparingMessageHtml) {
191
+
192
+ $preparingDialog = $("<div>").html(settings.preparingMessageHtml).dialog(settings.dialogOptions);
193
+
194
+ } else if (settings.prepareCallback) {
195
+
196
+ settings.prepareCallback(url);
197
+
198
+ }
199
+
200
+ },
201
+
202
+ onSuccess: function (url) {
203
+
204
+ //remove the perparing message if it was specified
205
+ if ($preparingDialog) {
206
+ $preparingDialog.dialog('close');
207
+ }
208
+
209
+ settings.successCallback(url);
210
+
211
+ deferred.resolve(url);
212
+ },
213
+
214
+ onAbort: function (url) {
215
+
216
+ //remove the perparing message if it was specified
217
+ if ($preparingDialog) {
218
+ $preparingDialog.dialog('close');
219
+ };
220
+
221
+ settings.abortCallback(url);
222
+
223
+ deferred.reject(url);
224
+ },
225
+
226
+ onFail: function (responseHtml, url, error) {
227
+
228
+ //remove the perparing message if it was specified
229
+ if ($preparingDialog) {
230
+ $preparingDialog.dialog('close');
231
+ }
232
+
233
+ //wire up a jquery dialog to display the fail message if specified
234
+ if (settings.failMessageHtml) {
235
+ $("<div>").html(settings.failMessageHtml).dialog(settings.dialogOptions);
236
+ }
237
+
238
+ settings.failCallback(responseHtml, url, error);
239
+
240
+ deferred.reject(responseHtml, url);
241
+ }
242
+ };
243
+
244
+ internalCallbacks.onPrepare(fileUrl);
245
+
246
+ //make settings.data a param string if it exists and isn't already
247
+ if (settings.data !== null && typeof settings.data !== "string") {
248
+ settings.data = $.param(settings.data);
249
+ }
250
+
251
+
252
+ var $iframe,
253
+ downloadWindow,
254
+ formDoc,
255
+ $form;
256
+
257
+ if (httpMethodUpper === "GET") {
258
+
259
+ if (settings.data !== null) {
260
+ //need to merge any fileUrl params with the data object
261
+
262
+ var qsStart = fileUrl.indexOf('?');
263
+
264
+ if (qsStart !== -1) {
265
+ //we have a querystring in the url
266
+
267
+ if (fileUrl.substring(fileUrl.length - 1) !== "&") {
268
+ fileUrl = fileUrl + "&";
269
+ }
270
+ } else {
271
+
272
+ fileUrl = fileUrl + "?";
273
+ }
274
+
275
+ fileUrl = fileUrl + settings.data;
276
+ }
277
+
278
+ if (isIos || isAndroid) {
279
+
280
+ downloadWindow = window.open(fileUrl);
281
+ downloadWindow.document.title = settings.popupWindowTitle;
282
+ window.focus();
283
+
284
+ } else if (isOtherMobileBrowser) {
285
+
286
+ window.location(fileUrl);
287
+
288
+ } else {
289
+
290
+ //create a temporary iframe that is used to request the fileUrl as a GET request
291
+ $iframe = $("<iframe>")
292
+ .hide()
293
+ .prop("src", fileUrl)
294
+ .appendTo("body");
295
+ }
296
+
297
+ } else {
298
+
299
+ var formInnerHtml = "";
300
+
301
+ if (settings.data !== null) {
302
+
303
+ $.each(settings.data.replace(/\+/g, ' ').split("&"), function () {
304
+
305
+ var kvp = this.split("=");
306
+
307
+ //Issue: When value contains sign '=' then the kvp array does have more than 2 items. We have to join value back
308
+ var k = kvp[0];
309
+ kvp.shift();
310
+ var v = kvp.join("=");
311
+ kvp = [k, v];
312
+
313
+ var key = settings.encodeHTMLEntities ? htmlSpecialCharsEntityEncode(decodeURIComponent(kvp[0])) : decodeURIComponent(kvp[0]);
314
+ if (key) {
315
+ var value = settings.encodeHTMLEntities ? htmlSpecialCharsEntityEncode(decodeURIComponent(kvp[1])) : decodeURIComponent(kvp[1]);
316
+ formInnerHtml += '<input type="hidden" name="' + key + '" value="' + value + '" />';
317
+ }
318
+ });
319
+ }
320
+
321
+ if (isOtherMobileBrowser) {
322
+
323
+ $form = $("<form>").appendTo("body");
324
+ $form.hide()
325
+ .prop('method', settings.httpMethod)
326
+ .prop('action', fileUrl)
327
+ .html(formInnerHtml);
328
+
329
+ } else {
330
+
331
+ if (isIos) {
332
+
333
+ downloadWindow = window.open("about:blank");
334
+ downloadWindow.document.title = settings.popupWindowTitle;
335
+ formDoc = downloadWindow.document;
336
+ window.focus();
337
+
338
+ } else {
339
+
340
+ $iframe = $("<iframe style='display: none' src='about:blank'></iframe>").appendTo("body");
341
+ formDoc = getiframeDocument($iframe);
342
+ }
343
+
344
+ formDoc.write("<html><head></head><body><form method='" + settings.httpMethod + "' action='" + fileUrl + "'>" + formInnerHtml + "</form>" + settings.popupWindowTitle + "</body></html>");
345
+ $form = $(formDoc).find('form');
346
+ }
347
+
348
+ $form.submit();
349
+ }
350
+
351
+
352
+ //check if the file download has completed every checkInterval ms
353
+ setTimeout(checkFileDownloadComplete, settings.checkInterval);
354
+
355
+
356
+ function checkFileDownloadComplete() {
357
+ //has the cookie been written due to a file download occuring?
358
+
359
+ var cookieValue = settings.cookieValue;
360
+ if(typeof cookieValue == 'string') {
361
+ cookieValue = cookieValue.toLowerCase();
362
+ }
363
+
364
+ var lowerCaseCookie = settings.cookieName.toLowerCase() + "=" + cookieValue;
365
+
366
+ if (document.cookie.toLowerCase().indexOf(lowerCaseCookie) > -1) {
367
+
368
+ //execute specified callback
369
+ internalCallbacks.onSuccess(fileUrl);
370
+
371
+ //remove cookie
372
+ var cookieData = settings.cookieName + "=; path=" + settings.cookiePath + "; expires=" + new Date(0).toUTCString() + ";";
373
+ if (settings.cookieDomain) cookieData += " domain=" + settings.cookieDomain + ";";
374
+ document.cookie = cookieData;
375
+
376
+ //remove iframe
377
+ cleanUp(false);
378
+
379
+ return;
380
+ }
381
+
382
+ //has an error occured?
383
+ //if neither containers exist below then the file download is occuring on the current window
384
+ if (downloadWindow || $iframe) {
385
+
386
+ //has an error occured?
387
+ try {
388
+
389
+ var formDoc = downloadWindow ? downloadWindow.document : getiframeDocument($iframe);
390
+
391
+ if (formDoc && formDoc.body !== null && formDoc.body.innerHTML.length) {
392
+
393
+ var isFailure = true;
394
+
395
+ if ($form && $form.length) {
396
+ var $contents = $(formDoc.body).contents().first();
397
+
398
+ try {
399
+ if ($contents.length && $contents[0] === $form[0]) {
400
+ isFailure = false;
401
+ }
402
+ } catch (e) {
403
+ if (e && e.number == -2146828218) {
404
+ // IE 8-10 throw a permission denied after the form reloads on the "$contents[0] === $form[0]" comparison
405
+ isFailure = true;
406
+ } else {
407
+ throw e;
408
+ }
409
+ }
410
+ }
411
+
412
+ if (isFailure) {
413
+ // IE 8-10 don't always have the full content available right away, they need a litle bit to finish
414
+ setTimeout(function () {
415
+ internalCallbacks.onFail(formDoc.body.innerHTML, fileUrl);
416
+ cleanUp(true);
417
+ }, 100);
418
+
419
+ return;
420
+ }
421
+ }
422
+ }
423
+ catch (err) {
424
+
425
+ //500 error less than IE9
426
+ internalCallbacks.onFail('', fileUrl, err);
427
+
428
+ cleanUp(true);
429
+
430
+ return;
431
+ }
432
+ }
433
+
434
+
435
+ //keep checking...
436
+ setTimeout(checkFileDownloadComplete, settings.checkInterval);
437
+ }
438
+
439
+ //gets an iframes document in a cross browser compatible manner
440
+ function getiframeDocument($iframe) {
441
+ var iframeDoc = $iframe[0].contentWindow || $iframe[0].contentDocument;
442
+ if (iframeDoc.document) {
443
+ iframeDoc = iframeDoc.document;
444
+ }
445
+ return iframeDoc;
446
+ }
447
+
448
+ function cleanUp(isFailure) {
449
+
450
+ setTimeout(function() {
451
+
452
+ if (downloadWindow) {
453
+
454
+ if (isAndroid) {
455
+ downloadWindow.close();
456
+ }
457
+
458
+ if (isIos) {
459
+ if (downloadWindow.focus) {
460
+ downloadWindow.focus(); //ios safari bug doesn't allow a window to be closed unless it is focused
461
+ if (isFailure) {
462
+ downloadWindow.close();
463
+ }
464
+ }
465
+ }
466
+ }
467
+
468
+ //iframe cleanup appears to randomly cause the download to fail
469
+ //not doing it seems better than failure...
470
+ //if ($iframe) {
471
+ // $iframe.remove();
472
+ //}
473
+
474
+ }, 0);
475
+ }
476
+
477
+
478
+ function htmlSpecialCharsEntityEncode(str) {
479
+ return str.replace(htmlSpecialCharsRegEx, function(match) {
480
+ return '&' + htmlSpecialCharsPlaceHolders[match];
481
+ });
482
+ }
483
+ var promise = deferred.promise();
484
+ promise.abort = function() {
485
+ cleanUp();
486
+ $iframe.attr('src', '').html('');
487
+ internalCallbacks.onAbort(fileUrl);
488
+ };
489
+ return promise;
490
+ }
491
+ });
492
+
493
+ })(jQuery, this || window);
@@ -8,6 +8,10 @@ module Effective
8
8
  concat content_tag(:li, link_to(*args))
9
9
  end
10
10
 
11
+ def bulk_download(*args)
12
+ concat content_tag(:li, link_to(*args), 'data-authenticity-token' => form_authenticity_token)
13
+ end
14
+
11
15
  def bulk_action_divider
12
16
  concat content_tag(:li, '', class: 'divider', role: 'separator')
13
17
  end
@@ -1,3 +1,3 @@
1
1
  module EffectiveDatatables
2
- VERSION = '2.6.19'.freeze
2
+ VERSION = '2.6.20'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_datatables
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.19
4
+ version: 2.6.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-04 00:00:00.000000000 Z
11
+ date: 2016-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -127,6 +127,7 @@ files:
127
127
  - app/assets/javascripts/effective_datatables/responsive.js.coffee
128
128
  - app/assets/javascripts/effective_datatables/scopes.js.coffee
129
129
  - app/assets/javascripts/vendor/jquery.delayedChange.js
130
+ - app/assets/javascripts/vendor/jquery.fileDownload.js
130
131
  - app/assets/stylesheets/dataTables/buttons/buttons.bootstrap.css
131
132
  - app/assets/stylesheets/dataTables/colReorder/colReorder.bootstrap.css
132
133
  - app/assets/stylesheets/dataTables/dataTables.bootstrap.css