activestorage 6.1.4.1 → 7.0.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activestorage might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +130 -220
- data/MIT-LICENSE +1 -1
- data/README.md +25 -11
- data/app/assets/javascripts/activestorage.esm.js +844 -0
- data/app/assets/javascripts/activestorage.js +257 -376
- data/app/controllers/active_storage/base_controller.rb +1 -10
- data/app/controllers/active_storage/blobs/proxy_controller.rb +14 -4
- data/app/controllers/active_storage/blobs/redirect_controller.rb +6 -4
- data/app/controllers/active_storage/representations/base_controller.rb +5 -1
- data/app/controllers/active_storage/representations/proxy_controller.rb +6 -4
- data/app/controllers/active_storage/representations/redirect_controller.rb +6 -4
- data/app/controllers/concerns/active_storage/set_blob.rb +6 -2
- data/app/controllers/concerns/active_storage/set_current.rb +3 -3
- data/app/controllers/concerns/active_storage/streaming.rb +65 -0
- data/app/javascript/activestorage/ujs.js +1 -1
- data/app/models/active_storage/attachment.rb +36 -3
- data/app/models/active_storage/blob/representable.rb +7 -5
- data/app/models/active_storage/blob.rb +26 -27
- data/app/models/active_storage/current.rb +12 -2
- data/app/models/active_storage/preview.rb +6 -4
- data/app/models/active_storage/record.rb +1 -1
- data/app/models/active_storage/variant.rb +3 -6
- data/app/models/active_storage/variant_record.rb +2 -0
- data/app/models/active_storage/variant_with_record.rb +9 -5
- data/app/models/active_storage/variation.rb +2 -2
- data/config/routes.rb +10 -10
- data/db/migrate/20170806125915_create_active_storage_tables.rb +29 -8
- data/db/update_migrate/20191206030411_create_active_storage_variant_records.rb +15 -2
- data/lib/active_storage/analyzer/audio_analyzer.rb +65 -0
- data/lib/active_storage/analyzer/image_analyzer/image_magick.rb +39 -0
- data/lib/active_storage/analyzer/image_analyzer/vips.rb +49 -0
- data/lib/active_storage/analyzer/image_analyzer.rb +2 -30
- data/lib/active_storage/analyzer/video_analyzer.rb +26 -11
- data/lib/active_storage/analyzer.rb +8 -4
- data/lib/active_storage/attached/changes/create_many.rb +7 -3
- data/lib/active_storage/attached/changes/create_one.rb +1 -1
- data/lib/active_storage/attached/changes/create_one_of_many.rb +1 -1
- data/lib/active_storage/attached/changes/delete_many.rb +1 -1
- data/lib/active_storage/attached/changes/delete_one.rb +1 -1
- data/lib/active_storage/attached/changes/detach_many.rb +18 -0
- data/lib/active_storage/attached/changes/detach_one.rb +24 -0
- data/lib/active_storage/attached/changes/purge_many.rb +27 -0
- data/lib/active_storage/attached/changes/purge_one.rb +27 -0
- data/lib/active_storage/attached/changes.rb +7 -1
- data/lib/active_storage/attached/many.rb +27 -15
- data/lib/active_storage/attached/model.rb +31 -5
- data/lib/active_storage/attached/one.rb +32 -27
- data/lib/active_storage/downloader.rb +2 -2
- data/lib/active_storage/engine.rb +28 -1
- data/lib/active_storage/fixture_set.rb +76 -0
- data/lib/active_storage/gem_version.rb +4 -4
- data/lib/active_storage/previewer.rb +4 -4
- data/lib/active_storage/reflection.rb +12 -2
- data/lib/active_storage/service/azure_storage_service.rb +1 -1
- data/lib/active_storage/service/configurator.rb +1 -1
- data/lib/active_storage/service/disk_service.rb +13 -18
- data/lib/active_storage/service/gcs_service.rb +91 -7
- data/lib/active_storage/service/mirror_service.rb +1 -1
- data/lib/active_storage/service/registry.rb +1 -1
- data/lib/active_storage/service/s3_service.rb +4 -4
- data/lib/active_storage/service.rb +3 -3
- data/lib/active_storage/transformers/image_processing_transformer.rb +1 -1
- data/lib/active_storage/transformers/transformer.rb +1 -1
- data/lib/active_storage.rb +3 -1
- metadata +30 -21
- data/app/controllers/concerns/active_storage/set_headers.rb +0 -12
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
@@ -32,7 +32,7 @@ class User < ApplicationRecord
|
|
32
32
|
end
|
33
33
|
|
34
34
|
# Attach an avatar to the user.
|
35
|
-
user.avatar.attach(io: File.open("/path/to/face.jpg"), filename: "face.jpg", content_type: "image/
|
35
|
+
user.avatar.attach(io: File.open("/path/to/face.jpg"), filename: "face.jpg", content_type: "image/jpeg")
|
36
36
|
|
37
37
|
# Does the user have an avatar?
|
38
38
|
user.avatar.attached? # => true
|
@@ -88,8 +88,7 @@ class MessagesController < ApplicationController
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def create
|
91
|
-
message = Message.create! params.require(:message).permit(:title, :content)
|
92
|
-
message.images.attach(params[:message][:images])
|
91
|
+
message = Message.create! params.require(:message).permit(:title, :content, images: [])
|
93
92
|
redirect_to message
|
94
93
|
end
|
95
94
|
|
@@ -124,27 +123,42 @@ When the application is configured to proxy files by default, use the `rails_sto
|
|
124
123
|
|
125
124
|
Optionally, files can be proxied instead. This means that your application servers will download file data from the storage service in response to requests. This can be useful for serving files from a CDN.
|
126
125
|
|
127
|
-
|
128
|
-
|
129
|
-
```erb
|
130
|
-
<%= image_tag rails_storage_proxy_path(@user.avatar) %>
|
131
|
-
```
|
132
|
-
|
133
|
-
Or configure Active Storage to use proxying by default:
|
126
|
+
You can configure Active Storage to use proxying by default:
|
134
127
|
|
135
128
|
```ruby
|
136
129
|
# config/initializers/active_storage.rb
|
137
130
|
Rails.application.config.active_storage.resolve_model_to_route = :rails_storage_proxy
|
138
131
|
```
|
139
132
|
|
133
|
+
Or if you want to explicitly proxy specific attachments there are URL helpers you can use in the form of `rails_storage_proxy_path` and `rails_storage_proxy_url`.
|
134
|
+
|
135
|
+
```erb
|
136
|
+
<%= image_tag rails_storage_proxy_path(@user.avatar) %>
|
137
|
+
```
|
138
|
+
|
140
139
|
## Direct uploads
|
141
140
|
|
142
141
|
Active Storage, with its included JavaScript library, supports uploading directly from the client to the cloud.
|
143
142
|
|
144
143
|
### Direct upload installation
|
145
144
|
|
146
|
-
1. Include
|
145
|
+
1. Include the Active Storage JavaScript in your application's JavaScript bundle or reference it directly.
|
147
146
|
|
147
|
+
Requiring directly without bundling through the asset pipeline in the application html with autostart:
|
148
|
+
```html
|
149
|
+
<%= javascript_include_tag "activestorage" %>
|
150
|
+
```
|
151
|
+
Requiring via importmap-rails without bundling through the asset pipeline in the application html without autostart as ESM:
|
152
|
+
```ruby
|
153
|
+
# config/importmap.rb
|
154
|
+
pin "@rails/activestorage", to: "activestorage.esm.js"
|
155
|
+
```
|
156
|
+
```html
|
157
|
+
<script type="module-shim">
|
158
|
+
import * as ActiveStorage from "@rails/activestorage"
|
159
|
+
ActiveStorage.start()
|
160
|
+
</script>
|
161
|
+
```
|
148
162
|
Using the asset pipeline:
|
149
163
|
```js
|
150
164
|
//= require activestorage
|
@@ -0,0 +1,844 @@
|
|
1
|
+
var sparkMd5 = {
|
2
|
+
exports: {}
|
3
|
+
};
|
4
|
+
|
5
|
+
(function(module, exports) {
|
6
|
+
(function(factory) {
|
7
|
+
{
|
8
|
+
module.exports = factory();
|
9
|
+
}
|
10
|
+
})((function(undefined$1) {
|
11
|
+
var hex_chr = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" ];
|
12
|
+
function md5cycle(x, k) {
|
13
|
+
var a = x[0], b = x[1], c = x[2], d = x[3];
|
14
|
+
a += (b & c | ~b & d) + k[0] - 680876936 | 0;
|
15
|
+
a = (a << 7 | a >>> 25) + b | 0;
|
16
|
+
d += (a & b | ~a & c) + k[1] - 389564586 | 0;
|
17
|
+
d = (d << 12 | d >>> 20) + a | 0;
|
18
|
+
c += (d & a | ~d & b) + k[2] + 606105819 | 0;
|
19
|
+
c = (c << 17 | c >>> 15) + d | 0;
|
20
|
+
b += (c & d | ~c & a) + k[3] - 1044525330 | 0;
|
21
|
+
b = (b << 22 | b >>> 10) + c | 0;
|
22
|
+
a += (b & c | ~b & d) + k[4] - 176418897 | 0;
|
23
|
+
a = (a << 7 | a >>> 25) + b | 0;
|
24
|
+
d += (a & b | ~a & c) + k[5] + 1200080426 | 0;
|
25
|
+
d = (d << 12 | d >>> 20) + a | 0;
|
26
|
+
c += (d & a | ~d & b) + k[6] - 1473231341 | 0;
|
27
|
+
c = (c << 17 | c >>> 15) + d | 0;
|
28
|
+
b += (c & d | ~c & a) + k[7] - 45705983 | 0;
|
29
|
+
b = (b << 22 | b >>> 10) + c | 0;
|
30
|
+
a += (b & c | ~b & d) + k[8] + 1770035416 | 0;
|
31
|
+
a = (a << 7 | a >>> 25) + b | 0;
|
32
|
+
d += (a & b | ~a & c) + k[9] - 1958414417 | 0;
|
33
|
+
d = (d << 12 | d >>> 20) + a | 0;
|
34
|
+
c += (d & a | ~d & b) + k[10] - 42063 | 0;
|
35
|
+
c = (c << 17 | c >>> 15) + d | 0;
|
36
|
+
b += (c & d | ~c & a) + k[11] - 1990404162 | 0;
|
37
|
+
b = (b << 22 | b >>> 10) + c | 0;
|
38
|
+
a += (b & c | ~b & d) + k[12] + 1804603682 | 0;
|
39
|
+
a = (a << 7 | a >>> 25) + b | 0;
|
40
|
+
d += (a & b | ~a & c) + k[13] - 40341101 | 0;
|
41
|
+
d = (d << 12 | d >>> 20) + a | 0;
|
42
|
+
c += (d & a | ~d & b) + k[14] - 1502002290 | 0;
|
43
|
+
c = (c << 17 | c >>> 15) + d | 0;
|
44
|
+
b += (c & d | ~c & a) + k[15] + 1236535329 | 0;
|
45
|
+
b = (b << 22 | b >>> 10) + c | 0;
|
46
|
+
a += (b & d | c & ~d) + k[1] - 165796510 | 0;
|
47
|
+
a = (a << 5 | a >>> 27) + b | 0;
|
48
|
+
d += (a & c | b & ~c) + k[6] - 1069501632 | 0;
|
49
|
+
d = (d << 9 | d >>> 23) + a | 0;
|
50
|
+
c += (d & b | a & ~b) + k[11] + 643717713 | 0;
|
51
|
+
c = (c << 14 | c >>> 18) + d | 0;
|
52
|
+
b += (c & a | d & ~a) + k[0] - 373897302 | 0;
|
53
|
+
b = (b << 20 | b >>> 12) + c | 0;
|
54
|
+
a += (b & d | c & ~d) + k[5] - 701558691 | 0;
|
55
|
+
a = (a << 5 | a >>> 27) + b | 0;
|
56
|
+
d += (a & c | b & ~c) + k[10] + 38016083 | 0;
|
57
|
+
d = (d << 9 | d >>> 23) + a | 0;
|
58
|
+
c += (d & b | a & ~b) + k[15] - 660478335 | 0;
|
59
|
+
c = (c << 14 | c >>> 18) + d | 0;
|
60
|
+
b += (c & a | d & ~a) + k[4] - 405537848 | 0;
|
61
|
+
b = (b << 20 | b >>> 12) + c | 0;
|
62
|
+
a += (b & d | c & ~d) + k[9] + 568446438 | 0;
|
63
|
+
a = (a << 5 | a >>> 27) + b | 0;
|
64
|
+
d += (a & c | b & ~c) + k[14] - 1019803690 | 0;
|
65
|
+
d = (d << 9 | d >>> 23) + a | 0;
|
66
|
+
c += (d & b | a & ~b) + k[3] - 187363961 | 0;
|
67
|
+
c = (c << 14 | c >>> 18) + d | 0;
|
68
|
+
b += (c & a | d & ~a) + k[8] + 1163531501 | 0;
|
69
|
+
b = (b << 20 | b >>> 12) + c | 0;
|
70
|
+
a += (b & d | c & ~d) + k[13] - 1444681467 | 0;
|
71
|
+
a = (a << 5 | a >>> 27) + b | 0;
|
72
|
+
d += (a & c | b & ~c) + k[2] - 51403784 | 0;
|
73
|
+
d = (d << 9 | d >>> 23) + a | 0;
|
74
|
+
c += (d & b | a & ~b) + k[7] + 1735328473 | 0;
|
75
|
+
c = (c << 14 | c >>> 18) + d | 0;
|
76
|
+
b += (c & a | d & ~a) + k[12] - 1926607734 | 0;
|
77
|
+
b = (b << 20 | b >>> 12) + c | 0;
|
78
|
+
a += (b ^ c ^ d) + k[5] - 378558 | 0;
|
79
|
+
a = (a << 4 | a >>> 28) + b | 0;
|
80
|
+
d += (a ^ b ^ c) + k[8] - 2022574463 | 0;
|
81
|
+
d = (d << 11 | d >>> 21) + a | 0;
|
82
|
+
c += (d ^ a ^ b) + k[11] + 1839030562 | 0;
|
83
|
+
c = (c << 16 | c >>> 16) + d | 0;
|
84
|
+
b += (c ^ d ^ a) + k[14] - 35309556 | 0;
|
85
|
+
b = (b << 23 | b >>> 9) + c | 0;
|
86
|
+
a += (b ^ c ^ d) + k[1] - 1530992060 | 0;
|
87
|
+
a = (a << 4 | a >>> 28) + b | 0;
|
88
|
+
d += (a ^ b ^ c) + k[4] + 1272893353 | 0;
|
89
|
+
d = (d << 11 | d >>> 21) + a | 0;
|
90
|
+
c += (d ^ a ^ b) + k[7] - 155497632 | 0;
|
91
|
+
c = (c << 16 | c >>> 16) + d | 0;
|
92
|
+
b += (c ^ d ^ a) + k[10] - 1094730640 | 0;
|
93
|
+
b = (b << 23 | b >>> 9) + c | 0;
|
94
|
+
a += (b ^ c ^ d) + k[13] + 681279174 | 0;
|
95
|
+
a = (a << 4 | a >>> 28) + b | 0;
|
96
|
+
d += (a ^ b ^ c) + k[0] - 358537222 | 0;
|
97
|
+
d = (d << 11 | d >>> 21) + a | 0;
|
98
|
+
c += (d ^ a ^ b) + k[3] - 722521979 | 0;
|
99
|
+
c = (c << 16 | c >>> 16) + d | 0;
|
100
|
+
b += (c ^ d ^ a) + k[6] + 76029189 | 0;
|
101
|
+
b = (b << 23 | b >>> 9) + c | 0;
|
102
|
+
a += (b ^ c ^ d) + k[9] - 640364487 | 0;
|
103
|
+
a = (a << 4 | a >>> 28) + b | 0;
|
104
|
+
d += (a ^ b ^ c) + k[12] - 421815835 | 0;
|
105
|
+
d = (d << 11 | d >>> 21) + a | 0;
|
106
|
+
c += (d ^ a ^ b) + k[15] + 530742520 | 0;
|
107
|
+
c = (c << 16 | c >>> 16) + d | 0;
|
108
|
+
b += (c ^ d ^ a) + k[2] - 995338651 | 0;
|
109
|
+
b = (b << 23 | b >>> 9) + c | 0;
|
110
|
+
a += (c ^ (b | ~d)) + k[0] - 198630844 | 0;
|
111
|
+
a = (a << 6 | a >>> 26) + b | 0;
|
112
|
+
d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0;
|
113
|
+
d = (d << 10 | d >>> 22) + a | 0;
|
114
|
+
c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0;
|
115
|
+
c = (c << 15 | c >>> 17) + d | 0;
|
116
|
+
b += (d ^ (c | ~a)) + k[5] - 57434055 | 0;
|
117
|
+
b = (b << 21 | b >>> 11) + c | 0;
|
118
|
+
a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0;
|
119
|
+
a = (a << 6 | a >>> 26) + b | 0;
|
120
|
+
d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0;
|
121
|
+
d = (d << 10 | d >>> 22) + a | 0;
|
122
|
+
c += (a ^ (d | ~b)) + k[10] - 1051523 | 0;
|
123
|
+
c = (c << 15 | c >>> 17) + d | 0;
|
124
|
+
b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0;
|
125
|
+
b = (b << 21 | b >>> 11) + c | 0;
|
126
|
+
a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0;
|
127
|
+
a = (a << 6 | a >>> 26) + b | 0;
|
128
|
+
d += (b ^ (a | ~c)) + k[15] - 30611744 | 0;
|
129
|
+
d = (d << 10 | d >>> 22) + a | 0;
|
130
|
+
c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0;
|
131
|
+
c = (c << 15 | c >>> 17) + d | 0;
|
132
|
+
b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0;
|
133
|
+
b = (b << 21 | b >>> 11) + c | 0;
|
134
|
+
a += (c ^ (b | ~d)) + k[4] - 145523070 | 0;
|
135
|
+
a = (a << 6 | a >>> 26) + b | 0;
|
136
|
+
d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0;
|
137
|
+
d = (d << 10 | d >>> 22) + a | 0;
|
138
|
+
c += (a ^ (d | ~b)) + k[2] + 718787259 | 0;
|
139
|
+
c = (c << 15 | c >>> 17) + d | 0;
|
140
|
+
b += (d ^ (c | ~a)) + k[9] - 343485551 | 0;
|
141
|
+
b = (b << 21 | b >>> 11) + c | 0;
|
142
|
+
x[0] = a + x[0] | 0;
|
143
|
+
x[1] = b + x[1] | 0;
|
144
|
+
x[2] = c + x[2] | 0;
|
145
|
+
x[3] = d + x[3] | 0;
|
146
|
+
}
|
147
|
+
function md5blk(s) {
|
148
|
+
var md5blks = [], i;
|
149
|
+
for (i = 0; i < 64; i += 4) {
|
150
|
+
md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
|
151
|
+
}
|
152
|
+
return md5blks;
|
153
|
+
}
|
154
|
+
function md5blk_array(a) {
|
155
|
+
var md5blks = [], i;
|
156
|
+
for (i = 0; i < 64; i += 4) {
|
157
|
+
md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
|
158
|
+
}
|
159
|
+
return md5blks;
|
160
|
+
}
|
161
|
+
function md51(s) {
|
162
|
+
var n = s.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;
|
163
|
+
for (i = 64; i <= n; i += 64) {
|
164
|
+
md5cycle(state, md5blk(s.substring(i - 64, i)));
|
165
|
+
}
|
166
|
+
s = s.substring(i - 64);
|
167
|
+
length = s.length;
|
168
|
+
tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
|
169
|
+
for (i = 0; i < length; i += 1) {
|
170
|
+
tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3);
|
171
|
+
}
|
172
|
+
tail[i >> 2] |= 128 << (i % 4 << 3);
|
173
|
+
if (i > 55) {
|
174
|
+
md5cycle(state, tail);
|
175
|
+
for (i = 0; i < 16; i += 1) {
|
176
|
+
tail[i] = 0;
|
177
|
+
}
|
178
|
+
}
|
179
|
+
tmp = n * 8;
|
180
|
+
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
|
181
|
+
lo = parseInt(tmp[2], 16);
|
182
|
+
hi = parseInt(tmp[1], 16) || 0;
|
183
|
+
tail[14] = lo;
|
184
|
+
tail[15] = hi;
|
185
|
+
md5cycle(state, tail);
|
186
|
+
return state;
|
187
|
+
}
|
188
|
+
function md51_array(a) {
|
189
|
+
var n = a.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;
|
190
|
+
for (i = 64; i <= n; i += 64) {
|
191
|
+
md5cycle(state, md5blk_array(a.subarray(i - 64, i)));
|
192
|
+
}
|
193
|
+
a = i - 64 < n ? a.subarray(i - 64) : new Uint8Array(0);
|
194
|
+
length = a.length;
|
195
|
+
tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
|
196
|
+
for (i = 0; i < length; i += 1) {
|
197
|
+
tail[i >> 2] |= a[i] << (i % 4 << 3);
|
198
|
+
}
|
199
|
+
tail[i >> 2] |= 128 << (i % 4 << 3);
|
200
|
+
if (i > 55) {
|
201
|
+
md5cycle(state, tail);
|
202
|
+
for (i = 0; i < 16; i += 1) {
|
203
|
+
tail[i] = 0;
|
204
|
+
}
|
205
|
+
}
|
206
|
+
tmp = n * 8;
|
207
|
+
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
|
208
|
+
lo = parseInt(tmp[2], 16);
|
209
|
+
hi = parseInt(tmp[1], 16) || 0;
|
210
|
+
tail[14] = lo;
|
211
|
+
tail[15] = hi;
|
212
|
+
md5cycle(state, tail);
|
213
|
+
return state;
|
214
|
+
}
|
215
|
+
function rhex(n) {
|
216
|
+
var s = "", j;
|
217
|
+
for (j = 0; j < 4; j += 1) {
|
218
|
+
s += hex_chr[n >> j * 8 + 4 & 15] + hex_chr[n >> j * 8 & 15];
|
219
|
+
}
|
220
|
+
return s;
|
221
|
+
}
|
222
|
+
function hex(x) {
|
223
|
+
var i;
|
224
|
+
for (i = 0; i < x.length; i += 1) {
|
225
|
+
x[i] = rhex(x[i]);
|
226
|
+
}
|
227
|
+
return x.join("");
|
228
|
+
}
|
229
|
+
if (hex(md51("hello")) !== "5d41402abc4b2a76b9719d911017c592") ;
|
230
|
+
if (typeof ArrayBuffer !== "undefined" && !ArrayBuffer.prototype.slice) {
|
231
|
+
(function() {
|
232
|
+
function clamp(val, length) {
|
233
|
+
val = val | 0 || 0;
|
234
|
+
if (val < 0) {
|
235
|
+
return Math.max(val + length, 0);
|
236
|
+
}
|
237
|
+
return Math.min(val, length);
|
238
|
+
}
|
239
|
+
ArrayBuffer.prototype.slice = function(from, to) {
|
240
|
+
var length = this.byteLength, begin = clamp(from, length), end = length, num, target, targetArray, sourceArray;
|
241
|
+
if (to !== undefined$1) {
|
242
|
+
end = clamp(to, length);
|
243
|
+
}
|
244
|
+
if (begin > end) {
|
245
|
+
return new ArrayBuffer(0);
|
246
|
+
}
|
247
|
+
num = end - begin;
|
248
|
+
target = new ArrayBuffer(num);
|
249
|
+
targetArray = new Uint8Array(target);
|
250
|
+
sourceArray = new Uint8Array(this, begin, num);
|
251
|
+
targetArray.set(sourceArray);
|
252
|
+
return target;
|
253
|
+
};
|
254
|
+
})();
|
255
|
+
}
|
256
|
+
function toUtf8(str) {
|
257
|
+
if (/[\u0080-\uFFFF]/.test(str)) {
|
258
|
+
str = unescape(encodeURIComponent(str));
|
259
|
+
}
|
260
|
+
return str;
|
261
|
+
}
|
262
|
+
function utf8Str2ArrayBuffer(str, returnUInt8Array) {
|
263
|
+
var length = str.length, buff = new ArrayBuffer(length), arr = new Uint8Array(buff), i;
|
264
|
+
for (i = 0; i < length; i += 1) {
|
265
|
+
arr[i] = str.charCodeAt(i);
|
266
|
+
}
|
267
|
+
return returnUInt8Array ? arr : buff;
|
268
|
+
}
|
269
|
+
function arrayBuffer2Utf8Str(buff) {
|
270
|
+
return String.fromCharCode.apply(null, new Uint8Array(buff));
|
271
|
+
}
|
272
|
+
function concatenateArrayBuffers(first, second, returnUInt8Array) {
|
273
|
+
var result = new Uint8Array(first.byteLength + second.byteLength);
|
274
|
+
result.set(new Uint8Array(first));
|
275
|
+
result.set(new Uint8Array(second), first.byteLength);
|
276
|
+
return returnUInt8Array ? result : result.buffer;
|
277
|
+
}
|
278
|
+
function hexToBinaryString(hex) {
|
279
|
+
var bytes = [], length = hex.length, x;
|
280
|
+
for (x = 0; x < length - 1; x += 2) {
|
281
|
+
bytes.push(parseInt(hex.substr(x, 2), 16));
|
282
|
+
}
|
283
|
+
return String.fromCharCode.apply(String, bytes);
|
284
|
+
}
|
285
|
+
function SparkMD5() {
|
286
|
+
this.reset();
|
287
|
+
}
|
288
|
+
SparkMD5.prototype.append = function(str) {
|
289
|
+
this.appendBinary(toUtf8(str));
|
290
|
+
return this;
|
291
|
+
};
|
292
|
+
SparkMD5.prototype.appendBinary = function(contents) {
|
293
|
+
this._buff += contents;
|
294
|
+
this._length += contents.length;
|
295
|
+
var length = this._buff.length, i;
|
296
|
+
for (i = 64; i <= length; i += 64) {
|
297
|
+
md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i)));
|
298
|
+
}
|
299
|
+
this._buff = this._buff.substring(i - 64);
|
300
|
+
return this;
|
301
|
+
};
|
302
|
+
SparkMD5.prototype.end = function(raw) {
|
303
|
+
var buff = this._buff, length = buff.length, i, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], ret;
|
304
|
+
for (i = 0; i < length; i += 1) {
|
305
|
+
tail[i >> 2] |= buff.charCodeAt(i) << (i % 4 << 3);
|
306
|
+
}
|
307
|
+
this._finish(tail, length);
|
308
|
+
ret = hex(this._hash);
|
309
|
+
if (raw) {
|
310
|
+
ret = hexToBinaryString(ret);
|
311
|
+
}
|
312
|
+
this.reset();
|
313
|
+
return ret;
|
314
|
+
};
|
315
|
+
SparkMD5.prototype.reset = function() {
|
316
|
+
this._buff = "";
|
317
|
+
this._length = 0;
|
318
|
+
this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];
|
319
|
+
return this;
|
320
|
+
};
|
321
|
+
SparkMD5.prototype.getState = function() {
|
322
|
+
return {
|
323
|
+
buff: this._buff,
|
324
|
+
length: this._length,
|
325
|
+
hash: this._hash.slice()
|
326
|
+
};
|
327
|
+
};
|
328
|
+
SparkMD5.prototype.setState = function(state) {
|
329
|
+
this._buff = state.buff;
|
330
|
+
this._length = state.length;
|
331
|
+
this._hash = state.hash;
|
332
|
+
return this;
|
333
|
+
};
|
334
|
+
SparkMD5.prototype.destroy = function() {
|
335
|
+
delete this._hash;
|
336
|
+
delete this._buff;
|
337
|
+
delete this._length;
|
338
|
+
};
|
339
|
+
SparkMD5.prototype._finish = function(tail, length) {
|
340
|
+
var i = length, tmp, lo, hi;
|
341
|
+
tail[i >> 2] |= 128 << (i % 4 << 3);
|
342
|
+
if (i > 55) {
|
343
|
+
md5cycle(this._hash, tail);
|
344
|
+
for (i = 0; i < 16; i += 1) {
|
345
|
+
tail[i] = 0;
|
346
|
+
}
|
347
|
+
}
|
348
|
+
tmp = this._length * 8;
|
349
|
+
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
|
350
|
+
lo = parseInt(tmp[2], 16);
|
351
|
+
hi = parseInt(tmp[1], 16) || 0;
|
352
|
+
tail[14] = lo;
|
353
|
+
tail[15] = hi;
|
354
|
+
md5cycle(this._hash, tail);
|
355
|
+
};
|
356
|
+
SparkMD5.hash = function(str, raw) {
|
357
|
+
return SparkMD5.hashBinary(toUtf8(str), raw);
|
358
|
+
};
|
359
|
+
SparkMD5.hashBinary = function(content, raw) {
|
360
|
+
var hash = md51(content), ret = hex(hash);
|
361
|
+
return raw ? hexToBinaryString(ret) : ret;
|
362
|
+
};
|
363
|
+
SparkMD5.ArrayBuffer = function() {
|
364
|
+
this.reset();
|
365
|
+
};
|
366
|
+
SparkMD5.ArrayBuffer.prototype.append = function(arr) {
|
367
|
+
var buff = concatenateArrayBuffers(this._buff.buffer, arr, true), length = buff.length, i;
|
368
|
+
this._length += arr.byteLength;
|
369
|
+
for (i = 64; i <= length; i += 64) {
|
370
|
+
md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i)));
|
371
|
+
}
|
372
|
+
this._buff = i - 64 < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0);
|
373
|
+
return this;
|
374
|
+
};
|
375
|
+
SparkMD5.ArrayBuffer.prototype.end = function(raw) {
|
376
|
+
var buff = this._buff, length = buff.length, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], i, ret;
|
377
|
+
for (i = 0; i < length; i += 1) {
|
378
|
+
tail[i >> 2] |= buff[i] << (i % 4 << 3);
|
379
|
+
}
|
380
|
+
this._finish(tail, length);
|
381
|
+
ret = hex(this._hash);
|
382
|
+
if (raw) {
|
383
|
+
ret = hexToBinaryString(ret);
|
384
|
+
}
|
385
|
+
this.reset();
|
386
|
+
return ret;
|
387
|
+
};
|
388
|
+
SparkMD5.ArrayBuffer.prototype.reset = function() {
|
389
|
+
this._buff = new Uint8Array(0);
|
390
|
+
this._length = 0;
|
391
|
+
this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];
|
392
|
+
return this;
|
393
|
+
};
|
394
|
+
SparkMD5.ArrayBuffer.prototype.getState = function() {
|
395
|
+
var state = SparkMD5.prototype.getState.call(this);
|
396
|
+
state.buff = arrayBuffer2Utf8Str(state.buff);
|
397
|
+
return state;
|
398
|
+
};
|
399
|
+
SparkMD5.ArrayBuffer.prototype.setState = function(state) {
|
400
|
+
state.buff = utf8Str2ArrayBuffer(state.buff, true);
|
401
|
+
return SparkMD5.prototype.setState.call(this, state);
|
402
|
+
};
|
403
|
+
SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;
|
404
|
+
SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;
|
405
|
+
SparkMD5.ArrayBuffer.hash = function(arr, raw) {
|
406
|
+
var hash = md51_array(new Uint8Array(arr)), ret = hex(hash);
|
407
|
+
return raw ? hexToBinaryString(ret) : ret;
|
408
|
+
};
|
409
|
+
return SparkMD5;
|
410
|
+
}));
|
411
|
+
})(sparkMd5);
|
412
|
+
|
413
|
+
var SparkMD5 = sparkMd5.exports;
|
414
|
+
|
415
|
+
const fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
|
416
|
+
|
417
|
+
class FileChecksum {
|
418
|
+
static create(file, callback) {
|
419
|
+
const instance = new FileChecksum(file);
|
420
|
+
instance.create(callback);
|
421
|
+
}
|
422
|
+
constructor(file) {
|
423
|
+
this.file = file;
|
424
|
+
this.chunkSize = 2097152;
|
425
|
+
this.chunkCount = Math.ceil(this.file.size / this.chunkSize);
|
426
|
+
this.chunkIndex = 0;
|
427
|
+
}
|
428
|
+
create(callback) {
|
429
|
+
this.callback = callback;
|
430
|
+
this.md5Buffer = new SparkMD5.ArrayBuffer;
|
431
|
+
this.fileReader = new FileReader;
|
432
|
+
this.fileReader.addEventListener("load", (event => this.fileReaderDidLoad(event)));
|
433
|
+
this.fileReader.addEventListener("error", (event => this.fileReaderDidError(event)));
|
434
|
+
this.readNextChunk();
|
435
|
+
}
|
436
|
+
fileReaderDidLoad(event) {
|
437
|
+
this.md5Buffer.append(event.target.result);
|
438
|
+
if (!this.readNextChunk()) {
|
439
|
+
const binaryDigest = this.md5Buffer.end(true);
|
440
|
+
const base64digest = btoa(binaryDigest);
|
441
|
+
this.callback(null, base64digest);
|
442
|
+
}
|
443
|
+
}
|
444
|
+
fileReaderDidError(event) {
|
445
|
+
this.callback(`Error reading ${this.file.name}`);
|
446
|
+
}
|
447
|
+
readNextChunk() {
|
448
|
+
if (this.chunkIndex < this.chunkCount || this.chunkIndex == 0 && this.chunkCount == 0) {
|
449
|
+
const start = this.chunkIndex * this.chunkSize;
|
450
|
+
const end = Math.min(start + this.chunkSize, this.file.size);
|
451
|
+
const bytes = fileSlice.call(this.file, start, end);
|
452
|
+
this.fileReader.readAsArrayBuffer(bytes);
|
453
|
+
this.chunkIndex++;
|
454
|
+
return true;
|
455
|
+
} else {
|
456
|
+
return false;
|
457
|
+
}
|
458
|
+
}
|
459
|
+
}
|
460
|
+
|
461
|
+
function getMetaValue(name) {
|
462
|
+
const element = findElement(document.head, `meta[name="${name}"]`);
|
463
|
+
if (element) {
|
464
|
+
return element.getAttribute("content");
|
465
|
+
}
|
466
|
+
}
|
467
|
+
|
468
|
+
function findElements(root, selector) {
|
469
|
+
if (typeof root == "string") {
|
470
|
+
selector = root;
|
471
|
+
root = document;
|
472
|
+
}
|
473
|
+
const elements = root.querySelectorAll(selector);
|
474
|
+
return toArray(elements);
|
475
|
+
}
|
476
|
+
|
477
|
+
function findElement(root, selector) {
|
478
|
+
if (typeof root == "string") {
|
479
|
+
selector = root;
|
480
|
+
root = document;
|
481
|
+
}
|
482
|
+
return root.querySelector(selector);
|
483
|
+
}
|
484
|
+
|
485
|
+
function dispatchEvent(element, type, eventInit = {}) {
|
486
|
+
const {disabled: disabled} = element;
|
487
|
+
const {bubbles: bubbles, cancelable: cancelable, detail: detail} = eventInit;
|
488
|
+
const event = document.createEvent("Event");
|
489
|
+
event.initEvent(type, bubbles || true, cancelable || true);
|
490
|
+
event.detail = detail || {};
|
491
|
+
try {
|
492
|
+
element.disabled = false;
|
493
|
+
element.dispatchEvent(event);
|
494
|
+
} finally {
|
495
|
+
element.disabled = disabled;
|
496
|
+
}
|
497
|
+
return event;
|
498
|
+
}
|
499
|
+
|
500
|
+
function toArray(value) {
|
501
|
+
if (Array.isArray(value)) {
|
502
|
+
return value;
|
503
|
+
} else if (Array.from) {
|
504
|
+
return Array.from(value);
|
505
|
+
} else {
|
506
|
+
return [].slice.call(value);
|
507
|
+
}
|
508
|
+
}
|
509
|
+
|
510
|
+
class BlobRecord {
|
511
|
+
constructor(file, checksum, url) {
|
512
|
+
this.file = file;
|
513
|
+
this.attributes = {
|
514
|
+
filename: file.name,
|
515
|
+
content_type: file.type || "application/octet-stream",
|
516
|
+
byte_size: file.size,
|
517
|
+
checksum: checksum
|
518
|
+
};
|
519
|
+
this.xhr = new XMLHttpRequest;
|
520
|
+
this.xhr.open("POST", url, true);
|
521
|
+
this.xhr.responseType = "json";
|
522
|
+
this.xhr.setRequestHeader("Content-Type", "application/json");
|
523
|
+
this.xhr.setRequestHeader("Accept", "application/json");
|
524
|
+
this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
525
|
+
const csrfToken = getMetaValue("csrf-token");
|
526
|
+
if (csrfToken != undefined) {
|
527
|
+
this.xhr.setRequestHeader("X-CSRF-Token", csrfToken);
|
528
|
+
}
|
529
|
+
this.xhr.addEventListener("load", (event => this.requestDidLoad(event)));
|
530
|
+
this.xhr.addEventListener("error", (event => this.requestDidError(event)));
|
531
|
+
}
|
532
|
+
get status() {
|
533
|
+
return this.xhr.status;
|
534
|
+
}
|
535
|
+
get response() {
|
536
|
+
const {responseType: responseType, response: response} = this.xhr;
|
537
|
+
if (responseType == "json") {
|
538
|
+
return response;
|
539
|
+
} else {
|
540
|
+
return JSON.parse(response);
|
541
|
+
}
|
542
|
+
}
|
543
|
+
create(callback) {
|
544
|
+
this.callback = callback;
|
545
|
+
this.xhr.send(JSON.stringify({
|
546
|
+
blob: this.attributes
|
547
|
+
}));
|
548
|
+
}
|
549
|
+
requestDidLoad(event) {
|
550
|
+
if (this.status >= 200 && this.status < 300) {
|
551
|
+
const {response: response} = this;
|
552
|
+
const {direct_upload: direct_upload} = response;
|
553
|
+
delete response.direct_upload;
|
554
|
+
this.attributes = response;
|
555
|
+
this.directUploadData = direct_upload;
|
556
|
+
this.callback(null, this.toJSON());
|
557
|
+
} else {
|
558
|
+
this.requestDidError(event);
|
559
|
+
}
|
560
|
+
}
|
561
|
+
requestDidError(event) {
|
562
|
+
this.callback(`Error creating Blob for "${this.file.name}". Status: ${this.status}`);
|
563
|
+
}
|
564
|
+
toJSON() {
|
565
|
+
const result = {};
|
566
|
+
for (const key in this.attributes) {
|
567
|
+
result[key] = this.attributes[key];
|
568
|
+
}
|
569
|
+
return result;
|
570
|
+
}
|
571
|
+
}
|
572
|
+
|
573
|
+
class BlobUpload {
|
574
|
+
constructor(blob) {
|
575
|
+
this.blob = blob;
|
576
|
+
this.file = blob.file;
|
577
|
+
const {url: url, headers: headers} = blob.directUploadData;
|
578
|
+
this.xhr = new XMLHttpRequest;
|
579
|
+
this.xhr.open("PUT", url, true);
|
580
|
+
this.xhr.responseType = "text";
|
581
|
+
for (const key in headers) {
|
582
|
+
this.xhr.setRequestHeader(key, headers[key]);
|
583
|
+
}
|
584
|
+
this.xhr.addEventListener("load", (event => this.requestDidLoad(event)));
|
585
|
+
this.xhr.addEventListener("error", (event => this.requestDidError(event)));
|
586
|
+
}
|
587
|
+
create(callback) {
|
588
|
+
this.callback = callback;
|
589
|
+
this.xhr.send(this.file.slice());
|
590
|
+
}
|
591
|
+
requestDidLoad(event) {
|
592
|
+
const {status: status, response: response} = this.xhr;
|
593
|
+
if (status >= 200 && status < 300) {
|
594
|
+
this.callback(null, response);
|
595
|
+
} else {
|
596
|
+
this.requestDidError(event);
|
597
|
+
}
|
598
|
+
}
|
599
|
+
requestDidError(event) {
|
600
|
+
this.callback(`Error storing "${this.file.name}". Status: ${this.xhr.status}`);
|
601
|
+
}
|
602
|
+
}
|
603
|
+
|
604
|
+
let id = 0;
|
605
|
+
|
606
|
+
class DirectUpload {
|
607
|
+
constructor(file, url, delegate) {
|
608
|
+
this.id = ++id;
|
609
|
+
this.file = file;
|
610
|
+
this.url = url;
|
611
|
+
this.delegate = delegate;
|
612
|
+
}
|
613
|
+
create(callback) {
|
614
|
+
FileChecksum.create(this.file, ((error, checksum) => {
|
615
|
+
if (error) {
|
616
|
+
callback(error);
|
617
|
+
return;
|
618
|
+
}
|
619
|
+
const blob = new BlobRecord(this.file, checksum, this.url);
|
620
|
+
notify(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr);
|
621
|
+
blob.create((error => {
|
622
|
+
if (error) {
|
623
|
+
callback(error);
|
624
|
+
} else {
|
625
|
+
const upload = new BlobUpload(blob);
|
626
|
+
notify(this.delegate, "directUploadWillStoreFileWithXHR", upload.xhr);
|
627
|
+
upload.create((error => {
|
628
|
+
if (error) {
|
629
|
+
callback(error);
|
630
|
+
} else {
|
631
|
+
callback(null, blob.toJSON());
|
632
|
+
}
|
633
|
+
}));
|
634
|
+
}
|
635
|
+
}));
|
636
|
+
}));
|
637
|
+
}
|
638
|
+
}
|
639
|
+
|
640
|
+
function notify(object, methodName, ...messages) {
|
641
|
+
if (object && typeof object[methodName] == "function") {
|
642
|
+
return object[methodName](...messages);
|
643
|
+
}
|
644
|
+
}
|
645
|
+
|
646
|
+
class DirectUploadController {
|
647
|
+
constructor(input, file) {
|
648
|
+
this.input = input;
|
649
|
+
this.file = file;
|
650
|
+
this.directUpload = new DirectUpload(this.file, this.url, this);
|
651
|
+
this.dispatch("initialize");
|
652
|
+
}
|
653
|
+
start(callback) {
|
654
|
+
const hiddenInput = document.createElement("input");
|
655
|
+
hiddenInput.type = "hidden";
|
656
|
+
hiddenInput.name = this.input.name;
|
657
|
+
this.input.insertAdjacentElement("beforebegin", hiddenInput);
|
658
|
+
this.dispatch("start");
|
659
|
+
this.directUpload.create(((error, attributes) => {
|
660
|
+
if (error) {
|
661
|
+
hiddenInput.parentNode.removeChild(hiddenInput);
|
662
|
+
this.dispatchError(error);
|
663
|
+
} else {
|
664
|
+
hiddenInput.value = attributes.signed_id;
|
665
|
+
}
|
666
|
+
this.dispatch("end");
|
667
|
+
callback(error);
|
668
|
+
}));
|
669
|
+
}
|
670
|
+
uploadRequestDidProgress(event) {
|
671
|
+
const progress = event.loaded / event.total * 100;
|
672
|
+
if (progress) {
|
673
|
+
this.dispatch("progress", {
|
674
|
+
progress: progress
|
675
|
+
});
|
676
|
+
}
|
677
|
+
}
|
678
|
+
get url() {
|
679
|
+
return this.input.getAttribute("data-direct-upload-url");
|
680
|
+
}
|
681
|
+
dispatch(name, detail = {}) {
|
682
|
+
detail.file = this.file;
|
683
|
+
detail.id = this.directUpload.id;
|
684
|
+
return dispatchEvent(this.input, `direct-upload:${name}`, {
|
685
|
+
detail: detail
|
686
|
+
});
|
687
|
+
}
|
688
|
+
dispatchError(error) {
|
689
|
+
const event = this.dispatch("error", {
|
690
|
+
error: error
|
691
|
+
});
|
692
|
+
if (!event.defaultPrevented) {
|
693
|
+
alert(error);
|
694
|
+
}
|
695
|
+
}
|
696
|
+
directUploadWillCreateBlobWithXHR(xhr) {
|
697
|
+
this.dispatch("before-blob-request", {
|
698
|
+
xhr: xhr
|
699
|
+
});
|
700
|
+
}
|
701
|
+
directUploadWillStoreFileWithXHR(xhr) {
|
702
|
+
this.dispatch("before-storage-request", {
|
703
|
+
xhr: xhr
|
704
|
+
});
|
705
|
+
xhr.upload.addEventListener("progress", (event => this.uploadRequestDidProgress(event)));
|
706
|
+
}
|
707
|
+
}
|
708
|
+
|
709
|
+
const inputSelector = "input[type=file][data-direct-upload-url]:not([disabled])";
|
710
|
+
|
711
|
+
class DirectUploadsController {
|
712
|
+
constructor(form) {
|
713
|
+
this.form = form;
|
714
|
+
this.inputs = findElements(form, inputSelector).filter((input => input.files.length));
|
715
|
+
}
|
716
|
+
start(callback) {
|
717
|
+
const controllers = this.createDirectUploadControllers();
|
718
|
+
const startNextController = () => {
|
719
|
+
const controller = controllers.shift();
|
720
|
+
if (controller) {
|
721
|
+
controller.start((error => {
|
722
|
+
if (error) {
|
723
|
+
callback(error);
|
724
|
+
this.dispatch("end");
|
725
|
+
} else {
|
726
|
+
startNextController();
|
727
|
+
}
|
728
|
+
}));
|
729
|
+
} else {
|
730
|
+
callback();
|
731
|
+
this.dispatch("end");
|
732
|
+
}
|
733
|
+
};
|
734
|
+
this.dispatch("start");
|
735
|
+
startNextController();
|
736
|
+
}
|
737
|
+
createDirectUploadControllers() {
|
738
|
+
const controllers = [];
|
739
|
+
this.inputs.forEach((input => {
|
740
|
+
toArray(input.files).forEach((file => {
|
741
|
+
const controller = new DirectUploadController(input, file);
|
742
|
+
controllers.push(controller);
|
743
|
+
}));
|
744
|
+
}));
|
745
|
+
return controllers;
|
746
|
+
}
|
747
|
+
dispatch(name, detail = {}) {
|
748
|
+
return dispatchEvent(this.form, `direct-uploads:${name}`, {
|
749
|
+
detail: detail
|
750
|
+
});
|
751
|
+
}
|
752
|
+
}
|
753
|
+
|
754
|
+
const processingAttribute = "data-direct-uploads-processing";
|
755
|
+
|
756
|
+
const submitButtonsByForm = new WeakMap;
|
757
|
+
|
758
|
+
let started = false;
|
759
|
+
|
760
|
+
function start() {
|
761
|
+
if (!started) {
|
762
|
+
started = true;
|
763
|
+
document.addEventListener("click", didClick, true);
|
764
|
+
document.addEventListener("submit", didSubmitForm, true);
|
765
|
+
document.addEventListener("ajax:before", didSubmitRemoteElement);
|
766
|
+
}
|
767
|
+
}
|
768
|
+
|
769
|
+
function didClick(event) {
|
770
|
+
const {target: target} = event;
|
771
|
+
if ((target.tagName == "INPUT" || target.tagName == "BUTTON") && target.type == "submit" && target.form) {
|
772
|
+
submitButtonsByForm.set(target.form, target);
|
773
|
+
}
|
774
|
+
}
|
775
|
+
|
776
|
+
function didSubmitForm(event) {
|
777
|
+
handleFormSubmissionEvent(event);
|
778
|
+
}
|
779
|
+
|
780
|
+
function didSubmitRemoteElement(event) {
|
781
|
+
if (event.target.tagName == "FORM") {
|
782
|
+
handleFormSubmissionEvent(event);
|
783
|
+
}
|
784
|
+
}
|
785
|
+
|
786
|
+
function handleFormSubmissionEvent(event) {
|
787
|
+
const form = event.target;
|
788
|
+
if (form.hasAttribute(processingAttribute)) {
|
789
|
+
event.preventDefault();
|
790
|
+
return;
|
791
|
+
}
|
792
|
+
const controller = new DirectUploadsController(form);
|
793
|
+
const {inputs: inputs} = controller;
|
794
|
+
if (inputs.length) {
|
795
|
+
event.preventDefault();
|
796
|
+
form.setAttribute(processingAttribute, "");
|
797
|
+
inputs.forEach(disable);
|
798
|
+
controller.start((error => {
|
799
|
+
form.removeAttribute(processingAttribute);
|
800
|
+
if (error) {
|
801
|
+
inputs.forEach(enable);
|
802
|
+
} else {
|
803
|
+
submitForm(form);
|
804
|
+
}
|
805
|
+
}));
|
806
|
+
}
|
807
|
+
}
|
808
|
+
|
809
|
+
function submitForm(form) {
|
810
|
+
let button = submitButtonsByForm.get(form) || findElement(form, "input[type=submit], button[type=submit]");
|
811
|
+
if (button) {
|
812
|
+
const {disabled: disabled} = button;
|
813
|
+
button.disabled = false;
|
814
|
+
button.focus();
|
815
|
+
button.click();
|
816
|
+
button.disabled = disabled;
|
817
|
+
} else {
|
818
|
+
button = document.createElement("input");
|
819
|
+
button.type = "submit";
|
820
|
+
button.style.display = "none";
|
821
|
+
form.appendChild(button);
|
822
|
+
button.click();
|
823
|
+
form.removeChild(button);
|
824
|
+
}
|
825
|
+
submitButtonsByForm.delete(form);
|
826
|
+
}
|
827
|
+
|
828
|
+
function disable(input) {
|
829
|
+
input.disabled = true;
|
830
|
+
}
|
831
|
+
|
832
|
+
function enable(input) {
|
833
|
+
input.disabled = false;
|
834
|
+
}
|
835
|
+
|
836
|
+
function autostart() {
|
837
|
+
if (window.ActiveStorage) {
|
838
|
+
start();
|
839
|
+
}
|
840
|
+
}
|
841
|
+
|
842
|
+
setTimeout(autostart, 1);
|
843
|
+
|
844
|
+
export { DirectUpload, start };
|