jquery_file_download-rails 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +7 -0
- data/LICENSE +20 -0
- data/README.md +58 -0
- data/Rakefile +70 -0
- data/app/assets/javascripts/jquery.fileDownload.js +432 -0
- data/lib/jquery_file_download.rb +2 -0
- data/lib/jquery_file_download/rails.rb +3 -0
- data/lib/jquery_file_download/rails/engine.rb +7 -0
- data/lib/jquery_file_download/rails/version.rb +7 -0
- metadata +66 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 00aa6e47ccc29d1bd11a5e3344a1d275ad661905
|
4
|
+
data.tar.gz: efc6433dd747ddfe26b540000b68b97d384a192e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cf9fb67015e007e52c450d1c6cf4ef11436d717ab110763e8b1d7b15cf8cddcdfcf2773653579ca5fd582da4a78c1131522457ea7b995fc2a694c5676194a85c
|
7
|
+
data.tar.gz: 968b3e422f9275e8b6d25da07f44ea175a2d832ba9dc878515ef6b486c7443672a377917e6541799cd26c13311213d7aa78a156347cc58432930c614f440aad6
|
data/CHANGELOG.md
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Richard Cook
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# `jquery_file_download-rails`
|
2
|
+
|
3
|
+
[](https://rubygems.org/gems/jquery_file_download-rails)
|
4
|
+
[](https://travis-ci.org/rcook/jquery_file_download-rails)
|
5
|
+
|
6
|
+
[`jquery.fileDownload.js`](https://github.com/johnculviner/jquery.fileDownload)
|
7
|
+
package for Rails 3.1+ asset pipeline.
|
8
|
+
|
9
|
+
# Installation
|
10
|
+
|
11
|
+
* Add `jquery_file_download-rails` to your application's `Gemfile`:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'jquery_file_download-rails'
|
15
|
+
```
|
16
|
+
|
17
|
+
* Run Bundler to lock the gem:
|
18
|
+
|
19
|
+
```bash
|
20
|
+
bundle install
|
21
|
+
```
|
22
|
+
|
23
|
+
* Add a reference to the gem's assets to your application's JavaScript asset
|
24
|
+
manifest (usually `app/assets/javascripts/application.js`):
|
25
|
+
|
26
|
+
```javascript
|
27
|
+
//= require jquery.fileDownload
|
28
|
+
```
|
29
|
+
|
30
|
+
* Actions sending files in response to download requests must set the `fileDownload`
|
31
|
+
cookie which can be done via the `cookies` collection as in this sample controller:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
class DownloadController < ApplicationController
|
35
|
+
def some_file
|
36
|
+
cookies['fileDownload'] = 'true'
|
37
|
+
|
38
|
+
send_file 'path-to-file-on-server',
|
39
|
+
:filename => 'browser-download-file-name',
|
40
|
+
:type => 'content-type',
|
41
|
+
:x_sendfile => true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
# Usage
|
47
|
+
|
48
|
+
With the gem installed, the `$.fileDownload` jQuery plugin is available in the browser.
|
49
|
+
|
50
|
+
# More details
|
51
|
+
|
52
|
+
* [`jquery.fileDownload.js` at GitHub](https://github.com/johnculviner/jquery.fileDownload)
|
53
|
+
* [John Culviner's original blog post](http://johnculviner.com/post/2012/03/22/Ajax-like-feature-rich-file-downloads-with-jQuery-File-Download.aspx)
|
54
|
+
|
55
|
+
# Licence
|
56
|
+
|
57
|
+
`jquery_file_download-rails` is released under the MIT licence.
|
58
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
|
4
|
+
module Util
|
5
|
+
extend self
|
6
|
+
|
7
|
+
JQUERY_FILE_DOWNLOAD_README_PATH = 'jquery.fileDownload/README.md'
|
8
|
+
JQUERY_FILE_DOWNLOAD_SCRIPT_PATH = 'jquery.fileDownload/src/Scripts/jquery.fileDownload.js'
|
9
|
+
TARGET_VERSION_PATH = 'lib/jquery_file_download/rails/version.rb'
|
10
|
+
|
11
|
+
def read_jquery_file_download_version(file_name)
|
12
|
+
File.readlines(file_name).each do |line|
|
13
|
+
return $1 if line =~ /jQuery File Download Plugin v(\d+\.\d+\.\d+)/
|
14
|
+
end
|
15
|
+
raise 'Could not determine jquery.fileDownload version'
|
16
|
+
end
|
17
|
+
|
18
|
+
# See https://github.com/joliss/jquery-ui-rails/blob/master/Rakefile
|
19
|
+
def protect_copyright_notice(content)
|
20
|
+
content.gsub!(/\A\s*\/\*\r?\n/, "/*!\n")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
desc 'Update the jquery.fileDownload submodule'
|
25
|
+
task :submodule do
|
26
|
+
Rake.rake_output_message 'Updating jquery.fileDownload submodule'
|
27
|
+
sh 'git submodule update --init' unless File.exist?(Util::JQUERY_FILE_DOWNLOAD_README_PATH)
|
28
|
+
end
|
29
|
+
|
30
|
+
desc 'Clean the app directory'
|
31
|
+
task :clean do
|
32
|
+
rm_rf 'app'
|
33
|
+
end
|
34
|
+
|
35
|
+
desc 'Update jquery.fileDownload.js version number'
|
36
|
+
task :version => :submodule do
|
37
|
+
version = Util.read_jquery_file_download_version(Util::JQUERY_FILE_DOWNLOAD_SCRIPT_PATH)
|
38
|
+
|
39
|
+
Rake.rake_output_message "jquery.fileDownload version is #{version}"
|
40
|
+
|
41
|
+
content = File.read(Util::TARGET_VERSION_PATH)
|
42
|
+
pattern = /JQUERY_FILE_DOWNLOAD_VERSION = '[^']*'/
|
43
|
+
replacement = "JQUERY_FILE_DOWNLOAD_VERSION = '#{version}'"
|
44
|
+
content.sub! pattern, replacement or raise "Could not update version in #{Util::TARGET_VERSION_PATH}"
|
45
|
+
File.write(Util::TARGET_VERSION_PATH, content)
|
46
|
+
end
|
47
|
+
|
48
|
+
desc 'Generate JavaScript assets'
|
49
|
+
task :javascripts => :submodule do
|
50
|
+
target_dir = "app/assets/javascripts"
|
51
|
+
mkdir_p target_dir
|
52
|
+
|
53
|
+
Dir.glob('jquery.fileDownload/src/Scripts/*.js').each do |path|
|
54
|
+
base_name = File.basename(path)
|
55
|
+
file_name = "#{target_dir}/#{base_name}"
|
56
|
+
Rake.rake_output_message "Updating #{file_name}"
|
57
|
+
File.open(file_name, 'w') do |f|
|
58
|
+
content = File.read(path)
|
59
|
+
Util.protect_copyright_notice(content)
|
60
|
+
f.write(content)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
task :default => [
|
66
|
+
:clean,
|
67
|
+
:version,
|
68
|
+
:javascripts
|
69
|
+
]
|
70
|
+
|
@@ -0,0 +1,432 @@
|
|
1
|
+
/*!
|
2
|
+
* jQuery File Download Plugin v1.4.2
|
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
|
+
"'": 'apos;' /*single quotes just to be safe*/
|
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
|
+
//
|
54
|
+
androidPostUnsupportedMessageHtml: "Unfortunately your Android browser doesn't support this type of file download. Please try again with a different browser.",
|
55
|
+
|
56
|
+
//
|
57
|
+
//Requires jQuery UI: options to pass into jQuery UI Dialog
|
58
|
+
//
|
59
|
+
dialogOptions: { modal: true },
|
60
|
+
|
61
|
+
//
|
62
|
+
//a function to call while the dowload is being prepared before the browser's dialog appears
|
63
|
+
//Args:
|
64
|
+
// url - the original url attempted
|
65
|
+
//
|
66
|
+
prepareCallback: function (url) { },
|
67
|
+
|
68
|
+
//
|
69
|
+
//a function to call after a file download dialog/ribbon has appeared
|
70
|
+
//Args:
|
71
|
+
// url - the original url attempted
|
72
|
+
//
|
73
|
+
successCallback: function (url) { },
|
74
|
+
|
75
|
+
//
|
76
|
+
//a function to call after a file download dialog/ribbon has appeared
|
77
|
+
//Args:
|
78
|
+
// responseHtml - the html that came back in response to the file download. this won't necessarily come back depending on the browser.
|
79
|
+
// in less than IE9 a cross domain error occurs because 500+ errors cause a cross domain issue due to IE subbing out the
|
80
|
+
// server's error message with a "helpful" IE built in message
|
81
|
+
// url - the original url attempted
|
82
|
+
//
|
83
|
+
failCallback: function (responseHtml, url) { },
|
84
|
+
|
85
|
+
//
|
86
|
+
// the HTTP method to use. Defaults to "GET".
|
87
|
+
//
|
88
|
+
httpMethod: "GET",
|
89
|
+
|
90
|
+
//
|
91
|
+
// if specified will perform a "httpMethod" request to the specified 'fileUrl' using the specified data.
|
92
|
+
// data must be an object (which will be $.param serialized) or already a key=value param string
|
93
|
+
//
|
94
|
+
data: null,
|
95
|
+
|
96
|
+
//
|
97
|
+
//a period in milliseconds to poll to determine if a successful file download has occured or not
|
98
|
+
//
|
99
|
+
checkInterval: 100,
|
100
|
+
|
101
|
+
//
|
102
|
+
//the cookie name to indicate if a file download has occured
|
103
|
+
//
|
104
|
+
cookieName: "fileDownload",
|
105
|
+
|
106
|
+
//
|
107
|
+
//the cookie value for the above name to indicate that a file download has occured
|
108
|
+
//
|
109
|
+
cookieValue: "true",
|
110
|
+
|
111
|
+
//
|
112
|
+
//the cookie path for above name value pair
|
113
|
+
//
|
114
|
+
cookiePath: "/",
|
115
|
+
|
116
|
+
//
|
117
|
+
//the title for the popup second window as a download is processing in the case of a mobile browser
|
118
|
+
//
|
119
|
+
popupWindowTitle: "Initiating file download...",
|
120
|
+
|
121
|
+
//
|
122
|
+
//Functionality to encode HTML entities for a POST, need this if data is an object with properties whose values contains strings with quotation marks.
|
123
|
+
//HTML entity encoding is done by replacing all &,<,>,',",\r,\n characters.
|
124
|
+
//Note that some browsers will POST the string htmlentity-encoded whilst others will decode it before POSTing.
|
125
|
+
//It is recommended that on the server, htmlentity decoding is done irrespective.
|
126
|
+
//
|
127
|
+
encodeHTMLEntities: true
|
128
|
+
|
129
|
+
}, options);
|
130
|
+
|
131
|
+
var deferred = new $.Deferred();
|
132
|
+
|
133
|
+
//Setup mobile browser detection: Partial credit: http://detectmobilebrowser.com/
|
134
|
+
var userAgent = (navigator.userAgent || navigator.vendor || window.opera).toLowerCase();
|
135
|
+
|
136
|
+
var isIos; //has full support of features in iOS 4.0+, uses a new window to accomplish this.
|
137
|
+
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.
|
138
|
+
var isOtherMobileBrowser; //there is no way to reliably guess here so all other mobile devices will GET and POST to the current window.
|
139
|
+
|
140
|
+
if (/ip(ad|hone|od)/.test(userAgent)) {
|
141
|
+
|
142
|
+
isIos = true;
|
143
|
+
|
144
|
+
} else if (userAgent.indexOf('android') !== -1) {
|
145
|
+
|
146
|
+
isAndroid = true;
|
147
|
+
|
148
|
+
} else {
|
149
|
+
|
150
|
+
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));
|
151
|
+
|
152
|
+
}
|
153
|
+
|
154
|
+
var httpMethodUpper = settings.httpMethod.toUpperCase();
|
155
|
+
|
156
|
+
if (isAndroid && httpMethodUpper !== "GET") {
|
157
|
+
//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
|
158
|
+
|
159
|
+
if ($().dialog) {
|
160
|
+
$("<div>").html(settings.androidPostUnsupportedMessageHtml).dialog(settings.dialogOptions);
|
161
|
+
} else {
|
162
|
+
alert(settings.androidPostUnsupportedMessageHtml);
|
163
|
+
}
|
164
|
+
|
165
|
+
return deferred.reject();
|
166
|
+
}
|
167
|
+
|
168
|
+
var $preparingDialog = null;
|
169
|
+
|
170
|
+
var internalCallbacks = {
|
171
|
+
|
172
|
+
onPrepare: function (url) {
|
173
|
+
|
174
|
+
//wire up a jquery dialog to display the preparing message if specified
|
175
|
+
if (settings.preparingMessageHtml) {
|
176
|
+
|
177
|
+
$preparingDialog = $("<div>").html(settings.preparingMessageHtml).dialog(settings.dialogOptions);
|
178
|
+
|
179
|
+
} else if (settings.prepareCallback) {
|
180
|
+
|
181
|
+
settings.prepareCallback(url);
|
182
|
+
|
183
|
+
}
|
184
|
+
|
185
|
+
},
|
186
|
+
|
187
|
+
onSuccess: function (url) {
|
188
|
+
|
189
|
+
//remove the perparing message if it was specified
|
190
|
+
if ($preparingDialog) {
|
191
|
+
$preparingDialog.dialog('close');
|
192
|
+
};
|
193
|
+
|
194
|
+
settings.successCallback(url);
|
195
|
+
|
196
|
+
deferred.resolve(url);
|
197
|
+
},
|
198
|
+
|
199
|
+
onFail: function (responseHtml, url) {
|
200
|
+
|
201
|
+
//remove the perparing message if it was specified
|
202
|
+
if ($preparingDialog) {
|
203
|
+
$preparingDialog.dialog('close');
|
204
|
+
};
|
205
|
+
|
206
|
+
//wire up a jquery dialog to display the fail message if specified
|
207
|
+
if (settings.failMessageHtml) {
|
208
|
+
$("<div>").html(settings.failMessageHtml).dialog(settings.dialogOptions);
|
209
|
+
}
|
210
|
+
|
211
|
+
settings.failCallback(responseHtml, url);
|
212
|
+
|
213
|
+
deferred.reject(responseHtml, url);
|
214
|
+
}
|
215
|
+
};
|
216
|
+
|
217
|
+
internalCallbacks.onPrepare(fileUrl);
|
218
|
+
|
219
|
+
//make settings.data a param string if it exists and isn't already
|
220
|
+
if (settings.data !== null && typeof settings.data !== "string") {
|
221
|
+
settings.data = $.param(settings.data);
|
222
|
+
}
|
223
|
+
|
224
|
+
|
225
|
+
var $iframe,
|
226
|
+
downloadWindow,
|
227
|
+
formDoc,
|
228
|
+
$form;
|
229
|
+
|
230
|
+
if (httpMethodUpper === "GET") {
|
231
|
+
|
232
|
+
if (settings.data !== null) {
|
233
|
+
//need to merge any fileUrl params with the data object
|
234
|
+
|
235
|
+
var qsStart = fileUrl.indexOf('?');
|
236
|
+
|
237
|
+
if (qsStart !== -1) {
|
238
|
+
//we have a querystring in the url
|
239
|
+
|
240
|
+
if (fileUrl.substring(fileUrl.length - 1) !== "&") {
|
241
|
+
fileUrl = fileUrl + "&";
|
242
|
+
}
|
243
|
+
} else {
|
244
|
+
|
245
|
+
fileUrl = fileUrl + "?";
|
246
|
+
}
|
247
|
+
|
248
|
+
fileUrl = fileUrl + settings.data;
|
249
|
+
}
|
250
|
+
|
251
|
+
if (isIos || isAndroid) {
|
252
|
+
|
253
|
+
downloadWindow = window.open(fileUrl);
|
254
|
+
downloadWindow.document.title = settings.popupWindowTitle;
|
255
|
+
window.focus();
|
256
|
+
|
257
|
+
} else if (isOtherMobileBrowser) {
|
258
|
+
|
259
|
+
window.location(fileUrl);
|
260
|
+
|
261
|
+
} else {
|
262
|
+
|
263
|
+
//create a temporary iframe that is used to request the fileUrl as a GET request
|
264
|
+
$iframe = $("<iframe>")
|
265
|
+
.hide()
|
266
|
+
.prop("src", fileUrl)
|
267
|
+
.appendTo("body");
|
268
|
+
}
|
269
|
+
|
270
|
+
} else {
|
271
|
+
|
272
|
+
var formInnerHtml = "";
|
273
|
+
|
274
|
+
if (settings.data !== null) {
|
275
|
+
|
276
|
+
$.each(settings.data.replace(/\+/g, ' ').split("&"), function () {
|
277
|
+
|
278
|
+
var kvp = this.split("=");
|
279
|
+
|
280
|
+
var key = settings.encodeHTMLEntities ? htmlSpecialCharsEntityEncode(decodeURIComponent(kvp[0])) : decodeURIComponent(kvp[0]);
|
281
|
+
if (key) {
|
282
|
+
var value = settings.encodeHTMLEntities ? htmlSpecialCharsEntityEncode(decodeURIComponent(kvp[1])) : decodeURIComponent(kvp[1]);
|
283
|
+
formInnerHtml += '<input type="hidden" name="' + key + '" value="' + value + '" />';
|
284
|
+
}
|
285
|
+
});
|
286
|
+
}
|
287
|
+
|
288
|
+
if (isOtherMobileBrowser) {
|
289
|
+
|
290
|
+
$form = $("<form>").appendTo("body");
|
291
|
+
$form.hide()
|
292
|
+
.prop('method', settings.httpMethod)
|
293
|
+
.prop('action', fileUrl)
|
294
|
+
.html(formInnerHtml);
|
295
|
+
|
296
|
+
} else {
|
297
|
+
|
298
|
+
if (isIos) {
|
299
|
+
|
300
|
+
downloadWindow = window.open("about:blank");
|
301
|
+
downloadWindow.document.title = settings.popupWindowTitle;
|
302
|
+
formDoc = downloadWindow.document;
|
303
|
+
window.focus();
|
304
|
+
|
305
|
+
} else {
|
306
|
+
|
307
|
+
$iframe = $("<iframe style='display: none' src='about:blank'></iframe>").appendTo("body");
|
308
|
+
formDoc = getiframeDocument($iframe);
|
309
|
+
}
|
310
|
+
|
311
|
+
formDoc.write("<html><head></head><body><form method='" + settings.httpMethod + "' action='" + fileUrl + "'>" + formInnerHtml + "</form>" + settings.popupWindowTitle + "</body></html>");
|
312
|
+
$form = $(formDoc).find('form');
|
313
|
+
}
|
314
|
+
|
315
|
+
$form.submit();
|
316
|
+
}
|
317
|
+
|
318
|
+
|
319
|
+
//check if the file download has completed every checkInterval ms
|
320
|
+
setTimeout(checkFileDownloadComplete, settings.checkInterval);
|
321
|
+
|
322
|
+
|
323
|
+
function checkFileDownloadComplete() {
|
324
|
+
|
325
|
+
//has the cookie been written due to a file download occuring?
|
326
|
+
if (document.cookie.indexOf(settings.cookieName + "=" + settings.cookieValue) != -1) {
|
327
|
+
|
328
|
+
//execute specified callback
|
329
|
+
internalCallbacks.onSuccess(fileUrl);
|
330
|
+
|
331
|
+
//remove the cookie and iframe
|
332
|
+
document.cookie = settings.cookieName + "=; expires=" + new Date(1000).toUTCString() + "; path=" + settings.cookiePath;
|
333
|
+
|
334
|
+
cleanUp(false);
|
335
|
+
|
336
|
+
return;
|
337
|
+
}
|
338
|
+
|
339
|
+
//has an error occured?
|
340
|
+
//if neither containers exist below then the file download is occuring on the current window
|
341
|
+
if (downloadWindow || $iframe) {
|
342
|
+
|
343
|
+
//has an error occured?
|
344
|
+
try {
|
345
|
+
|
346
|
+
var formDoc = downloadWindow ? downloadWindow.document : getiframeDocument($iframe);
|
347
|
+
|
348
|
+
if (formDoc && formDoc.body != null && formDoc.body.innerHTML.length) {
|
349
|
+
|
350
|
+
var isFailure = true;
|
351
|
+
|
352
|
+
if ($form && $form.length) {
|
353
|
+
var $contents = $(formDoc.body).contents().first();
|
354
|
+
|
355
|
+
if ($contents.length && $contents[0] === $form[0]) {
|
356
|
+
isFailure = false;
|
357
|
+
}
|
358
|
+
}
|
359
|
+
|
360
|
+
if (isFailure) {
|
361
|
+
internalCallbacks.onFail(formDoc.body.innerHTML, fileUrl);
|
362
|
+
|
363
|
+
cleanUp(true);
|
364
|
+
|
365
|
+
return;
|
366
|
+
}
|
367
|
+
}
|
368
|
+
}
|
369
|
+
catch (err) {
|
370
|
+
|
371
|
+
//500 error less than IE9
|
372
|
+
internalCallbacks.onFail('', fileUrl);
|
373
|
+
|
374
|
+
cleanUp(true);
|
375
|
+
|
376
|
+
return;
|
377
|
+
}
|
378
|
+
}
|
379
|
+
|
380
|
+
|
381
|
+
//keep checking...
|
382
|
+
setTimeout(checkFileDownloadComplete, settings.checkInterval);
|
383
|
+
}
|
384
|
+
|
385
|
+
//gets an iframes document in a cross browser compatible manner
|
386
|
+
function getiframeDocument($iframe) {
|
387
|
+
var iframeDoc = $iframe[0].contentWindow || $iframe[0].contentDocument;
|
388
|
+
if (iframeDoc.document) {
|
389
|
+
iframeDoc = iframeDoc.document;
|
390
|
+
}
|
391
|
+
return iframeDoc;
|
392
|
+
}
|
393
|
+
|
394
|
+
function cleanUp(isFailure) {
|
395
|
+
|
396
|
+
setTimeout(function() {
|
397
|
+
|
398
|
+
if (downloadWindow) {
|
399
|
+
|
400
|
+
if (isAndroid) {
|
401
|
+
downloadWindow.close();
|
402
|
+
}
|
403
|
+
|
404
|
+
if (isIos) {
|
405
|
+
downloadWindow.focus(); //ios safari bug doesn't allow a window to be closed unless it is focused
|
406
|
+
if (isFailure) {
|
407
|
+
downloadWindow.close();
|
408
|
+
}
|
409
|
+
}
|
410
|
+
}
|
411
|
+
|
412
|
+
//iframe cleanup appears to randomly cause the download to fail
|
413
|
+
//not doing it seems better than failure...
|
414
|
+
//if ($iframe) {
|
415
|
+
// $iframe.remove();
|
416
|
+
//}
|
417
|
+
|
418
|
+
}, 0);
|
419
|
+
}
|
420
|
+
|
421
|
+
|
422
|
+
function htmlSpecialCharsEntityEncode(str) {
|
423
|
+
return str.replace(htmlSpecialCharsRegEx, function(match) {
|
424
|
+
return '&' + htmlSpecialCharsPlaceHolders[match];
|
425
|
+
});
|
426
|
+
}
|
427
|
+
|
428
|
+
return deferred.promise();
|
429
|
+
}
|
430
|
+
});
|
431
|
+
|
432
|
+
})(jQuery, this);
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jquery_file_download-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Richard Cook
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-01-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: railties
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.1.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.1.0
|
27
|
+
description: jquery.fileDownload.js package for Rails 3.1+ asset pipeline
|
28
|
+
email: rcook@rcook.org
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- app/assets/javascripts/jquery.fileDownload.js
|
34
|
+
- lib/jquery_file_download.rb
|
35
|
+
- lib/jquery_file_download/rails.rb
|
36
|
+
- lib/jquery_file_download/rails/version.rb
|
37
|
+
- lib/jquery_file_download/rails/engine.rb
|
38
|
+
- LICENSE
|
39
|
+
- Rakefile
|
40
|
+
- README.md
|
41
|
+
- CHANGELOG.md
|
42
|
+
homepage: https://github.com/rcook/jquery-filedownload-rails/
|
43
|
+
licenses:
|
44
|
+
- MIT
|
45
|
+
metadata: {}
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
requirements: []
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 2.0.14
|
63
|
+
signing_key:
|
64
|
+
specification_version: 4
|
65
|
+
summary: jquery_file_download-rails
|
66
|
+
test_files: []
|