rails-uploader 0.1.0 → 0.1.2
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.
- data/README.md +33 -0
- data/app/assets/javascripts/uploader/application.js +1 -2
- data/app/views/uploader/default/_container.html.erb +3 -4
- data/config/locales/en.yml +1 -0
- data/lib/uploader/asset.rb +79 -36
- data/lib/uploader/fileuploads.rb +16 -2
- data/lib/uploader/helpers/field_tag.rb +1 -1
- data/lib/uploader/hooks/formtastic.rb +7 -0
- data/lib/uploader/version.rb +1 -1
- data/spec/factories/articles.rb +1 -0
- data/spec/mongoid.yml +17 -0
- data/spec/mongoid_spec.rb +40 -0
- data/spec/spec_helper.rb +10 -3
- data/vendor/assets/javascripts/uploader/jquery.fileupload-fp.js +8 -4
- data/vendor/assets/javascripts/uploader/jquery.fileupload-ui.js +32 -24
- data/vendor/assets/javascripts/uploader/jquery.fileupload.js +199 -120
- data/vendor/assets/stylesheets/uploader/default.css +1 -1
- metadata +39 -6
- data/app/assets/javascripts/uploader/init.js +0 -5
- data/app/views/uploader/default/_init.html.erb +0 -9
data/README.md
CHANGED
@@ -75,6 +75,29 @@ Find asset by foreign key or guid:
|
|
75
75
|
@user.fileupload_asset(:picture)
|
76
76
|
```
|
77
77
|
|
78
|
+
### Mongoid
|
79
|
+
|
80
|
+
No parent asset model is required, one only has to `include Uploader::Asset::Mongoid` into the
|
81
|
+
model that should act like an asset:
|
82
|
+
|
83
|
+
``` ruby
|
84
|
+
class Picture
|
85
|
+
include Mongoid::Document
|
86
|
+
include Uploader::Asset::Mongoid
|
87
|
+
|
88
|
+
belongs_to :user
|
89
|
+
end
|
90
|
+
|
91
|
+
class User
|
92
|
+
include Mongoid::Document
|
93
|
+
include Uploader::Fileuploads
|
94
|
+
|
95
|
+
has_one :picture, :as => :assetable
|
96
|
+
|
97
|
+
fileuploads :picture
|
98
|
+
end
|
99
|
+
```
|
100
|
+
|
78
101
|
### Include assets
|
79
102
|
|
80
103
|
Javascripts:
|
@@ -113,6 +136,16 @@ or FormBuilder:
|
|
113
136
|
<%= f.input :pictures, :as => :uploader, :input_html => {:sortable => true} %>
|
114
137
|
```
|
115
138
|
|
139
|
+
#### Confirming deletions
|
140
|
+
|
141
|
+
This is only working in Formtastic and FormBuilder:
|
142
|
+
|
143
|
+
``` ruby
|
144
|
+
# formtastic
|
145
|
+
<%= f.input :picture, :as => :uploader, :confirm_delete => true %>
|
146
|
+
# the i18n lookup key would be en.formtastic.delete_confirmations.picture
|
147
|
+
```
|
148
|
+
|
116
149
|
## Contributing
|
117
150
|
|
118
151
|
1. Fork it
|
@@ -1,9 +1,8 @@
|
|
1
|
+
//= require uploader/jquery.ui.widget
|
1
2
|
//= require uploader/locales/en
|
2
3
|
//= require uploader/tmpl.min
|
3
4
|
//= require uploader/load-image.min
|
4
|
-
//= require uploader/jquery.ui.widget
|
5
5
|
//= require uploader/jquery.iframe-transport
|
6
6
|
//= require uploader/jquery.fileupload
|
7
7
|
//= require uploader/jquery.fileupload-ui
|
8
|
-
//= require uploader/init
|
9
8
|
|
@@ -4,21 +4,20 @@
|
|
4
4
|
<div class="uploader-files"></div>
|
5
5
|
|
6
6
|
<div class="uploader-dnd-hints">
|
7
|
-
<
|
7
|
+
<span class="uploader-button gray fileinput-button">
|
8
8
|
<span><%= I18n.t('uploader.button') %></span>
|
9
9
|
<%= fields_for field.object do |f| -%>
|
10
10
|
<%= f.fields_for field.method_name, field.klass.new do |m| -%>
|
11
11
|
<%= m.file_field(:data, field.input_html) %>
|
12
12
|
<% end -%>
|
13
13
|
<% end -%>
|
14
|
-
</
|
14
|
+
</span>
|
15
15
|
|
16
16
|
<div class="uploader-dnd-hint">
|
17
17
|
<%= I18n.t('uploader.or') %><span><%= I18n.t('uploader.drop') %></span>
|
18
18
|
</div>
|
19
19
|
</div>
|
20
20
|
|
21
|
-
<%= render :partial => "uploader/#{field.theme}/init", :locals => {:field => field} %>
|
22
21
|
<%= render :partial => "uploader/#{field.theme}/upload", :locals => {:field => field} %>
|
23
22
|
<%= render :partial => "uploader/#{field.theme}/download", :locals => {:field => field} %>
|
24
23
|
<%= render :partial => "uploader/#{field.theme}/sortable", :locals => {:field => field} if field.sortable? %>
|
@@ -28,7 +27,7 @@
|
|
28
27
|
var uploader, container;
|
29
28
|
container = $("#<%= field.id %> div.uploader-files");
|
30
29
|
|
31
|
-
$('#<%= field.id %> input[type="file"]').
|
30
|
+
$('#<%= field.id %> input[type="file"]').each(function(){
|
32
31
|
$(this).fileupload({
|
33
32
|
dataType: 'json',
|
34
33
|
dropZone: $("#<%= field.id %>"),
|
data/config/locales/en.yml
CHANGED
data/lib/uploader/asset.rb
CHANGED
@@ -1,42 +1,85 @@
|
|
1
1
|
module Uploader
|
2
2
|
module Asset
|
3
|
-
|
4
|
-
|
5
|
-
#
|
6
|
-
# class Asset < ActiveRecord::Base
|
7
|
-
# include Uploader::Asset
|
8
|
-
#
|
9
|
-
# def uploader_create(params, request = nil)
|
10
|
-
# self.user = request.env['warden'].user
|
11
|
-
# super
|
12
|
-
# end
|
13
|
-
# end
|
14
|
-
#
|
15
|
-
def uploader_create(params, request = nil)
|
16
|
-
self.guid = params[:guid]
|
17
|
-
self.assetable_type = params[:assetable_type]
|
18
|
-
self.assetable_id = params[:assetable_id]
|
19
|
-
save
|
3
|
+
def self.included(base)
|
4
|
+
base.send(:include, Uploader::Asset::AssetProcessor)
|
20
5
|
end
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
6
|
+
|
7
|
+
module Mongoid
|
8
|
+
def self.included(base)
|
9
|
+
base.send(:include, Uploader::Asset::AssetProcessor)
|
10
|
+
|
11
|
+
base.instance_eval do
|
12
|
+
field :guid, type: String
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def as_json(options = {})
|
17
|
+
json_data = super
|
18
|
+
json_data['filename'] = File.basename(data.path)
|
19
|
+
json_data['size'] = data.file.size
|
20
|
+
json_data['id'] = json_data['_id']
|
21
|
+
|
22
|
+
if data.respond_to?(:thumb)
|
23
|
+
json_data['thumb_url'] = data.thumb.url
|
24
|
+
end
|
25
|
+
|
26
|
+
json_data
|
27
|
+
end
|
28
|
+
|
29
|
+
def assetable_id_format(assetable_id)
|
30
|
+
Moped::BSON::ObjectId.from_string(assetable_id)
|
31
|
+
end
|
32
|
+
|
33
|
+
class << self
|
34
|
+
def include_root_in_json
|
35
|
+
false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module AssetProcessor
|
41
|
+
# Save asset
|
42
|
+
# Usage:
|
43
|
+
#
|
44
|
+
# class Asset < ActiveRecord::Base
|
45
|
+
# include Uploader::Asset
|
46
|
+
#
|
47
|
+
# def uploader_create(params, request = nil)
|
48
|
+
# self.user = request.env['warden'].user
|
49
|
+
# super
|
50
|
+
# end
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
def uploader_create(params, request = nil)
|
54
|
+
self.guid = params[:guid]
|
55
|
+
self.assetable_type = params[:assetable_type]
|
56
|
+
self.assetable_id = assetable_id_format(params[:assetable_id]) if params[:assetable_id]
|
57
|
+
save
|
58
|
+
end
|
59
|
+
|
60
|
+
# Destroy asset
|
61
|
+
# Usage (cancan example):
|
62
|
+
#
|
63
|
+
# class Asset < ActiveRecord::Base
|
64
|
+
# include Uploader::Asset
|
65
|
+
#
|
66
|
+
# def uploader_destroy(params, request = nil)
|
67
|
+
# ability = Ability.new(request.env['warden'].user)
|
68
|
+
# if ability.can? :delete, self
|
69
|
+
# super
|
70
|
+
# else
|
71
|
+
# errors.add(:id, :access_denied)
|
72
|
+
# end
|
73
|
+
# end
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
def uploader_destroy(params, request)
|
77
|
+
destroy
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def assetable_id_format(assetable_id)
|
82
|
+
assetable_id
|
40
83
|
end
|
41
84
|
end
|
42
85
|
end
|
data/lib/uploader/fileuploads.rb
CHANGED
@@ -3,7 +3,17 @@ module Uploader
|
|
3
3
|
def self.included(base)
|
4
4
|
base.send :extend, SingletonMethods
|
5
5
|
end
|
6
|
-
|
6
|
+
|
7
|
+
module Mongoid
|
8
|
+
def self.included(base)
|
9
|
+
base.send :include, Uploader::Fileuploads
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.include_root_in_json
|
13
|
+
false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
7
17
|
module SingletonMethods
|
8
18
|
# Join ActiveRecord object with uploaded file
|
9
19
|
# Usage:
|
@@ -77,7 +87,11 @@ module Uploader
|
|
77
87
|
|
78
88
|
def fileupload_multiple?(method)
|
79
89
|
association = self.class.reflect_on_association(method.to_sym)
|
80
|
-
|
90
|
+
|
91
|
+
# many? for Mongoid, :collection? for AR
|
92
|
+
method = association.respond_to?(:many?) ? :many? : :collection?
|
93
|
+
|
94
|
+
!!(association && association.send(method))
|
81
95
|
end
|
82
96
|
|
83
97
|
# Find or build new asset object
|
@@ -13,7 +13,7 @@ module Uploader
|
|
13
13
|
#
|
14
14
|
def initialize(object_name, method_name, template, options = {}) #:nodoc:
|
15
15
|
options = { :object_name => object_name, :method_name => method_name }.merge(options)
|
16
|
-
|
16
|
+
|
17
17
|
@template, @options = template, options.dup
|
18
18
|
|
19
19
|
@theme = (@options.delete(:theme) || "default")
|
@@ -9,4 +9,11 @@ class UploaderInput
|
|
9
9
|
builder.uploader_field(method, input_html_options)
|
10
10
|
end
|
11
11
|
end
|
12
|
+
|
13
|
+
def input_html_options
|
14
|
+
data = super
|
15
|
+
data[:confirm_delete] = options[:confirm_delete]
|
16
|
+
data[:confirm_message] = localized_string(method, method, :delete_confirmation) || I18n.t('uploader.confirm_delete')
|
17
|
+
data
|
18
|
+
end
|
12
19
|
end
|
data/lib/uploader/version.rb
CHANGED
data/spec/factories/articles.rb
CHANGED
data/spec/mongoid.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Tell Mongoid which environment this configuration is for.
|
2
|
+
test:
|
3
|
+
# This starts the session configuration settings. You may have as
|
4
|
+
# many sessions as you like, but you must have at least 1 named
|
5
|
+
# 'default'.
|
6
|
+
sessions:
|
7
|
+
# Define the default session.
|
8
|
+
default:
|
9
|
+
# A session can have any number of hosts. Usually 1 for a single
|
10
|
+
# server setup, and at least 3 for a replica set. Hosts must be
|
11
|
+
# an array of host:port pairs. This session is single server.
|
12
|
+
hosts:
|
13
|
+
- localhost:27017
|
14
|
+
# Define the default database name.
|
15
|
+
database: rails_uploader_test
|
16
|
+
options:
|
17
|
+
include_root_in_json: false
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class MongoidArticle
|
4
|
+
include Mongoid::Document
|
5
|
+
include Uploader::Fileuploads
|
6
|
+
|
7
|
+
has_one :mongoid_picture, :as => :assetable
|
8
|
+
|
9
|
+
fileuploads :mongoid_picture
|
10
|
+
end
|
11
|
+
|
12
|
+
class MongoidPicture
|
13
|
+
include Mongoid::Document
|
14
|
+
include Uploader::Asset::Mongoid
|
15
|
+
|
16
|
+
belongs_to :assetable, polymorphic: true
|
17
|
+
end
|
18
|
+
|
19
|
+
describe Uploader::Asset::Mongoid do
|
20
|
+
before do
|
21
|
+
@guid = 'guid'
|
22
|
+
@picture = MongoidPicture.create!(:guid => @guid, :assetable_type => 'MongoidArticle')
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should find asset by guid' do
|
26
|
+
asset = MongoidArticle.fileupload_find("mongoid_picture", @picture.guid)
|
27
|
+
asset.should == @picture
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should update asset target_id by guid" do
|
31
|
+
MongoidArticle.fileupload_update(1000, @picture.guid, :mongoid_picture)
|
32
|
+
@picture.reload
|
33
|
+
@picture.assetable_id.should == 1000
|
34
|
+
@picture.guid.should be_nil
|
35
|
+
end
|
36
|
+
|
37
|
+
after do
|
38
|
+
MongoidPicture.destroy_all
|
39
|
+
end
|
40
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -29,6 +29,10 @@ end
|
|
29
29
|
# Load support files
|
30
30
|
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
31
31
|
|
32
|
+
# Mongoid
|
33
|
+
require 'mongoid'
|
34
|
+
Mongoid.load!('spec/mongoid.yml')
|
35
|
+
|
32
36
|
RSpec.configure do |config|
|
33
37
|
# Remove this line if you don't want RSpec's should and should_not
|
34
38
|
# methods or matchers
|
@@ -39,14 +43,17 @@ RSpec.configure do |config|
|
|
39
43
|
config.mock_with :rspec
|
40
44
|
|
41
45
|
config.before(:suite) do
|
42
|
-
DatabaseCleaner.strategy = :truncation
|
46
|
+
DatabaseCleaner[:active_record].strategy = :truncation
|
47
|
+
DatabaseCleaner[:mongoid].strategy = :truncation
|
43
48
|
end
|
44
49
|
|
45
50
|
config.before(:all) do
|
46
|
-
DatabaseCleaner.start
|
51
|
+
DatabaseCleaner[:active_record].start
|
52
|
+
DatabaseCleaner[:mongoid].start
|
47
53
|
end
|
48
54
|
|
49
55
|
config.after(:all) do
|
50
|
-
DatabaseCleaner.clean
|
56
|
+
DatabaseCleaner[:active_record].clean
|
57
|
+
DatabaseCleaner[:mongoid].clean
|
51
58
|
end
|
52
59
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* jQuery File Upload File Processing Plugin 1.2.
|
2
|
+
* jQuery File Upload File Processing Plugin 1.2.3
|
3
3
|
* https://github.com/blueimp/jQuery-File-Upload
|
4
4
|
*
|
5
5
|
* Copyright 2012, Sebastian Tschan
|
@@ -62,9 +62,13 @@
|
|
62
62
|
// fileupload widget (via file input selection, drag & drop or add
|
63
63
|
// API call). See the basic file upload widget for more information:
|
64
64
|
add: function (e, data) {
|
65
|
-
|
66
|
-
|
67
|
-
|
65
|
+
if (data.autoUpload || (data.autoUpload !== false &&
|
66
|
+
($(this).data('blueimp-fileupload') ||
|
67
|
+
$(this).data('fileupload')).options.autoUpload)) {
|
68
|
+
$(this).fileupload('process', data).done(function () {
|
69
|
+
data.submit();
|
70
|
+
});
|
71
|
+
}
|
68
72
|
}
|
69
73
|
},
|
70
74
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* jQuery File Upload User Interface Plugin 7.
|
2
|
+
* jQuery File Upload User Interface Plugin 7.4.4
|
3
3
|
* https://github.com/blueimp/jQuery-File-Upload
|
4
4
|
*
|
5
5
|
* Copyright 2010, Sebastian Tschan
|
@@ -263,7 +263,7 @@
|
|
263
263
|
// Callback for upload progress events:
|
264
264
|
progress: function (e, data) {
|
265
265
|
if (data.context) {
|
266
|
-
var progress =
|
266
|
+
var progress = Math.floor(data.loaded / data.total * 100);
|
267
267
|
data.context.find('.progress')
|
268
268
|
.attr('aria-valuenow', progress)
|
269
269
|
.find('.bar').css(
|
@@ -275,7 +275,7 @@
|
|
275
275
|
// Callback for global upload progress events:
|
276
276
|
progressall: function (e, data) {
|
277
277
|
var $this = $(this),
|
278
|
-
progress =
|
278
|
+
progress = Math.floor(data.loaded / data.total * 100),
|
279
279
|
globalProgressNode = $this.find('.fileupload-progress'),
|
280
280
|
extendedProgressNode = globalProgressNode
|
281
281
|
.find('.progress-extended');
|
@@ -328,15 +328,16 @@
|
|
328
328
|
var that = $(this).data('blueimp-fileupload') ||
|
329
329
|
$(this).data('fileupload');
|
330
330
|
if (data.url) {
|
331
|
-
$.ajax(data)
|
332
|
-
|
331
|
+
$.ajax(data).done(function () {
|
332
|
+
that._transition(data.context).done(
|
333
|
+
function () {
|
334
|
+
$(this).remove();
|
335
|
+
that._adjustMaxNumberOfFiles(1);
|
336
|
+
that._trigger('destroyed', e, data);
|
337
|
+
}
|
338
|
+
);
|
339
|
+
});
|
333
340
|
}
|
334
|
-
that._transition(data.context).done(
|
335
|
-
function () {
|
336
|
-
$(this).remove();
|
337
|
-
that._trigger('destroyed', e, data);
|
338
|
-
}
|
339
|
-
);
|
340
341
|
}
|
341
342
|
},
|
342
343
|
|
@@ -422,7 +423,7 @@
|
|
422
423
|
|
423
424
|
_formatTime: function (seconds) {
|
424
425
|
var date = new Date(seconds * 1000),
|
425
|
-
days =
|
426
|
+
days = Math.floor(seconds / 86400);
|
426
427
|
days = days ? days + 'd ' : '';
|
427
428
|
return days +
|
428
429
|
('0' + date.getUTCHours()).slice(-2) + ':' +
|
@@ -519,6 +520,12 @@
|
|
519
520
|
// so we have to resolve manually:
|
520
521
|
dfd.resolveWith(node);
|
521
522
|
}
|
523
|
+
node.on('remove', function () {
|
524
|
+
// If the element is removed before the
|
525
|
+
// transition finishes, transition events are
|
526
|
+
// not triggered, resolve manually:
|
527
|
+
dfd.resolveWith(node);
|
528
|
+
});
|
522
529
|
},
|
523
530
|
{
|
524
531
|
maxWidth: options.previewMaxWidth,
|
@@ -595,8 +602,7 @@
|
|
595
602
|
var button = $(e.currentTarget);
|
596
603
|
this._trigger('destroy', e, $.extend({
|
597
604
|
context: button.closest('.template-download'),
|
598
|
-
type: 'DELETE'
|
599
|
-
dataType: this.options.dataType
|
605
|
+
type: 'DELETE'
|
600
606
|
}, button.data()));
|
601
607
|
},
|
602
608
|
|
@@ -607,7 +613,7 @@
|
|
607
613
|
|
608
614
|
_transition: function (node) {
|
609
615
|
var dfd = $.Deferred();
|
610
|
-
if ($.support.transition && node.hasClass('fade')) {
|
616
|
+
if ($.support.transition && node.hasClass('fade') && node.is(':visible')) {
|
611
617
|
node.bind(
|
612
618
|
$.support.transition.end,
|
613
619
|
function (e) {
|
@@ -632,27 +638,28 @@
|
|
632
638
|
this._on(fileUploadButtonBar.find('.start'), {
|
633
639
|
click: function (e) {
|
634
640
|
e.preventDefault();
|
635
|
-
filesList.find('.start
|
641
|
+
filesList.find('.start').click();
|
636
642
|
}
|
637
643
|
});
|
638
644
|
this._on(fileUploadButtonBar.find('.cancel'), {
|
639
645
|
click: function (e) {
|
640
646
|
e.preventDefault();
|
641
|
-
filesList.find('.cancel
|
647
|
+
filesList.find('.cancel').click();
|
642
648
|
}
|
643
649
|
});
|
644
650
|
this._on(fileUploadButtonBar.find('.delete'), {
|
645
651
|
click: function (e) {
|
646
652
|
e.preventDefault();
|
647
|
-
filesList.find('.
|
648
|
-
.
|
653
|
+
filesList.find('.toggle:checked')
|
654
|
+
.closest('.template-download')
|
655
|
+
.find('.delete').click();
|
649
656
|
fileUploadButtonBar.find('.toggle')
|
650
657
|
.prop('checked', false);
|
651
658
|
}
|
652
659
|
});
|
653
660
|
this._on(fileUploadButtonBar.find('.toggle'), {
|
654
661
|
change: function (e) {
|
655
|
-
filesList.find('.
|
662
|
+
filesList.find('.toggle').prop(
|
656
663
|
'checked',
|
657
664
|
$(e.currentTarget).is(':checked')
|
658
665
|
);
|
@@ -662,7 +669,8 @@
|
|
662
669
|
|
663
670
|
_destroyButtonBarEventHandlers: function () {
|
664
671
|
this._off(
|
665
|
-
this.element.find('.fileupload-buttonbar
|
672
|
+
this.element.find('.fileupload-buttonbar')
|
673
|
+
.find('.start, .cancel, .delete'),
|
666
674
|
'click'
|
667
675
|
);
|
668
676
|
this._off(
|
@@ -674,9 +682,9 @@
|
|
674
682
|
_initEventHandlers: function () {
|
675
683
|
this._super();
|
676
684
|
this._on(this.options.filesContainer, {
|
677
|
-
'click .start
|
678
|
-
'click .cancel
|
679
|
-
'click .delete
|
685
|
+
'click .start': this._startHandler,
|
686
|
+
'click .cancel': this._cancelHandler,
|
687
|
+
'click .delete': this._deleteHandler
|
680
688
|
});
|
681
689
|
this._initButtonBarEventHandlers();
|
682
690
|
},
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* jQuery File Upload Plugin 5.
|
2
|
+
* jQuery File Upload Plugin 5.28.8
|
3
3
|
* https://github.com/blueimp/jQuery-File-Upload
|
4
4
|
*
|
5
5
|
* Copyright 2010, Sebastian Tschan
|
@@ -33,21 +33,6 @@
|
|
33
33
|
$.support.xhrFileUpload = !!(window.XMLHttpRequestUpload && window.FileReader);
|
34
34
|
$.support.xhrFormDataFileUpload = !!window.FormData;
|
35
35
|
|
36
|
-
// The form.elements propHook is added to filter serialized elements
|
37
|
-
// to not include file inputs in jQuery 1.9.0.
|
38
|
-
// This hooks directly into jQuery.fn.serializeArray.
|
39
|
-
// For more info, see http://bugs.jquery.com/ticket/13306
|
40
|
-
$.propHooks.elements = {
|
41
|
-
get: function (form) {
|
42
|
-
if ($.nodeName(form, 'form')) {
|
43
|
-
return $.grep(form.elements, function (elem) {
|
44
|
-
return !$.nodeName(elem, 'input') || elem.type !== 'file';
|
45
|
-
});
|
46
|
-
}
|
47
|
-
return null;
|
48
|
-
}
|
49
|
-
};
|
50
|
-
|
51
36
|
// The fileupload widget listens for change events on file input fields defined
|
52
37
|
// via fileInput setting and paste or drop events of the given dropZone.
|
53
38
|
// In addition to the default jQuery Widget methods, the fileupload widget
|
@@ -127,6 +112,8 @@
|
|
127
112
|
progressInterval: 100,
|
128
113
|
// Interval in milliseconds to calculate progress bitrate:
|
129
114
|
bitrateInterval: 500,
|
115
|
+
// By default, uploads are started automatically when adding files:
|
116
|
+
autoUpload: true,
|
130
117
|
|
131
118
|
// Additional form data to be sent along with the file uploads can be set
|
132
119
|
// using this option, which accepts an array of objects with name and
|
@@ -151,7 +138,11 @@
|
|
151
138
|
// handlers using jQuery's Deferred callbacks:
|
152
139
|
// data.submit().done(func).fail(func).always(func);
|
153
140
|
add: function (e, data) {
|
154
|
-
data.
|
141
|
+
if (data.autoUpload || (data.autoUpload !== false &&
|
142
|
+
($(this).data('blueimp-fileupload') ||
|
143
|
+
$(this).data('fileupload')).options.autoUpload)) {
|
144
|
+
data.submit();
|
145
|
+
}
|
155
146
|
},
|
156
147
|
|
157
148
|
// Other callbacks:
|
@@ -224,7 +215,7 @@
|
|
224
215
|
],
|
225
216
|
|
226
217
|
_BitrateTimer: function () {
|
227
|
-
this.timestamp =
|
218
|
+
this.timestamp = ((Date.now) ? Date.now() : (new Date()).getTime());
|
228
219
|
this.loaded = 0;
|
229
220
|
this.bitrate = 0;
|
230
221
|
this.getBitrate = function (now, loaded, interval) {
|
@@ -252,7 +243,7 @@
|
|
252
243
|
if ($.isArray(options.formData)) {
|
253
244
|
return options.formData;
|
254
245
|
}
|
255
|
-
if (options.formData) {
|
246
|
+
if ($.type(options.formData) === 'object') {
|
256
247
|
formData = [];
|
257
248
|
$.each(options.formData, function (name, value) {
|
258
249
|
formData.push({name: name, value: value});
|
@@ -270,10 +261,35 @@
|
|
270
261
|
return total;
|
271
262
|
},
|
272
263
|
|
264
|
+
_initProgressObject: function (obj) {
|
265
|
+
var progress = {
|
266
|
+
loaded: 0,
|
267
|
+
total: 0,
|
268
|
+
bitrate: 0
|
269
|
+
};
|
270
|
+
if (obj._progress) {
|
271
|
+
$.extend(obj._progress, progress);
|
272
|
+
} else {
|
273
|
+
obj._progress = progress;
|
274
|
+
}
|
275
|
+
},
|
276
|
+
|
277
|
+
_initResponseObject: function (obj) {
|
278
|
+
var prop;
|
279
|
+
if (obj._response) {
|
280
|
+
for (prop in obj._response) {
|
281
|
+
if (obj._response.hasOwnProperty(prop)) {
|
282
|
+
delete obj._response[prop];
|
283
|
+
}
|
284
|
+
}
|
285
|
+
} else {
|
286
|
+
obj._response = {};
|
287
|
+
}
|
288
|
+
},
|
289
|
+
|
273
290
|
_onProgress: function (e, data) {
|
274
291
|
if (e.lengthComputable) {
|
275
|
-
var now =
|
276
|
-
total,
|
292
|
+
var now = ((Date.now) ? Date.now() : (new Date()).getTime()),
|
277
293
|
loaded;
|
278
294
|
if (data._time && data.progressInterval &&
|
279
295
|
(now - data._time < data.progressInterval) &&
|
@@ -281,16 +297,19 @@
|
|
281
297
|
return;
|
282
298
|
}
|
283
299
|
data._time = now;
|
284
|
-
|
285
|
-
|
286
|
-
e.loaded / e.total * (data.chunkSize || total),
|
287
|
-
10
|
300
|
+
loaded = Math.floor(
|
301
|
+
e.loaded / e.total * (data.chunkSize || data._progress.total)
|
288
302
|
) + (data.uploadedBytes || 0);
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
303
|
+
// Add the difference from the previously loaded state
|
304
|
+
// to the global loaded counter:
|
305
|
+
this._progress.loaded += (loaded - data._progress.loaded);
|
306
|
+
this._progress.bitrate = this._bitrateTimer.getBitrate(
|
307
|
+
now,
|
308
|
+
this._progress.loaded,
|
309
|
+
data.bitrateInterval
|
310
|
+
);
|
311
|
+
data._progress.loaded = data.loaded = loaded;
|
312
|
+
data._progress.bitrate = data.bitrate = data._bitrateTimer.getBitrate(
|
294
313
|
now,
|
295
314
|
loaded,
|
296
315
|
data.bitrateInterval
|
@@ -301,16 +320,7 @@
|
|
301
320
|
this._trigger('progress', e, data);
|
302
321
|
// Trigger a global progress event for all current file uploads,
|
303
322
|
// including ajax calls queued for sequential file uploads:
|
304
|
-
this._trigger('progressall', e,
|
305
|
-
lengthComputable: true,
|
306
|
-
loaded: this._loaded,
|
307
|
-
total: this._total,
|
308
|
-
bitrate: this._bitrateTimer.getBitrate(
|
309
|
-
now,
|
310
|
-
this._loaded,
|
311
|
-
data.bitrateInterval
|
312
|
-
)
|
313
|
-
});
|
323
|
+
this._trigger('progressall', e, this._progress);
|
314
324
|
}
|
315
325
|
},
|
316
326
|
|
@@ -334,8 +344,14 @@
|
|
334
344
|
}
|
335
345
|
},
|
336
346
|
|
347
|
+
_isInstanceOf: function (type, obj) {
|
348
|
+
// Cross-frame instanceof check
|
349
|
+
return Object.prototype.toString.call(obj) === '[object ' + type + ']';
|
350
|
+
},
|
351
|
+
|
337
352
|
_initXHRData: function (options) {
|
338
|
-
var
|
353
|
+
var that = this,
|
354
|
+
formData,
|
339
355
|
file = options.files[0],
|
340
356
|
// Ignore non-multipart setting if not supported:
|
341
357
|
multipart = options.multipart || !$.support.xhrFileUpload,
|
@@ -370,7 +386,7 @@
|
|
370
386
|
});
|
371
387
|
}
|
372
388
|
} else {
|
373
|
-
if (options.formData
|
389
|
+
if (that._isInstanceOf('FormData', options.formData)) {
|
374
390
|
formData = options.formData;
|
375
391
|
} else {
|
376
392
|
formData = new FormData();
|
@@ -384,12 +400,10 @@
|
|
384
400
|
formData.append(paramName, options.blob, file.name);
|
385
401
|
} else {
|
386
402
|
$.each(options.files, function (index, file) {
|
387
|
-
// Files are also Blob instances, but some browsers
|
388
|
-
// (Firefox 3.6) support the File API but not Blobs.
|
389
403
|
// This check allows the tests to run with
|
390
404
|
// dummy objects:
|
391
|
-
if ((
|
392
|
-
(
|
405
|
+
if (that._isInstanceOf('File', file) ||
|
406
|
+
that._isInstanceOf('Blob', file)) {
|
393
407
|
formData.append(
|
394
408
|
options.paramName[index] || paramName,
|
395
409
|
file,
|
@@ -434,7 +448,7 @@
|
|
434
448
|
options.dataType = 'postmessage ' + (options.dataType || '');
|
435
449
|
}
|
436
450
|
} else {
|
437
|
-
this._initIframeSettings(options
|
451
|
+
this._initIframeSettings(options);
|
438
452
|
}
|
439
453
|
},
|
440
454
|
|
@@ -495,6 +509,21 @@
|
|
495
509
|
return options;
|
496
510
|
},
|
497
511
|
|
512
|
+
// jQuery 1.6 doesn't provide .state(),
|
513
|
+
// while jQuery 1.8+ removed .isRejected() and .isResolved():
|
514
|
+
_getDeferredState: function (deferred) {
|
515
|
+
if (deferred.state) {
|
516
|
+
return deferred.state();
|
517
|
+
}
|
518
|
+
if (deferred.isResolved()) {
|
519
|
+
return 'resolved';
|
520
|
+
}
|
521
|
+
if (deferred.isRejected()) {
|
522
|
+
return 'rejected';
|
523
|
+
}
|
524
|
+
return 'pending';
|
525
|
+
},
|
526
|
+
|
498
527
|
// Maps jqXHR callbacks to the equivalent
|
499
528
|
// methods of the given Promise object:
|
500
529
|
_enhancePromise: function (promise) {
|
@@ -519,6 +548,36 @@
|
|
519
548
|
return this._enhancePromise(promise);
|
520
549
|
},
|
521
550
|
|
551
|
+
// Adds convenience methods to the callback arguments:
|
552
|
+
_addConvenienceMethods: function (e, data) {
|
553
|
+
var that = this;
|
554
|
+
data.submit = function () {
|
555
|
+
if (this.state() !== 'pending') {
|
556
|
+
data.jqXHR = this.jqXHR =
|
557
|
+
(that._trigger('submit', e, this) !== false) &&
|
558
|
+
that._onSend(e, this);
|
559
|
+
}
|
560
|
+
return this.jqXHR || that._getXHRPromise();
|
561
|
+
};
|
562
|
+
data.abort = function () {
|
563
|
+
if (this.jqXHR) {
|
564
|
+
return this.jqXHR.abort();
|
565
|
+
}
|
566
|
+
return that._getXHRPromise();
|
567
|
+
};
|
568
|
+
data.state = function () {
|
569
|
+
if (this.jqXHR) {
|
570
|
+
return that._getDeferredState(this.jqXHR);
|
571
|
+
}
|
572
|
+
};
|
573
|
+
data.progress = function () {
|
574
|
+
return this._progress;
|
575
|
+
};
|
576
|
+
data.response = function () {
|
577
|
+
return this._response;
|
578
|
+
};
|
579
|
+
},
|
580
|
+
|
522
581
|
// Parses the Range header from the server response
|
523
582
|
// and returns the uploaded bytes:
|
524
583
|
_getUploadedBytes: function (jqXHR) {
|
@@ -563,7 +622,8 @@
|
|
563
622
|
// The chunk upload method:
|
564
623
|
upload = function () {
|
565
624
|
// Clone the options object for each chunk upload:
|
566
|
-
var o = $.extend({}, options)
|
625
|
+
var o = $.extend({}, options),
|
626
|
+
currentLoaded = o._progress.loaded;
|
567
627
|
o.blob = slice.call(
|
568
628
|
file,
|
569
629
|
ub,
|
@@ -585,10 +645,10 @@
|
|
585
645
|
.done(function (result, textStatus, jqXHR) {
|
586
646
|
ub = that._getUploadedBytes(jqXHR) ||
|
587
647
|
(ub + o.chunkSize);
|
588
|
-
// Create a progress event if
|
589
|
-
//
|
590
|
-
//
|
591
|
-
if (
|
648
|
+
// Create a progress event if no final progress event
|
649
|
+
// with loaded equaling total has been triggered
|
650
|
+
// for this chunk:
|
651
|
+
if (o._progress.loaded === currentLoaded) {
|
592
652
|
that._onProgress($.Event('progress', {
|
593
653
|
lengthComputable: true,
|
594
654
|
loaded: ub - o.uploadedBytes,
|
@@ -640,61 +700,66 @@
|
|
640
700
|
this._trigger('start');
|
641
701
|
// Set timer for global bitrate progress calculation:
|
642
702
|
this._bitrateTimer = new this._BitrateTimer();
|
703
|
+
// Reset the global progress values:
|
704
|
+
this._progress.loaded = this._progress.total = 0;
|
705
|
+
this._progress.bitrate = 0;
|
643
706
|
}
|
707
|
+
// Make sure the container objects for the .response() and
|
708
|
+
// .progress() methods on the data object are available
|
709
|
+
// and reset to their initial state:
|
710
|
+
this._initResponseObject(data);
|
711
|
+
this._initProgressObject(data);
|
712
|
+
data._progress.loaded = data.loaded = data.uploadedBytes || 0;
|
713
|
+
data._progress.total = data.total = this._getTotal(data.files) || 1;
|
714
|
+
data._progress.bitrate = data.bitrate = 0;
|
644
715
|
this._active += 1;
|
645
716
|
// Initialize the global progress values:
|
646
|
-
this.
|
647
|
-
this.
|
717
|
+
this._progress.loaded += data.loaded;
|
718
|
+
this._progress.total += data.total;
|
648
719
|
},
|
649
720
|
|
650
721
|
_onDone: function (result, textStatus, jqXHR, options) {
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
// Create a progress event
|
655
|
-
//
|
656
|
-
// loaded equaling total for XHR uploads:
|
722
|
+
var total = options._progress.total,
|
723
|
+
response = options._response;
|
724
|
+
if (options._progress.loaded < total) {
|
725
|
+
// Create a progress event if no final progress event
|
726
|
+
// with loaded equaling total has been triggered:
|
657
727
|
this._onProgress($.Event('progress', {
|
658
728
|
lengthComputable: true,
|
659
729
|
loaded: total,
|
660
730
|
total: total
|
661
731
|
}), options);
|
662
732
|
}
|
663
|
-
options.result = result;
|
664
|
-
options.textStatus = textStatus;
|
665
|
-
options.jqXHR = jqXHR;
|
733
|
+
response.result = options.result = result;
|
734
|
+
response.textStatus = options.textStatus = textStatus;
|
735
|
+
response.jqXHR = options.jqXHR = jqXHR;
|
666
736
|
this._trigger('done', null, options);
|
667
737
|
},
|
668
738
|
|
669
739
|
_onFail: function (jqXHR, textStatus, errorThrown, options) {
|
670
|
-
|
671
|
-
options.textStatus = textStatus;
|
672
|
-
options.errorThrown = errorThrown;
|
673
|
-
this._trigger('fail', null, options);
|
740
|
+
var response = options._response;
|
674
741
|
if (options.recalculateProgress) {
|
675
742
|
// Remove the failed (error or abort) file upload from
|
676
743
|
// the global progress calculation:
|
677
|
-
this.
|
678
|
-
this.
|
744
|
+
this._progress.loaded -= options._progress.loaded;
|
745
|
+
this._progress.total -= options._progress.total;
|
679
746
|
}
|
747
|
+
response.jqXHR = options.jqXHR = jqXHR;
|
748
|
+
response.textStatus = options.textStatus = textStatus;
|
749
|
+
response.errorThrown = options.errorThrown = errorThrown;
|
750
|
+
this._trigger('fail', null, options);
|
680
751
|
},
|
681
752
|
|
682
753
|
_onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) {
|
683
754
|
// jqXHRorResult, textStatus and jqXHRorError are added to the
|
684
755
|
// options object via done and fail callbacks
|
685
|
-
this._active -= 1;
|
686
756
|
this._trigger('always', null, options);
|
687
|
-
if (this._active === 0) {
|
688
|
-
// The stop callback is triggered when all uploads have
|
689
|
-
// been completed, equivalent to the global ajaxStop event:
|
690
|
-
this._trigger('stop');
|
691
|
-
// Reset the global progress values:
|
692
|
-
this._loaded = this._total = 0;
|
693
|
-
this._bitrateTimer = null;
|
694
|
-
}
|
695
757
|
},
|
696
758
|
|
697
759
|
_onSend: function (e, data) {
|
760
|
+
if (!data.submit) {
|
761
|
+
this._addConvenienceMethods(e, data);
|
762
|
+
}
|
698
763
|
var that = this,
|
699
764
|
jqXHR,
|
700
765
|
aborted,
|
@@ -714,32 +779,32 @@
|
|
714
779
|
}).fail(function (jqXHR, textStatus, errorThrown) {
|
715
780
|
that._onFail(jqXHR, textStatus, errorThrown, options);
|
716
781
|
}).always(function (jqXHRorResult, textStatus, jqXHRorError) {
|
717
|
-
that._sending -= 1;
|
718
782
|
that._onAlways(
|
719
783
|
jqXHRorResult,
|
720
784
|
textStatus,
|
721
785
|
jqXHRorError,
|
722
786
|
options
|
723
787
|
);
|
788
|
+
that._sending -= 1;
|
789
|
+
that._active -= 1;
|
724
790
|
if (options.limitConcurrentUploads &&
|
725
791
|
options.limitConcurrentUploads > that._sending) {
|
726
792
|
// Start the next queued upload,
|
727
793
|
// that has not been aborted:
|
728
|
-
var nextSlot = that._slots.shift()
|
729
|
-
isPending;
|
794
|
+
var nextSlot = that._slots.shift();
|
730
795
|
while (nextSlot) {
|
731
|
-
|
732
|
-
// while jQuery 1.8+ removed .isRejected():
|
733
|
-
isPending = nextSlot.state ?
|
734
|
-
nextSlot.state() === 'pending' :
|
735
|
-
!nextSlot.isRejected();
|
736
|
-
if (isPending) {
|
796
|
+
if (that._getDeferredState(nextSlot) === 'pending') {
|
737
797
|
nextSlot.resolve();
|
738
798
|
break;
|
739
799
|
}
|
740
800
|
nextSlot = that._slots.shift();
|
741
801
|
}
|
742
802
|
}
|
803
|
+
if (that._active === 0) {
|
804
|
+
// The stop callback is triggered when all uploads have
|
805
|
+
// been completed, equivalent to the global ajaxStop event:
|
806
|
+
that._trigger('stop');
|
807
|
+
}
|
743
808
|
});
|
744
809
|
return jqXHR;
|
745
810
|
};
|
@@ -805,12 +870,9 @@
|
|
805
870
|
var newData = $.extend({}, data);
|
806
871
|
newData.files = fileSet ? element : [element];
|
807
872
|
newData.paramName = paramNameSet[index];
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
that._onSend(e, this);
|
812
|
-
return this.jqXHR;
|
813
|
-
};
|
873
|
+
that._initResponseObject(newData);
|
874
|
+
that._initProgressObject(newData);
|
875
|
+
that._addConvenienceMethods(e, newData);
|
814
876
|
result = that._trigger('add', e, newData);
|
815
877
|
return result;
|
816
878
|
});
|
@@ -987,44 +1049,50 @@
|
|
987
1049
|
},
|
988
1050
|
|
989
1051
|
_onPaste: function (e) {
|
990
|
-
var
|
991
|
-
|
1052
|
+
var items = e.originalEvent && e.originalEvent.clipboardData &&
|
1053
|
+
e.originalEvent.clipboardData.items,
|
992
1054
|
data = {files: []};
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
1055
|
+
if (items && items.length) {
|
1056
|
+
$.each(items, function (index, item) {
|
1057
|
+
var file = item.getAsFile && item.getAsFile();
|
1058
|
+
if (file) {
|
1059
|
+
data.files.push(file);
|
1060
|
+
}
|
1061
|
+
});
|
1062
|
+
if (this._trigger('paste', e, data) === false ||
|
1063
|
+
this._onAdd(e, data) === false) {
|
1064
|
+
return false;
|
997
1065
|
}
|
998
|
-
});
|
999
|
-
if (this._trigger('paste', e, data) === false ||
|
1000
|
-
this._onAdd(e, data) === false) {
|
1001
|
-
return false;
|
1002
1066
|
}
|
1003
1067
|
},
|
1004
1068
|
|
1005
1069
|
_onDrop: function (e) {
|
1006
1070
|
var that = this,
|
1007
|
-
dataTransfer = e.dataTransfer = e.originalEvent
|
1071
|
+
dataTransfer = e.dataTransfer = e.originalEvent &&
|
1072
|
+
e.originalEvent.dataTransfer,
|
1008
1073
|
data = {};
|
1009
1074
|
if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {
|
1010
1075
|
e.preventDefault();
|
1076
|
+
this._getDroppedFiles(dataTransfer).always(function (files) {
|
1077
|
+
data.files = files;
|
1078
|
+
if (that._trigger('drop', e, data) !== false) {
|
1079
|
+
that._onAdd(e, data);
|
1080
|
+
}
|
1081
|
+
});
|
1011
1082
|
}
|
1012
|
-
this._getDroppedFiles(dataTransfer).always(function (files) {
|
1013
|
-
data.files = files;
|
1014
|
-
if (that._trigger('drop', e, data) !== false) {
|
1015
|
-
that._onAdd(e, data);
|
1016
|
-
}
|
1017
|
-
});
|
1018
1083
|
},
|
1019
1084
|
|
1020
1085
|
_onDragOver: function (e) {
|
1021
|
-
var dataTransfer = e.dataTransfer = e.originalEvent
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1086
|
+
var dataTransfer = e.dataTransfer = e.originalEvent &&
|
1087
|
+
e.originalEvent.dataTransfer;
|
1088
|
+
if (dataTransfer) {
|
1089
|
+
if (this._trigger('dragover', e) === false) {
|
1090
|
+
return false;
|
1091
|
+
}
|
1092
|
+
if ($.inArray('Files', dataTransfer.types) !== -1) {
|
1093
|
+
dataTransfer.dropEffect = 'copy';
|
1094
|
+
e.preventDefault();
|
1095
|
+
}
|
1028
1096
|
}
|
1029
1097
|
},
|
1030
1098
|
|
@@ -1084,12 +1152,23 @@
|
|
1084
1152
|
this._initSpecialOptions();
|
1085
1153
|
this._slots = [];
|
1086
1154
|
this._sequence = this._getXHRPromise(true);
|
1087
|
-
this._sending = this._active =
|
1155
|
+
this._sending = this._active = 0;
|
1156
|
+
this._initProgressObject(this);
|
1088
1157
|
this._initEventHandlers();
|
1089
1158
|
},
|
1090
1159
|
|
1091
|
-
|
1092
|
-
|
1160
|
+
// This method is exposed to the widget API and allows to query
|
1161
|
+
// the number of active uploads:
|
1162
|
+
active: function () {
|
1163
|
+
return this._active;
|
1164
|
+
},
|
1165
|
+
|
1166
|
+
// This method is exposed to the widget API and allows to query
|
1167
|
+
// the widget upload progress.
|
1168
|
+
// It returns an object with loaded, total and bitrate properties
|
1169
|
+
// for the running uploads:
|
1170
|
+
progress: function () {
|
1171
|
+
return this._progress;
|
1093
1172
|
},
|
1094
1173
|
|
1095
1174
|
// This method is exposed to the widget API and allows adding files
|
@@ -35,7 +35,7 @@
|
|
35
35
|
line-height: 31px;
|
36
36
|
}
|
37
37
|
.uploader-button {
|
38
|
-
display: block;
|
38
|
+
display: inline-block;
|
39
39
|
background: #972da0;
|
40
40
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#982da1', endColorstr='#892891');
|
41
41
|
background: -webkit-linear-gradient(left top, left bottom, #982da1, #892891);
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-uploader
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,8 +10,24 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-
|
13
|
+
date: 2013-04-09 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: jquery-ui-rails
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ! '>='
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '0'
|
15
31
|
- !ruby/object:Gem::Dependency
|
16
32
|
name: sqlite3
|
17
33
|
requirement: !ruby/object:Gem::Requirement
|
@@ -44,6 +60,22 @@ dependencies:
|
|
44
60
|
- - ! '>='
|
45
61
|
- !ruby/object:Gem::Version
|
46
62
|
version: '0'
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: mongoid
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
type: :development
|
72
|
+
prerelease: false
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
47
79
|
description: Rails HTML5 FileUpload helpers
|
48
80
|
email: superp1987@gmail.com
|
49
81
|
executables: []
|
@@ -54,10 +86,8 @@ files:
|
|
54
86
|
- app/views/uploader/default/_upload.html.erb
|
55
87
|
- app/views/uploader/default/_sortable.html.erb
|
56
88
|
- app/views/uploader/default/_container.html.erb
|
57
|
-
- app/views/uploader/default/_init.html.erb
|
58
89
|
- app/views/uploader/default/_download.html.erb
|
59
90
|
- app/assets/stylesheets/uploader/application.css
|
60
|
-
- app/assets/javascripts/uploader/init.js
|
61
91
|
- app/assets/javascripts/uploader/application.js
|
62
92
|
- app/controllers/uploader/attachments_controller.rb
|
63
93
|
- lib/uploader.rb
|
@@ -134,11 +164,13 @@ files:
|
|
134
164
|
- spec/dummy/README.rdoc
|
135
165
|
- spec/dummy/script/rails
|
136
166
|
- spec/spec_helper.rb
|
167
|
+
- spec/mongoid_spec.rb
|
137
168
|
- spec/uploader_spec.rb
|
138
169
|
- spec/requests/attachments_controller_spec.rb
|
139
170
|
- spec/factories/articles.rb
|
140
171
|
- spec/factories/assets.rb
|
141
172
|
- spec/factories/files/rails.png
|
173
|
+
- spec/mongoid.yml
|
142
174
|
- spec/fileuploads_spec.rb
|
143
175
|
homepage: https://github.com/superp/rails-uploader
|
144
176
|
licenses: []
|
@@ -160,7 +192,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
160
192
|
version: '0'
|
161
193
|
requirements: []
|
162
194
|
rubyforge_project: rails-uploader
|
163
|
-
rubygems_version: 1.8.
|
195
|
+
rubygems_version: 1.8.25
|
164
196
|
signing_key:
|
165
197
|
specification_version: 3
|
166
198
|
summary: Rails file upload implementation with jQuery-File-Upload
|
@@ -204,10 +236,11 @@ test_files:
|
|
204
236
|
- spec/dummy/README.rdoc
|
205
237
|
- spec/dummy/script/rails
|
206
238
|
- spec/spec_helper.rb
|
239
|
+
- spec/mongoid_spec.rb
|
207
240
|
- spec/uploader_spec.rb
|
208
241
|
- spec/requests/attachments_controller_spec.rb
|
209
242
|
- spec/factories/articles.rb
|
210
243
|
- spec/factories/assets.rb
|
211
244
|
- spec/factories/files/rails.png
|
245
|
+
- spec/mongoid.yml
|
212
246
|
- spec/fileuploads_spec.rb
|
213
|
-
has_rdoc:
|
@@ -1,9 +0,0 @@
|
|
1
|
-
<script type="text/javascript">
|
2
|
-
(function(d, s, id) {
|
3
|
-
var js, fjs = d.getElementsByTagName(s)[0];
|
4
|
-
if (d.getElementById(id)) return;
|
5
|
-
js = d.createElement(s); js.id = id;
|
6
|
-
js.src = "/assets/uploader/application.js";
|
7
|
-
fjs.parentNode.appendChild(js);
|
8
|
-
}(document, 'script', 'uploader-jssdk'));
|
9
|
-
</script>
|