multiuploader 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.
@@ -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,4 @@
1
+ # The Rails engine for MultiUploader.
2
+
3
+ class MultiUploader < Rails::Engine
4
+ end
@@ -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
+
@@ -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: []