glebtv-rails-uploader 0.1.3 → 0.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.
- checksums.yaml +7 -0
- data/README.md +17 -10
- data/{vendor → app}/assets/images/uploader/but_del_tag2.png +0 -0
- data/{vendor → app}/assets/images/uploader/ico_attach.png +0 -0
- data/{vendor → app}/assets/images/uploader/preloader.gif +0 -0
- data/{vendor → app}/assets/images/uploader/progressBarFillBg.png +0 -0
- data/app/assets/javascripts/uploader/application.js +2 -2
- data/app/assets/javascripts/uploader/canvas-to-blob.js +95 -0
- data/app/assets/javascripts/uploader/jquery.fileupload-angular.js +348 -0
- data/app/assets/javascripts/uploader/jquery.fileupload-process.js +158 -0
- data/app/assets/javascripts/uploader/jquery.fileupload-resize.js +212 -0
- data/{vendor → app}/assets/javascripts/uploader/jquery.fileupload-ui.js +265 -269
- data/app/assets/javascripts/uploader/jquery.fileupload-validate.js +116 -0
- data/{vendor → app}/assets/javascripts/uploader/jquery.fileupload.js +655 -258
- data/{vendor → app}/assets/javascripts/uploader/jquery.iframe-transport.js +29 -9
- data/app/assets/javascripts/uploader/jquery.ui.widget.js +530 -0
- data/app/assets/javascripts/uploader/load-image.js +381 -0
- data/{vendor → app}/assets/javascripts/uploader/locales/en.js +0 -0
- data/{vendor → app}/assets/javascripts/uploader/locales/ru.js +0 -0
- data/{vendor → app}/assets/javascripts/uploader/locales/uk.js +0 -0
- data/app/assets/javascripts/uploader/rails_admin.js +26 -24
- data/app/assets/javascripts/uploader/tmpl.js +86 -0
- data/{vendor → app}/assets/stylesheets/uploader/default.css +0 -0
- data/{vendor → app}/assets/stylesheets/uploader/jquery.fileupload-ui.css +0 -0
- data/app/controllers/uploader/attachments_controller.rb +13 -10
- data/app/views/rails_admin/main/_form_rails_uploader.haml +9 -9
- data/app/views/uploader/default/_container.html.erb +1 -2
- data/app/views/uploader/default/_download.html.erb +1 -1
- data/lib/uploader/asset.rb +2 -2
- data/lib/uploader/engine.rb +4 -4
- data/lib/uploader/fileuploads.rb +18 -18
- data/lib/uploader/helpers/field_tag.rb +16 -17
- data/lib/uploader/helpers/form_builder.rb +1 -1
- data/lib/uploader/helpers/form_tag_helper.rb +1 -1
- data/lib/uploader/hooks/formtastic.rb +1 -2
- data/lib/uploader/rails_admin/field.rb +27 -27
- data/lib/uploader/version.rb +1 -1
- metadata +115 -131
- data/vendor/assets/javascripts/uploader/jquery.fileupload-ip.js +0 -160
- data/vendor/assets/javascripts/uploader/jquery.ui.widget.js +0 -282
- data/vendor/assets/javascripts/uploader/load-image.min.js +0 -1
- data/vendor/assets/javascripts/uploader/tmpl.min.js +0 -1
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7d583687777e18cb84615643e8d052d340b42fc2
|
4
|
+
data.tar.gz: 736689da394ccc26adb783a08ba1914f1a196a29
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 93268c2f5c15e9c184e389174e309dae458ddb0c776063e6cbc8f54d3b74e6ea78811e1bbc42719e3ad7063908a341a6ecf2c0eb0c7c0b1381c6e888c76cc96d
|
7
|
+
data.tar.gz: 19d7de68f7c36612dfcd58b3a195eab73787e3d6ef609b8ed084294fec1331b2da9ae441dac35aadfeb291f8eae8d25ecb308d253c2bdfea059332342b9c6ed7
|
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
|
1
|
+
## this fork adds mongoid and rails_admin support
|
2
2
|
|
3
3
|
This fork works when both simple form and formtastic are loaded
|
4
4
|
|
5
5
|
Also nested associations are working
|
6
6
|
|
7
|
-
|
7
|
+
## HTML5 File uploader for rails
|
8
8
|
|
9
9
|
This gem use https://github.com/blueimp/jQuery-File-Upload for upload files.
|
10
10
|
|
@@ -37,8 +37,15 @@ mount Uploader::Engine => '/uploader'
|
|
37
37
|
|
38
38
|
field :guid, type: String
|
39
39
|
belongs_to :assetable, polymorphic: true
|
40
|
+
|
41
|
+
# this workaround is sometimes needed so IDs are ObjectIDs not strings before_save do
|
42
|
+
if !assetable_id.blank? && !assetable_id.class.name == "Moped::BSON::ObjectId" && Moped::BSON::ObjectId.legal?(assetable_id)
|
43
|
+
self.assetable_id = Moped::BSON::ObjectId.from_string(assetable_id)
|
44
|
+
end
|
45
|
+
true
|
40
46
|
end
|
41
|
-
|
47
|
+
end
|
48
|
+
```
|
42
49
|
|
43
50
|
### Your asset model
|
44
51
|
``` ruby
|
@@ -142,10 +149,10 @@ Architecture to store uploaded files (cancan integration):
|
|
142
149
|
``` ruby
|
143
150
|
class Asset < ActiveRecord::Base
|
144
151
|
include Uploader::Asset
|
145
|
-
|
152
|
+
|
146
153
|
def uploader_create(params, request = nil)
|
147
154
|
ability = Ability.new(request.env['warden'].user)
|
148
|
-
|
155
|
+
|
149
156
|
if ability.can? :create, self
|
150
157
|
self.user = request.env['warden'].user
|
151
158
|
super
|
@@ -153,10 +160,10 @@ class Asset < ActiveRecord::Base
|
|
153
160
|
errors.add(:id, :access_denied)
|
154
161
|
end
|
155
162
|
end
|
156
|
-
|
163
|
+
|
157
164
|
def uploader_destroy(params, request = nil)
|
158
165
|
ability = Ability.new(request.env['warden'].user)
|
159
|
-
|
166
|
+
|
160
167
|
if ability.can? :delete, self
|
161
168
|
super
|
162
169
|
else
|
@@ -167,7 +174,7 @@ end
|
|
167
174
|
|
168
175
|
class Picture < Asset
|
169
176
|
mount_uploader :data, PictureUploader
|
170
|
-
|
177
|
+
|
171
178
|
validates_integrity_of :data
|
172
179
|
validates_filesize_of :data, :maximum => 2.megabytes.to_i
|
173
180
|
end
|
@@ -178,7 +185,7 @@ For example user has one picture:
|
|
178
185
|
``` ruby
|
179
186
|
class User < ActiveRecord::Base
|
180
187
|
has_one :picture, :as => :assetable, :dependent => :destroy
|
181
|
-
|
188
|
+
|
182
189
|
fileuploads :picture
|
183
190
|
|
184
191
|
# If your don't use strong_parameters, uncomment next line
|
@@ -203,7 +210,7 @@ Javascripts:
|
|
203
210
|
Stylesheets:
|
204
211
|
|
205
212
|
``` ruby
|
206
|
-
*= require uploader/application
|
213
|
+
*= require uploader/application
|
207
214
|
```
|
208
215
|
|
209
216
|
### Views
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -1,6 +1,6 @@
|
|
1
1
|
//= require uploader/locales/en
|
2
|
-
//= require uploader/tmpl
|
3
|
-
//= require uploader/load-image
|
2
|
+
//= require uploader/tmpl
|
3
|
+
//= require uploader/load-image
|
4
4
|
//= require uploader/jquery.ui.widget
|
5
5
|
//= require uploader/jquery.iframe-transport
|
6
6
|
//= require uploader/jquery.fileupload
|
@@ -0,0 +1,95 @@
|
|
1
|
+
/*
|
2
|
+
* JavaScript Canvas to Blob 2.0.5
|
3
|
+
* https://github.com/blueimp/JavaScript-Canvas-to-Blob
|
4
|
+
*
|
5
|
+
* Copyright 2012, Sebastian Tschan
|
6
|
+
* https://blueimp.net
|
7
|
+
*
|
8
|
+
* Licensed under the MIT license:
|
9
|
+
* http://www.opensource.org/licenses/MIT
|
10
|
+
*
|
11
|
+
* Based on stackoverflow user Stoive's code snippet:
|
12
|
+
* http://stackoverflow.com/q/4998908
|
13
|
+
*/
|
14
|
+
|
15
|
+
/*jslint nomen: true, regexp: true */
|
16
|
+
/*global window, atob, Blob, ArrayBuffer, Uint8Array, define */
|
17
|
+
|
18
|
+
(function (window) {
|
19
|
+
'use strict';
|
20
|
+
var CanvasPrototype = window.HTMLCanvasElement &&
|
21
|
+
window.HTMLCanvasElement.prototype,
|
22
|
+
hasBlobConstructor = window.Blob && (function () {
|
23
|
+
try {
|
24
|
+
return Boolean(new Blob());
|
25
|
+
} catch (e) {
|
26
|
+
return false;
|
27
|
+
}
|
28
|
+
}()),
|
29
|
+
hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array &&
|
30
|
+
(function () {
|
31
|
+
try {
|
32
|
+
return new Blob([new Uint8Array(100)]).size === 100;
|
33
|
+
} catch (e) {
|
34
|
+
return false;
|
35
|
+
}
|
36
|
+
}()),
|
37
|
+
BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder ||
|
38
|
+
window.MozBlobBuilder || window.MSBlobBuilder,
|
39
|
+
dataURLtoBlob = (hasBlobConstructor || BlobBuilder) && window.atob &&
|
40
|
+
window.ArrayBuffer && window.Uint8Array && function (dataURI) {
|
41
|
+
var byteString,
|
42
|
+
arrayBuffer,
|
43
|
+
intArray,
|
44
|
+
i,
|
45
|
+
mimeString,
|
46
|
+
bb;
|
47
|
+
if (dataURI.split(',')[0].indexOf('base64') >= 0) {
|
48
|
+
// Convert base64 to raw binary data held in a string:
|
49
|
+
byteString = atob(dataURI.split(',')[1]);
|
50
|
+
} else {
|
51
|
+
// Convert base64/URLEncoded data component to raw binary data:
|
52
|
+
byteString = decodeURIComponent(dataURI.split(',')[1]);
|
53
|
+
}
|
54
|
+
// Write the bytes of the string to an ArrayBuffer:
|
55
|
+
arrayBuffer = new ArrayBuffer(byteString.length);
|
56
|
+
intArray = new Uint8Array(arrayBuffer);
|
57
|
+
for (i = 0; i < byteString.length; i += 1) {
|
58
|
+
intArray[i] = byteString.charCodeAt(i);
|
59
|
+
}
|
60
|
+
// Separate out the mime component:
|
61
|
+
mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
|
62
|
+
// Write the ArrayBuffer (or ArrayBufferView) to a blob:
|
63
|
+
if (hasBlobConstructor) {
|
64
|
+
return new Blob(
|
65
|
+
[hasArrayBufferViewSupport ? intArray : arrayBuffer],
|
66
|
+
{type: mimeString}
|
67
|
+
);
|
68
|
+
}
|
69
|
+
bb = new BlobBuilder();
|
70
|
+
bb.append(arrayBuffer);
|
71
|
+
return bb.getBlob(mimeString);
|
72
|
+
};
|
73
|
+
if (window.HTMLCanvasElement && !CanvasPrototype.toBlob) {
|
74
|
+
if (CanvasPrototype.mozGetAsFile) {
|
75
|
+
CanvasPrototype.toBlob = function (callback, type, quality) {
|
76
|
+
if (quality && CanvasPrototype.toDataURL && dataURLtoBlob) {
|
77
|
+
callback(dataURLtoBlob(this.toDataURL(type, quality)));
|
78
|
+
} else {
|
79
|
+
callback(this.mozGetAsFile('blob', type));
|
80
|
+
}
|
81
|
+
};
|
82
|
+
} else if (CanvasPrototype.toDataURL && dataURLtoBlob) {
|
83
|
+
CanvasPrototype.toBlob = function (callback, type, quality) {
|
84
|
+
callback(dataURLtoBlob(this.toDataURL(type, quality)));
|
85
|
+
};
|
86
|
+
}
|
87
|
+
}
|
88
|
+
if (typeof define === 'function' && define.amd) {
|
89
|
+
define(function () {
|
90
|
+
return dataURLtoBlob;
|
91
|
+
});
|
92
|
+
} else {
|
93
|
+
window.dataURLtoBlob = dataURLtoBlob;
|
94
|
+
}
|
95
|
+
}(this));
|
@@ -0,0 +1,348 @@
|
|
1
|
+
/*
|
2
|
+
* jQuery File Upload AngularJS Plugin 1.0.1
|
3
|
+
* https://github.com/blueimp/jQuery-File-Upload
|
4
|
+
*
|
5
|
+
* Copyright 2013, Sebastian Tschan
|
6
|
+
* https://blueimp.net
|
7
|
+
*
|
8
|
+
* Licensed under the MIT license:
|
9
|
+
* http://www.opensource.org/licenses/MIT
|
10
|
+
*/
|
11
|
+
|
12
|
+
/*jslint nomen: true, unparam: true */
|
13
|
+
/*global angular */
|
14
|
+
|
15
|
+
(function () {
|
16
|
+
'use strict';
|
17
|
+
|
18
|
+
angular.module('blueimp.fileupload', [])
|
19
|
+
|
20
|
+
.provider('fileUpload', function () {
|
21
|
+
var scopeApply = function () {
|
22
|
+
var scope = angular.element(this)
|
23
|
+
.fileupload('option', 'scope')();
|
24
|
+
if (!scope.$$phase) {
|
25
|
+
scope.$apply();
|
26
|
+
}
|
27
|
+
},
|
28
|
+
$config;
|
29
|
+
$config = this.defaults = {
|
30
|
+
handleResponse: function (e, data) {
|
31
|
+
var files = data.result && data.result.files;
|
32
|
+
if (files) {
|
33
|
+
data.scope().replace(data.files, files);
|
34
|
+
} else if (data.errorThrown ||
|
35
|
+
data.textStatus === 'error') {
|
36
|
+
data.files[0].error = data.errorThrown ||
|
37
|
+
data.textStatus;
|
38
|
+
}
|
39
|
+
},
|
40
|
+
add: function (e, data) {
|
41
|
+
var scope = data.scope();
|
42
|
+
data.process(function () {
|
43
|
+
return scope.process(data);
|
44
|
+
}).always(
|
45
|
+
function () {
|
46
|
+
var file = data.files[0],
|
47
|
+
submit = function () {
|
48
|
+
return data.submit();
|
49
|
+
};
|
50
|
+
file.$cancel = function () {
|
51
|
+
scope.clear(data.files);
|
52
|
+
return data.abort();
|
53
|
+
};
|
54
|
+
file.$state = function () {
|
55
|
+
return data.state();
|
56
|
+
};
|
57
|
+
file.$progress = function () {
|
58
|
+
return data.progress();
|
59
|
+
};
|
60
|
+
file.$response = function () {
|
61
|
+
return data.response();
|
62
|
+
};
|
63
|
+
if (file.$state() === 'rejected') {
|
64
|
+
file._$submit = submit;
|
65
|
+
} else {
|
66
|
+
file.$submit = submit;
|
67
|
+
}
|
68
|
+
scope.$apply(function () {
|
69
|
+
var method = scope.option('prependFiles') ?
|
70
|
+
'unshift' : 'push';
|
71
|
+
Array.prototype[method].apply(
|
72
|
+
scope.queue,
|
73
|
+
data.files
|
74
|
+
);
|
75
|
+
if (file.$submit &&
|
76
|
+
(scope.option('autoUpload') ||
|
77
|
+
data.autoUpload) &&
|
78
|
+
data.autoUpload !== false) {
|
79
|
+
file.$submit();
|
80
|
+
}
|
81
|
+
});
|
82
|
+
}
|
83
|
+
);
|
84
|
+
},
|
85
|
+
progress: function (e, data) {
|
86
|
+
data.scope().$apply();
|
87
|
+
},
|
88
|
+
done: function (e, data) {
|
89
|
+
var that = this;
|
90
|
+
data.scope().$apply(function () {
|
91
|
+
data.handleResponse.call(that, e, data);
|
92
|
+
});
|
93
|
+
},
|
94
|
+
fail: function (e, data) {
|
95
|
+
var that = this;
|
96
|
+
if (data.errorThrown === 'abort') {
|
97
|
+
return;
|
98
|
+
}
|
99
|
+
if (data.dataType.indexOf('json') === data.dataType.length - 4) {
|
100
|
+
try {
|
101
|
+
data.result = angular.fromJson(data.jqXHR.responseText);
|
102
|
+
} catch (err) {}
|
103
|
+
}
|
104
|
+
data.scope().$apply(function () {
|
105
|
+
data.handleResponse.call(that, e, data);
|
106
|
+
});
|
107
|
+
},
|
108
|
+
stop: scopeApply,
|
109
|
+
processstart: scopeApply,
|
110
|
+
processstop: scopeApply,
|
111
|
+
getNumberOfFiles: function () {
|
112
|
+
return this.scope().queue.length;
|
113
|
+
},
|
114
|
+
dataType: 'json',
|
115
|
+
prependFiles: true,
|
116
|
+
autoUpload: false
|
117
|
+
};
|
118
|
+
this.$get = [
|
119
|
+
function () {
|
120
|
+
return {
|
121
|
+
defaults: $config
|
122
|
+
};
|
123
|
+
}
|
124
|
+
];
|
125
|
+
})
|
126
|
+
|
127
|
+
.provider('formatFileSizeFilter', function () {
|
128
|
+
var $config = this.defaults = {
|
129
|
+
// Byte units following the IEC format
|
130
|
+
// http://en.wikipedia.org/wiki/Kilobyte
|
131
|
+
units: [
|
132
|
+
{size: 1000000000, suffix: ' GB'},
|
133
|
+
{size: 1000000, suffix: ' MB'},
|
134
|
+
{size: 1000, suffix: ' KB'}
|
135
|
+
]
|
136
|
+
};
|
137
|
+
this.$get = function () {
|
138
|
+
return function (bytes) {
|
139
|
+
if (!angular.isNumber(bytes)) {
|
140
|
+
return '';
|
141
|
+
}
|
142
|
+
var unit = true,
|
143
|
+
i = -1;
|
144
|
+
while (unit) {
|
145
|
+
unit = $config.units[i += 1];
|
146
|
+
if (i === $config.units.length - 1 || bytes >= unit.size) {
|
147
|
+
return (bytes / unit.size).toFixed(2) + unit.suffix;
|
148
|
+
}
|
149
|
+
}
|
150
|
+
};
|
151
|
+
};
|
152
|
+
})
|
153
|
+
|
154
|
+
.controller('FileUploadController', [
|
155
|
+
'$scope', '$element', '$attrs', 'fileUpload',
|
156
|
+
function ($scope, $element, $attrs, fileUpload) {
|
157
|
+
$scope.disabled = angular.element('<input type="file">')
|
158
|
+
.prop('disabled');
|
159
|
+
$scope.queue = $scope.queue || [];
|
160
|
+
$scope.clear = function (files) {
|
161
|
+
var queue = this.queue,
|
162
|
+
i = queue.length,
|
163
|
+
file = files,
|
164
|
+
length = 1;
|
165
|
+
if (angular.isArray(files)) {
|
166
|
+
file = files[0];
|
167
|
+
length = files.length;
|
168
|
+
}
|
169
|
+
while (i) {
|
170
|
+
if (queue[i -= 1] === file) {
|
171
|
+
return queue.splice(i, length);
|
172
|
+
}
|
173
|
+
}
|
174
|
+
};
|
175
|
+
$scope.replace = function (oldFiles, newFiles) {
|
176
|
+
var queue = this.queue,
|
177
|
+
file = oldFiles[0],
|
178
|
+
i,
|
179
|
+
j;
|
180
|
+
for (i = 0; i < queue.length; i += 1) {
|
181
|
+
if (queue[i] === file) {
|
182
|
+
for (j = 0; j < newFiles.length; j += 1) {
|
183
|
+
queue[i + j] = newFiles[j];
|
184
|
+
}
|
185
|
+
return;
|
186
|
+
}
|
187
|
+
}
|
188
|
+
};
|
189
|
+
$scope.progress = function () {
|
190
|
+
return $element.fileupload('progress');
|
191
|
+
};
|
192
|
+
$scope.active = function () {
|
193
|
+
return $element.fileupload('active');
|
194
|
+
};
|
195
|
+
$scope.option = function (option, data) {
|
196
|
+
return $element.fileupload('option', option, data);
|
197
|
+
};
|
198
|
+
$scope.add = function (data) {
|
199
|
+
return $element.fileupload('add', data);
|
200
|
+
};
|
201
|
+
$scope.send = function (data) {
|
202
|
+
return $element.fileupload('send', data);
|
203
|
+
};
|
204
|
+
$scope.process = function (data) {
|
205
|
+
return $element.fileupload('process', data);
|
206
|
+
};
|
207
|
+
$scope.processing = function (data) {
|
208
|
+
return $element.fileupload('processing', data);
|
209
|
+
};
|
210
|
+
$scope.applyOnQueue = function (method) {
|
211
|
+
var list = this.queue.slice(0),
|
212
|
+
i,
|
213
|
+
file;
|
214
|
+
for (i = 0; i < list.length; i += 1) {
|
215
|
+
file = list[i];
|
216
|
+
if (file[method]) {
|
217
|
+
file[method]();
|
218
|
+
}
|
219
|
+
}
|
220
|
+
};
|
221
|
+
$scope.submit = function () {
|
222
|
+
this.applyOnQueue('$submit');
|
223
|
+
};
|
224
|
+
$scope.cancel = function () {
|
225
|
+
this.applyOnQueue('$cancel');
|
226
|
+
};
|
227
|
+
// The fileupload widget will initialize with
|
228
|
+
// the options provided via "data-"-parameters,
|
229
|
+
// as well as those given via options object:
|
230
|
+
$element.fileupload(angular.extend(
|
231
|
+
{scope: function () {
|
232
|
+
return $scope;
|
233
|
+
}},
|
234
|
+
fileUpload.defaults
|
235
|
+
)).on('fileuploadadd', function (e, data) {
|
236
|
+
data.scope = $scope.option('scope');
|
237
|
+
}).on([
|
238
|
+
'fileuploadadd',
|
239
|
+
'fileuploadsubmit',
|
240
|
+
'fileuploadsend',
|
241
|
+
'fileuploaddone',
|
242
|
+
'fileuploadfail',
|
243
|
+
'fileuploadalways',
|
244
|
+
'fileuploadprogress',
|
245
|
+
'fileuploadprogressall',
|
246
|
+
'fileuploadstart',
|
247
|
+
'fileuploadstop',
|
248
|
+
'fileuploadchange',
|
249
|
+
'fileuploadpaste',
|
250
|
+
'fileuploaddrop',
|
251
|
+
'fileuploaddragover',
|
252
|
+
'fileuploadchunksend',
|
253
|
+
'fileuploadchunkdone',
|
254
|
+
'fileuploadchunkfail',
|
255
|
+
'fileuploadchunkalways',
|
256
|
+
'fileuploadprocessstart',
|
257
|
+
'fileuploadprocess',
|
258
|
+
'fileuploadprocessdone',
|
259
|
+
'fileuploadprocessfail',
|
260
|
+
'fileuploadprocessalways',
|
261
|
+
'fileuploadprocessstop'
|
262
|
+
].join(' '), function (e, data) {
|
263
|
+
$scope.$emit(e.type, data);
|
264
|
+
});
|
265
|
+
// Observe option changes:
|
266
|
+
$scope.$watch(
|
267
|
+
$attrs.fileupload,
|
268
|
+
function (newOptions, oldOptions) {
|
269
|
+
if (newOptions) {
|
270
|
+
$element.fileupload('option', newOptions);
|
271
|
+
}
|
272
|
+
}
|
273
|
+
);
|
274
|
+
}
|
275
|
+
])
|
276
|
+
|
277
|
+
.controller('FileUploadProgressController', [
|
278
|
+
'$scope', '$attrs', '$parse',
|
279
|
+
function ($scope, $attrs, $parse) {
|
280
|
+
var fn = $parse($attrs.progress),
|
281
|
+
update = function () {
|
282
|
+
var progress = fn($scope);
|
283
|
+
if (!progress || !progress.total) {
|
284
|
+
return;
|
285
|
+
}
|
286
|
+
$scope.num = Math.floor(
|
287
|
+
progress.loaded / progress.total * 100
|
288
|
+
);
|
289
|
+
};
|
290
|
+
update();
|
291
|
+
$scope.$watch(
|
292
|
+
$attrs.progress + '.loaded',
|
293
|
+
function (newValue, oldValue) {
|
294
|
+
if (newValue !== oldValue) {
|
295
|
+
update();
|
296
|
+
}
|
297
|
+
}
|
298
|
+
);
|
299
|
+
}
|
300
|
+
])
|
301
|
+
|
302
|
+
.controller('FileUploadPreviewController', [
|
303
|
+
'$scope', '$element', '$attrs', '$parse',
|
304
|
+
function ($scope, $element, $attrs, $parse) {
|
305
|
+
var fn = $parse($attrs.preview),
|
306
|
+
file = fn($scope);
|
307
|
+
if (file.preview) {
|
308
|
+
$element.append(file.preview);
|
309
|
+
}
|
310
|
+
}
|
311
|
+
])
|
312
|
+
|
313
|
+
.directive('fileupload', function () {
|
314
|
+
return {
|
315
|
+
controller: 'FileUploadController'
|
316
|
+
};
|
317
|
+
})
|
318
|
+
|
319
|
+
.directive('progress', function () {
|
320
|
+
return {
|
321
|
+
controller: 'FileUploadProgressController'
|
322
|
+
};
|
323
|
+
})
|
324
|
+
|
325
|
+
.directive('preview', function () {
|
326
|
+
return {
|
327
|
+
controller: 'FileUploadPreviewController'
|
328
|
+
};
|
329
|
+
})
|
330
|
+
|
331
|
+
.directive('download', function () {
|
332
|
+
return function (scope, elm, attrs) {
|
333
|
+
elm.on('dragstart', function (e) {
|
334
|
+
try {
|
335
|
+
e.originalEvent.dataTransfer.setData(
|
336
|
+
'DownloadURL',
|
337
|
+
[
|
338
|
+
'application/octet-stream',
|
339
|
+
elm.prop('download'),
|
340
|
+
elm.prop('href')
|
341
|
+
].join(':')
|
342
|
+
);
|
343
|
+
} catch (err) {}
|
344
|
+
});
|
345
|
+
};
|
346
|
+
});
|
347
|
+
|
348
|
+
}());
|