multiuploader 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE.txt +20 -0
- data/README.md +164 -0
- data/lib/multiuploader.rb +4 -0
- data/multiuploader.gemspec +63 -0
- data/vendor/assets/images/easyuploader/empty.png +0 -0
- data/vendor/assets/images/easyuploader/filled.png +0 -0
- data/vendor/assets/javascripts/easyuploader.js.coffee.erb +74 -0
- data/vendor/assets/javascripts/multiuploader.js.coffee +121 -0
- data/vendor/assets/stylesheets/easyuploader.css.scss.erb +51 -0
- metadata +172 -0
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Tim Morgan
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
MultiUploader
|
2
|
+
=============
|
3
|
+
|
4
|
+
A Ruby on Rails engine that adds drag-and-drop streaming multi-file uploader
|
5
|
+
that uses strictly modern standard Web technologies.
|
6
|
+
|
7
|
+
| | |
|
8
|
+
|:------------|:--------------------------------|
|
9
|
+
| **Author** | Tim Morgan |
|
10
|
+
| **Version** | 1.0 (Apr 20, 2012) |
|
11
|
+
| **License** | Released under the MIT license. |
|
12
|
+
|
13
|
+
About
|
14
|
+
-----
|
15
|
+
|
16
|
+
This gem adds a JavaScript library that draws a drag-and-drop target. When a
|
17
|
+
file is dragged to this target, it is queued for upload. Files are uploaded to
|
18
|
+
an endpoint with a configured amount of maximum parallel uploads. JavaScript
|
19
|
+
callbacks are used to track file progress.
|
20
|
+
|
21
|
+
In addition to the uploader itself, a higher-level abstraction, called
|
22
|
+
"EasyUploader", is also included. EasyUploader is powered by MultiUploader, but
|
23
|
+
also includes a quick-'n'-ugly™ user interface. You can use EasyUploader to
|
24
|
+
quickly start testing MultiUploader in your app, or you can even use it in
|
25
|
+
production if you really hate rolling your own designs. It also makes for
|
26
|
+
excellent example code for learning MultiUploader!
|
27
|
+
|
28
|
+
### Requirements
|
29
|
+
|
30
|
+
* **Rails 3.1**: This gem uses Rails engines.
|
31
|
+
* **jQuery**: The carousel and lightbox is rendered and managed using jQuery.
|
32
|
+
* **Sass**: The carousel layout is written using SCSS.
|
33
|
+
|
34
|
+
#### Client Requirements
|
35
|
+
|
36
|
+
For people to use this gem, they will need support for XmlHttpRequest level 2
|
37
|
+
and the JavaScript drag-and-drop API. If you use the theme that ships with this
|
38
|
+
gem, your clients will also need CSS level 3. All of these are supported on
|
39
|
+
recent versions of Safari and Google Chrome.
|
40
|
+
|
41
|
+
Installation
|
42
|
+
------------
|
43
|
+
|
44
|
+
To use this gem, add to your Gemfile:
|
45
|
+
|
46
|
+
```` ruby
|
47
|
+
gem 'multiuploader'
|
48
|
+
````
|
49
|
+
|
50
|
+
To your `application.js` file (or some other JavaScript manifest file), add:
|
51
|
+
|
52
|
+
```` javascript
|
53
|
+
//= require multiuploader
|
54
|
+
````
|
55
|
+
|
56
|
+
You may also need to add the following if it is not already there:
|
57
|
+
|
58
|
+
```` javascript
|
59
|
+
//= require jquery
|
60
|
+
````
|
61
|
+
|
62
|
+
### EasyUploader
|
63
|
+
|
64
|
+
If you wish to additionally use EasyUploader, you must add the following to
|
65
|
+
your `application.css` file (or some other CSS manifest file);
|
66
|
+
|
67
|
+
```` css
|
68
|
+
/*
|
69
|
+
*= require multiuploader
|
70
|
+
*= require easyuploader
|
71
|
+
*/
|
72
|
+
````
|
73
|
+
|
74
|
+
To your `application.js` file (or some other JavaScript manifest file), add:
|
75
|
+
|
76
|
+
```` javascript
|
77
|
+
//= require easyuploader
|
78
|
+
````
|
79
|
+
|
80
|
+
Usage
|
81
|
+
-----
|
82
|
+
|
83
|
+
We'll get started with EasyUploader first, since that's the ... easiest. If you
|
84
|
+
want to skip the baby stuff and get right into hot hot adult uploading, flip to
|
85
|
+
the next subsection.
|
86
|
+
|
87
|
+
### EasyUploader
|
88
|
+
|
89
|
+
All you need to do to start using EasyUploader is create a DIV element and call
|
90
|
+
the `easyUploader` jQuery method on it:
|
91
|
+
|
92
|
+
```` javascript
|
93
|
+
$('#easyuploader').easyUploader("http://some/endpoint", 'file');
|
94
|
+
````
|
95
|
+
|
96
|
+
The first parameter is the URL to upload the files to, and the second is the
|
97
|
+
name of the form field to associate the file data with. The encoding will always
|
98
|
+
be `application/x-www-form-urlencoded`.
|
99
|
+
|
100
|
+
If you use the `easyuploader` ID, the styles in the `easyuploader.css.scss.erb`
|
101
|
+
file will kick in and you should get an instant drag-and-drop target. Drag one
|
102
|
+
or more files in there and you should start seeing the magic happen on your
|
103
|
+
server.
|
104
|
+
|
105
|
+
There is a third parameter, not used above, that allows you to pass in
|
106
|
+
additional options to the underlying MultiUploader:
|
107
|
+
|
108
|
+
```` javascript
|
109
|
+
$('#easyuploader').easyUploader("http://some/endpoint", 'file', {
|
110
|
+
maxSimultaneousUploads: 4
|
111
|
+
});
|
112
|
+
````
|
113
|
+
|
114
|
+
Read the MultiUploader documentation for a full list of options.
|
115
|
+
|
116
|
+
### MultiUploader
|
117
|
+
|
118
|
+
For more low-level control of the upload process, you'll need to use
|
119
|
+
MultiUploader directly. The signature is the same as EasyUploader:
|
120
|
+
|
121
|
+
```` javascript
|
122
|
+
$('#easyuploader').multiUploader("http://some/endpoint", 'file');
|
123
|
+
````
|
124
|
+
|
125
|
+
The only difference is, this time you need to implement the callbacks yourself.
|
126
|
+
There are four: `startHandler`, `progressHandler`, `loadHandler`, and
|
127
|
+
`errorHandler`. Their method signatures are as follows:
|
128
|
+
|
129
|
+
```` javascript
|
130
|
+
$('#easyuploader').multiUploader("http://some/endpoint", 'file', {
|
131
|
+
startHandler: function(file_unique_id, file) {
|
132
|
+
// called when a file begins uploading
|
133
|
+
},
|
134
|
+
progressHandler: function(file_unique_id, state, position, total) {
|
135
|
+
// called periodically as a file is uploaded
|
136
|
+
// (position/total)*100 gives the percent complete
|
137
|
+
},
|
138
|
+
loadHandler: function(file_unique_id, xhr) {
|
139
|
+
// called when the upload is complete and the response has been received
|
140
|
+
// use the xhr (an XmlHttpRequest instance) to get response data
|
141
|
+
},
|
142
|
+
errorHandler: function(file_unique_id, xhr) {
|
143
|
+
// called when the upload fails or an error response is received
|
144
|
+
// same arguments as loadHandler
|
145
|
+
}
|
146
|
+
});
|
147
|
+
````
|
148
|
+
|
149
|
+
Notice that each callback receives a unique ID for the file. These are randomly
|
150
|
+
generated and have no meaningful information. They're just used to keep track of
|
151
|
+
your files. You should associate each upload's unique ID with the page element
|
152
|
+
that displays its progress.
|
153
|
+
|
154
|
+
Also note that the `startHandler` will not necessarily be called the moment the
|
155
|
+
user releases his mouse button. If the `maxSimultaneousUploads` option is set,
|
156
|
+
additional uploads beyond this number will be queued and put into a pending
|
157
|
+
state until an "upload slot" is vacated.
|
158
|
+
|
159
|
+
The `progressHandler` method receives a state parameter. The value will be
|
160
|
+
"upload" when the file is uploading, and "download" when the upload has
|
161
|
+
completed and the client is downloading the server's response.
|
162
|
+
|
163
|
+
For more information, and a list of additional options, see the MultiUploader
|
164
|
+
class documentation.
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "multiuploader"
|
8
|
+
s.version = "1.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Tim Morgan"]
|
12
|
+
s.date = "2012-04-21"
|
13
|
+
s.description = "A drag-and-drop multi-streaming uploader that uses XHR level 2 and the drag-drop JS API (and no Flash!)."
|
14
|
+
s.email = "github@timothymorgan.info"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.md"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
"LICENSE.txt",
|
21
|
+
"README.md",
|
22
|
+
"lib/multiuploader.rb",
|
23
|
+
"multiuploader.gemspec",
|
24
|
+
"vendor/assets/images/easyuploader/empty.png",
|
25
|
+
"vendor/assets/images/easyuploader/filled.png",
|
26
|
+
"vendor/assets/javascripts/easyuploader.js.coffee.erb",
|
27
|
+
"vendor/assets/javascripts/multiuploader.js.coffee",
|
28
|
+
"vendor/assets/stylesheets/easyuploader.css.scss.erb"
|
29
|
+
]
|
30
|
+
s.homepage = "http://github.com/RISCfuture/multiuploader"
|
31
|
+
s.licenses = ["MIT"]
|
32
|
+
s.require_paths = ["lib"]
|
33
|
+
s.rubygems_version = "1.8.23"
|
34
|
+
s.summary = "Multi-file drag-and-drop file uploader using strictly HTML5"
|
35
|
+
|
36
|
+
if s.respond_to? :specification_version then
|
37
|
+
s.specification_version = 3
|
38
|
+
|
39
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
40
|
+
s.add_runtime_dependency(%q<rails>, [">= 0"])
|
41
|
+
s.add_runtime_dependency(%q<compass>, [">= 0"])
|
42
|
+
s.add_runtime_dependency(%q<jquery-rails>, [">= 0"])
|
43
|
+
s.add_development_dependency(%q<yard>, [">= 0"])
|
44
|
+
s.add_development_dependency(%q<bundler>, [">= 0"])
|
45
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
46
|
+
else
|
47
|
+
s.add_dependency(%q<rails>, [">= 0"])
|
48
|
+
s.add_dependency(%q<compass>, [">= 0"])
|
49
|
+
s.add_dependency(%q<jquery-rails>, [">= 0"])
|
50
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
51
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
52
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
53
|
+
end
|
54
|
+
else
|
55
|
+
s.add_dependency(%q<rails>, [">= 0"])
|
56
|
+
s.add_dependency(%q<compass>, [">= 0"])
|
57
|
+
s.add_dependency(%q<jquery-rails>, [">= 0"])
|
58
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
59
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
60
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
Binary file
|
Binary file
|
@@ -0,0 +1,74 @@
|
|
1
|
+
root = exports ? this
|
2
|
+
|
3
|
+
# A basic implementation of the {MultiUploader} class. Use this class in
|
4
|
+
# conjunction with the "easyuploader" assets in `vendor/assets` for a
|
5
|
+
# quick-and-dirty file uploader.
|
6
|
+
#
|
7
|
+
# Use the `$(...).easyUploader(...)` method for a more jQuery-like syntax.
|
8
|
+
#
|
9
|
+
# In order to take advantage of the included quick-'n'-ugly theme, your target
|
10
|
+
# div needs to have an ID of `#easyuploader`.
|
11
|
+
#
|
12
|
+
class EasyUploader
|
13
|
+
|
14
|
+
# Creates a new upload manager.
|
15
|
+
#
|
16
|
+
# @param [jQuery element array] element The element to render the uploader in.
|
17
|
+
# @param [String] url The URL endpoint to post files to.
|
18
|
+
# @param [String] name The name of the file field.
|
19
|
+
# @param [Object] options Additional options to pass to {MultiUploader}.
|
20
|
+
#
|
21
|
+
constructor: (element, url, name, options) ->
|
22
|
+
options = $.extend({}, options,
|
23
|
+
startHandler: (uid, file) =>
|
24
|
+
if !@currentRow || @currentRow.find('>div.file').length == 5
|
25
|
+
@currentRow = $('<div/>').addClass('file-row').appendTo(element)
|
26
|
+
|
27
|
+
# preload images
|
28
|
+
(new Image()).src = "<%= image_path('easyuploader/empty.png') %>"
|
29
|
+
(new Image()).src = "<%= image_path('easyuploader/filled.png') %>"
|
30
|
+
|
31
|
+
fileDiv = $('<div/>').addClass('file').attr('id', "file_#{uid}").appendTo(@currentRow)
|
32
|
+
empty = $('<div/>').addClass('empty').appendTo(fileDiv)
|
33
|
+
$('<div/>').addClass('filled').appendTo empty
|
34
|
+
filename = $('<p/>').text(file.fileName).appendTo(fileDiv)
|
35
|
+
progressHandler: (uid, phase, position, total) =>
|
36
|
+
if (phase == 'upload')
|
37
|
+
amount = Math.round((position/total)*44)
|
38
|
+
$("#file_#{uid} .filled").css 'width', "#{amount}px"
|
39
|
+
loadHandler: (uid, xhr) =>
|
40
|
+
if Math.round(xhr.status/100) == 2
|
41
|
+
$("#file_#{uid}").addClass 'finished'
|
42
|
+
else
|
43
|
+
$("#file_#{uid}").addClass 'error'
|
44
|
+
if (xhr.status == 422)
|
45
|
+
errors = JSON.parse(xhr.responseText)
|
46
|
+
errorList = []
|
47
|
+
|
48
|
+
for fieldErrors in errors
|
49
|
+
do (fieldErrors) -> errorList = errorList.concat(fieldErrors)
|
50
|
+
$('<p/>').addClass('message').text(errorList.join(', ')).appendTo $("#file_#{uid}")
|
51
|
+
else
|
52
|
+
$('<p/>').addClass('message').text(xhr.statusText).appendTo $("#file_#{uid}")
|
53
|
+
|
54
|
+
if uploader.isFinished() && !uploader.isFailed() then window.location.reload()
|
55
|
+
errorHandler: (uid, xhr) =>
|
56
|
+
$("#file_#{uid}").addClass 'error'
|
57
|
+
if uploader.isFinished() && !uploader.isFailed() then window.location.reload()
|
58
|
+
|
59
|
+
)
|
60
|
+
uploader = element.multiUploader url, name, options
|
61
|
+
element.text "Drag files here to upload"
|
62
|
+
|
63
|
+
|
64
|
+
$.fn.extend
|
65
|
+
|
66
|
+
# Creates an EasyUploader in the target element.
|
67
|
+
#
|
68
|
+
# @param [String] url The URL endpoint to post files to.
|
69
|
+
# @param [String] name The name of the file field.
|
70
|
+
# @param [Object] options Additional options to pass to {MultiUploader}.
|
71
|
+
# @return [EasyUploader] The new upload manager.
|
72
|
+
#
|
73
|
+
easyUploader: (url, name, options={}) ->
|
74
|
+
new EasyUploader(this, url, name, options)
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# A drag-and-drop multi-file uploader using strictly modern standard Web
|
2
|
+
# technologies.
|
3
|
+
#
|
4
|
+
# Use the `$(...).multiUploader(...)` method for a more jQuery-like syntax.
|
5
|
+
|
6
|
+
class MultiUploader
|
7
|
+
|
8
|
+
# Creates a new upload manager. Files dropped into `elem` will be uploaded (or
|
9
|
+
# queued for upload). The callbacks will be invoked at each phase of each
|
10
|
+
# file's upload.
|
11
|
+
#
|
12
|
+
# @param [jQuery element array] elem The drop target.
|
13
|
+
# @param [String] url The URL endpoint to post files to.
|
14
|
+
# @param [String] name The name of the file field.
|
15
|
+
# @param [Object] options Additional options.
|
16
|
+
# @option options [Integer] maxSimultaneousUploads The maximum number of
|
17
|
+
# parallel uploads. If not set, unlimited.
|
18
|
+
# @option options [String] method ("POST") The request method.
|
19
|
+
# @option options [Object] data Additional key-value pairs to include in the
|
20
|
+
# request form body.
|
21
|
+
# @option options [Function] startHandler Called when a file begins uploading.
|
22
|
+
# @option options [Function] progressHandler Called when some file data is
|
23
|
+
# uploaded.
|
24
|
+
# @option options [Function] loadHandler Called when a file finishes
|
25
|
+
# uploading.
|
26
|
+
# @option options [Function] errorHandler Called when a file upload fails or a
|
27
|
+
# bad response is received.
|
28
|
+
#
|
29
|
+
constructor: (elem, @url, @name, @options={}) ->
|
30
|
+
@method = @options.method || 'POST'
|
31
|
+
@element = $(elem)
|
32
|
+
|
33
|
+
@activeUploads = 0
|
34
|
+
@successfulUploads = 0
|
35
|
+
@failedUploads = 0
|
36
|
+
@pendingUploads = []
|
37
|
+
|
38
|
+
@element.bind 'dragenter', (event) ->
|
39
|
+
event.stopPropagation()
|
40
|
+
event.preventDefault()
|
41
|
+
false
|
42
|
+
@element.bind 'dragover', (event) ->
|
43
|
+
event.stopPropagation()
|
44
|
+
event.preventDefault()
|
45
|
+
false
|
46
|
+
@element.bind 'drop', this.drop
|
47
|
+
|
48
|
+
# @private
|
49
|
+
drop: (event) =>
|
50
|
+
event.stopPropagation()
|
51
|
+
event.preventDefault()
|
52
|
+
|
53
|
+
@element.text ''
|
54
|
+
|
55
|
+
$.each event.originalEvent.dataTransfer.files, (_, file) =>
|
56
|
+
this.upload file
|
57
|
+
|
58
|
+
# @private
|
59
|
+
isFinished: =>
|
60
|
+
@activeUploads == 0 && @pendingUploads.length == 0
|
61
|
+
|
62
|
+
# @private
|
63
|
+
isFailed: =>
|
64
|
+
@failedUploads > 0
|
65
|
+
|
66
|
+
# Uploads a file, or enqueues it for uploading.
|
67
|
+
#
|
68
|
+
# @param [File] file The file to upload.
|
69
|
+
#
|
70
|
+
upload: (file) =>
|
71
|
+
if @options.maxSimultaneousUploads && @activeUploads > @options.maxSimultaneousUploads
|
72
|
+
@pendingUploads.push file
|
73
|
+
return
|
74
|
+
|
75
|
+
@activeUploads++
|
76
|
+
uid = Math.round(Math.random()*0x1000000).toString(16); # so that the listeners can keep their files apart
|
77
|
+
@options.startHandler(uid, file) if @options.startHandler
|
78
|
+
|
79
|
+
xhr = new XMLHttpRequest()
|
80
|
+
|
81
|
+
data = new FormData()
|
82
|
+
data.append @name, file
|
83
|
+
if @options.data
|
84
|
+
for key, value of @options.data
|
85
|
+
do (key, value) -> data.append key, value
|
86
|
+
|
87
|
+
xhr.addEventListener 'load', (event) =>
|
88
|
+
@activeUploads--
|
89
|
+
if xhr.status >= 400 then @failedUploads++ else @successfulUploads++
|
90
|
+
this.upload @pendingUploads.pop() if @pendingUploads.length > 0
|
91
|
+
xhr.addEventListener 'error', (event) =>
|
92
|
+
@activeUploads--
|
93
|
+
@failedUploads++
|
94
|
+
this.upload @pendingUploads.pop() if @pendingUploads.length > 0
|
95
|
+
|
96
|
+
if @options.progressHandler
|
97
|
+
xhr.upload.addEventListener 'progress', (event) =>
|
98
|
+
@options.progressHandler uid, 'upload', event.position, event.total
|
99
|
+
xhr.addEventListener 'progress', (event) =>
|
100
|
+
@options.progressHandler uid, 'download', event.position, event.total
|
101
|
+
if @options.errorHandler
|
102
|
+
xhr.addEventListener 'error', (event) =>
|
103
|
+
@options.errorHandler uid, xhr
|
104
|
+
if @options.loadHandler
|
105
|
+
xhr.addEventListener 'load', (event) =>
|
106
|
+
@options.loadHandler uid, xhr
|
107
|
+
|
108
|
+
xhr.open @method, @url, true
|
109
|
+
xhr.send data
|
110
|
+
|
111
|
+
$.fn.extend
|
112
|
+
|
113
|
+
# Creates a new file uploader using the target element as the drop zone.
|
114
|
+
#
|
115
|
+
# @param [String] url The URL endpoint to post files to.
|
116
|
+
# @param [String] name The name of the file field.
|
117
|
+
# @param [Object] options Additional options to pass to {MultiUploader}.
|
118
|
+
# @return [MultiUploader] The new upload manager.
|
119
|
+
#
|
120
|
+
multiUploader: (url, name, options={}) ->
|
121
|
+
new MultiUploader(this, url, name, options)
|
@@ -0,0 +1,51 @@
|
|
1
|
+
@import "compass/css3/box";
|
2
|
+
$theme-color: gray;
|
3
|
+
|
4
|
+
#easyuploader {
|
5
|
+
color: $theme-color;
|
6
|
+
font-size: 14pt;
|
7
|
+
font-weight: bold;
|
8
|
+
text-align: center;
|
9
|
+
padding: 20px 10px;
|
10
|
+
background-color: lighten($theme-color, 40%);
|
11
|
+
border: 5px dashed lighten($theme-color, 25%);
|
12
|
+
|
13
|
+
.file-row {
|
14
|
+
@include display-box;
|
15
|
+
@include box-orient(horizontal);
|
16
|
+
@include box-pack(center);
|
17
|
+
}
|
18
|
+
|
19
|
+
.file {
|
20
|
+
margin: 20px;
|
21
|
+
width: 100px;
|
22
|
+
|
23
|
+
.empty {
|
24
|
+
background: url("<%= image_path 'easyuploader/empty.png' %>") no-repeat left top;
|
25
|
+
width: 44px;
|
26
|
+
height: 56px;
|
27
|
+
margin-left: 28px;
|
28
|
+
}
|
29
|
+
|
30
|
+
.filled {
|
31
|
+
background: url("<%= image_path 'easyuploader/filled.png' %>") no-repeat left top;
|
32
|
+
width: 0;
|
33
|
+
height: 56px;
|
34
|
+
}
|
35
|
+
|
36
|
+
p {
|
37
|
+
text-align: center;
|
38
|
+
overflow: hidden;
|
39
|
+
text-overflow: ellipsis;
|
40
|
+
}
|
41
|
+
|
42
|
+
&.finished p { color: black; }
|
43
|
+
&.error p { color: #900; }
|
44
|
+
|
45
|
+
p.message {
|
46
|
+
font-size: 10pt;
|
47
|
+
font-style: italic;
|
48
|
+
font-weight: normal;
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
metadata
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: multiuploader
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Tim Morgan
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-21 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rails
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: compass
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: jquery-rails
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: yard
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: redcarpet
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: bundler
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: jeweler
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
description: A drag-and-drop multi-streaming uploader that uses XHR level 2 and the
|
127
|
+
drag-drop JS API (and no Flash!).
|
128
|
+
email: github@timothymorgan.info
|
129
|
+
executables: []
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files:
|
132
|
+
- LICENSE.txt
|
133
|
+
- README.md
|
134
|
+
files:
|
135
|
+
- LICENSE.txt
|
136
|
+
- README.md
|
137
|
+
- lib/multiuploader.rb
|
138
|
+
- multiuploader.gemspec
|
139
|
+
- vendor/assets/images/easyuploader/empty.png
|
140
|
+
- vendor/assets/images/easyuploader/filled.png
|
141
|
+
- vendor/assets/javascripts/easyuploader.js.coffee.erb
|
142
|
+
- vendor/assets/javascripts/multiuploader.js.coffee
|
143
|
+
- vendor/assets/stylesheets/easyuploader.css.scss.erb
|
144
|
+
homepage: http://github.com/RISCfuture/multiuploader
|
145
|
+
licenses:
|
146
|
+
- MIT
|
147
|
+
post_install_message:
|
148
|
+
rdoc_options: []
|
149
|
+
require_paths:
|
150
|
+
- lib
|
151
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
152
|
+
none: false
|
153
|
+
requirements:
|
154
|
+
- - ! '>='
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: '0'
|
157
|
+
segments:
|
158
|
+
- 0
|
159
|
+
hash: -4392674048479711301
|
160
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ! '>='
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
requirements: []
|
167
|
+
rubyforge_project:
|
168
|
+
rubygems_version: 1.8.23
|
169
|
+
signing_key:
|
170
|
+
specification_version: 3
|
171
|
+
summary: Multi-file drag-and-drop file uploader using strictly HTML5
|
172
|
+
test_files: []
|