uploadbox 0.0.13 → 0.0.14

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cf3cbfed4974a811cdaa9bc00700fdb1cc8d57e0
4
- data.tar.gz: 5f080cd8e8be770faf1ae1310568158ae8884a4f
3
+ metadata.gz: 93240b0280249b35b89cd367932e1b2de5e6cce9
4
+ data.tar.gz: e94a982a1aeb55497b4825a2ff89be06037d2914
5
5
  SHA512:
6
- metadata.gz: bd6b3534fb34c79dd511e3c1fbd12b0865df99e938197d21083dbf44b974218e8d3eb1b8b967d0a48cc9aee992663830796ac4e23701842dbc099331d41838da
7
- data.tar.gz: b03253560ed00d6b9f1c6000912c63c4a2d125acded190bfdec3fa20cc647a66b602f8f912920c942a87b3a84b61e357fa757e0c28be2b50d922b392abec20e3
6
+ metadata.gz: 0c1221c95ae558e91ac8699db2ea603bdfb46b5b85a77aea927b58733ebaa52c66a7a621872ade40572d6f988d08998c8e92f370499d9f50c214b29443447649
7
+ data.tar.gz: 2386b4127cedfc97a72c7ec8133748fddb14ebcbb88f921a73f36bd3218d13f88dfdc6774482631f5aecc9d36e09fb303b899df23bc5ad152d699d68a95383bf
Binary file
@@ -7,6 +7,7 @@
7
7
  <font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
8
8
  <missing-glyph horiz-adv-x="1000" />
9
9
  <glyph glyph-name="picture-1" unicode="&#xe800;" d="m357 529q0-45-31-76t-76-32t-76 32t-31 76t31 75t76 32t76-32t31-75z m572-215v-250h-786v107l178 179l90-89l285 285z m53 393h-893q-7 0-12-5t-6-13v-678q0-8 6-13t12-5h893q7 0 13 5t5 13v678q0 7-5 13t-13 5z m89-18v-678q0-37-26-63t-63-27h-893q-36 0-63 27t-26 63v678q0 37 26 63t63 27h893q37 0 63-27t26-63z" horiz-adv-x="1071.4" />
10
+ <glyph glyph-name="plus-1" unicode="&#xe802;" d="m786 439v-107q0-22-16-38t-38-15h-232v-233q0-22-16-37t-38-16h-107q-22 0-38 16t-15 37v233h-232q-23 0-38 15t-16 38v107q0 23 16 38t38 16h232v232q0 22 15 38t38 16h107q23 0 38-16t16-38v-232h232q22 0 38-16t16-38z" horiz-adv-x="785.7" />
10
11
  </font>
11
12
  </defs>
12
13
  </svg>
Binary file
Binary file
@@ -0,0 +1,64 @@
1
+ class @GalleryUploader
2
+ constructor: (@container) ->
3
+ @previews = {}
4
+
5
+ @container.find('input[type="file"]:first').show().fileupload
6
+ type: 'POST'
7
+ dataType: 'xml'
8
+ replaceFileInput: false
9
+ autoUpload: true
10
+ formData: @getFormData
11
+ dropZone: @container
12
+ pasteZone: @container
13
+ add: @add
14
+ progress: @progress
15
+ done: @done
16
+ fail: @fail
17
+
18
+ add: (e, data) =>
19
+ if @loader
20
+ @loader.detach()
21
+
22
+ if @verifyProcessingInterval
23
+ clearInterval(@verifyProcessingInterval)
24
+
25
+ if data.files[0].type.match /gif|jpe?g|png/
26
+ @clone = @container.find('[data-container="uploader"]:first').clone()
27
+ @container.append(@clone)
28
+ previewInstanceName = Manager.getInstanceName('UploaderPreview')
29
+ preview = new UploaderPreview(@clone, data.files[0])
30
+ @clone.data(previewInstanceName, preview)
31
+ @previews[preview.id()] = preview
32
+ data.context = preview.id()
33
+
34
+ @container.closest('form').find('[type=submit]').attr("disabled", true)
35
+ data.submit()
36
+
37
+ getFormData: =>
38
+ preview = @nextPreview()
39
+ filePath = "uploads/#{preview.id()}/" + preview.file.name
40
+ preview.filePath = filePath
41
+ [
42
+ { name: 'key', value: filePath },
43
+ { name: 'acl', value: @container.find('input[name="acl"]').val() },
44
+ { name: 'Content-Type', value: preview.file.type },
45
+ { name: 'AWSAccessKeyId', value: @container.find('input[name="AWSAccessKeyId"]').val() },
46
+ { name: 'policy', value: @container.find('input[name="policy"]').val() },
47
+ { name: 'signature', value: @container.find('input[name="signature"]').val() },
48
+ { name: 'file', value: preview.file }
49
+ ]
50
+
51
+ progress: (e, data) =>
52
+ @previews[data.context].progress(data)
53
+
54
+ done: (e, data) =>
55
+ @previews[data.context].done(data)
56
+
57
+ fail: (e, data) =>
58
+ @previews[data.context].fail(data)
59
+
60
+ nextPreview: =>
61
+ @currentIndex ||= 0
62
+ key = Object.keys(@previews)[@currentIndex]
63
+ @currentIndex++
64
+ @previews[key]
@@ -0,0 +1,18 @@
1
+ class @Manager
2
+ @getInstanceName: (className) ->
3
+ className.charAt(0).toLowerCase() + className.slice(1)
4
+
5
+ @init = (container) ->
6
+ classNames = container.data('component').split(' ')
7
+
8
+ for className in classNames
9
+ try
10
+ instance = new (eval(className))(container)
11
+ instanceName = Manager.getInstanceName(className)
12
+ container.data(instanceName, instance)
13
+ catch error
14
+ try
15
+ console.warn "#{className} component not found"
16
+
17
+ $(document).ready ->
18
+ $('[data-component]').each (i, el) -> Manager.init($(el))
@@ -0,0 +1,134 @@
1
+ class @UploaderPreview
2
+ constructor: (@container, @file) ->
3
+ @loader = $('<div class="progress progress-striped active"><div class="bar" style="width: 0%;"></div></div>').hide()
4
+
5
+ @startLoader() if @isUploadStarting()
6
+
7
+ @container.find('a.btn.fileupload-exists').bind('ajax:success', @delete)
8
+
9
+ @container.find('input[type="file"]:first').show().fileupload
10
+ type: 'POST'
11
+ dataType: 'xml'
12
+ replaceFileInput: false
13
+ autoUpload: true
14
+ formData: @getFormData
15
+ dropZone: @container
16
+ pasteZone: @container
17
+ add: @add
18
+ progress: @progress
19
+ done: @done
20
+ fail: @fail
21
+
22
+ @fileInput = @container.find('input[type="file"]')
23
+ @typeInput = @container.find('input[name="image[imageable_type]"]')
24
+ @uploadNameInput = @container.find('input[name="image[upload_name]"]')
25
+ @idInput = @container.find('[data-item="id"]')
26
+ @thumbContainer = @container.find('.fileupload-preview.thumbnail')
27
+
28
+ startLoader: =>
29
+ @container.prepend(@loader.fadeIn())
30
+ @container.find('.fileupload').removeClass('processing').addClass('uploading')
31
+
32
+
33
+ add: (e, data) =>
34
+ @file = data.files[0]
35
+
36
+ if @loader
37
+ @loader.detach()
38
+
39
+ if @verifyProcessingInterval
40
+ clearInterval(@verifyProcessingInterval)
41
+
42
+ if @file.type.match /gif|jpe?g|png/
43
+ data.context = @id()
44
+ @startLoader()
45
+ @container.closest('form').find('[type=submit]').attr("disabled", true)
46
+ data.submit()
47
+
48
+ getFormData: =>
49
+ @filePath = "uploads/#{@id()}/" + @file.name
50
+
51
+ [
52
+ { name: 'key', value: @filePath },
53
+ { name: 'acl', value: @container.find('input[name="acl"]').val() },
54
+ { name: 'Content-Type', value: @file.type },
55
+ { name: 'AWSAccessKeyId', value: @container.find('input[name="AWSAccessKeyId"]').val() },
56
+ { name: 'policy', value: @container.find('input[name="policy"]').val() },
57
+ { name: 'signature', value: @container.find('input[name="signature"]').val() },
58
+ { name: 'file', value: @file }
59
+ ]
60
+
61
+
62
+ isUploadStarting: =>
63
+ @container.find('.fileupload').hasClass('fileupload-new')
64
+
65
+ id: =>
66
+ @_id ||= uuid.v4()
67
+
68
+ progress: (data) =>
69
+ progress = parseInt(data.loaded / data.total * 100, 10)
70
+ @loader.find('.bar').css({width: progress + '%'})
71
+
72
+ done: (data) =>
73
+ @container.find('.fileupload').removeClass('uploading').addClass('processing')
74
+ $.ajax
75
+ type: 'POST'
76
+ url: @fileInput.data('callback-url')
77
+ data:
78
+ 'image[remote_file_url]': @fileInput.data('url') + @filePath
79
+ 'image[imageable_type]': @typeInput.val()
80
+ 'image[upload_name]': @uploadNameInput.val()
81
+ 'image[secure_random]': @id()
82
+
83
+ complete: =>
84
+ @verifyProcessingInterval = setInterval(@verifyProcessing, 5000)
85
+
86
+ error: =>
87
+ @loader.detach()
88
+ @container.find('.fileupload').removeClass('uploading').removeClass('processing')
89
+ @container.closest('form').find('[type=submit]').attr("disabled", false)
90
+
91
+ verifyProcessing: =>
92
+ arr = @filePath.split('/')
93
+ filename = arr[arr.length - 1]
94
+ $.ajax
95
+ type: 'GET'
96
+ dataType: 'json'
97
+ url: @fileInput.data('find-url')
98
+ data:
99
+ 'name': filename
100
+ 'imageable_type': @typeInput.val()
101
+ 'upload_name': @uploadNameInput.val()
102
+ 'secure_random': @id()
103
+
104
+ complete: (data) =>
105
+ if data.responseJSON.hasOwnProperty('id')
106
+ clearInterval(@verifyProcessingInterval)
107
+ @showThumb(data.responseJSON)
108
+
109
+ error: =>
110
+ @loader.detach()
111
+ @container.detach()
112
+
113
+ showThumb: (image) =>
114
+ @loader.detach()
115
+ @idInput.val(image.id)
116
+ @container.find('a.btn.fileupload-exists').attr('href', image.url)
117
+ @thumbContainer.find('img').detach()
118
+ img = $('<img/>')
119
+ img.attr('src', image.versions[@thumbContainer.data('version')])
120
+ img.attr('width', @thumbContainer.data('width'))
121
+ img.attr('height', @thumbContainer.data('height')).hide()
122
+ @container.find('.fileupload-preview.thumbnail').append(img.fadeIn())
123
+ @container.find('.fileupload').removeClass('fileupload-new').addClass('fileupload-exists')
124
+ @container.find('.fileupload').removeClass('uploading').removeClass('processing')
125
+ @container.closest('form').find('[type=submit]').attr("disabled", false)
126
+
127
+ fail: =>
128
+ @loader.detach()
129
+ @container.detach()
130
+
131
+ delete: =>
132
+ @idInput.val('')
133
+ @container.detach()
134
+
@@ -0,0 +1,245 @@
1
+ // uuid.js
2
+ //
3
+ // Copyright (c) 2010-2012 Robert Kieffer
4
+ // MIT License - http://opensource.org/licenses/mit-license.php
5
+
6
+ (function() {
7
+ var _global = this;
8
+
9
+ // Unique ID creation requires a high quality random # generator. We feature
10
+ // detect to determine the best RNG source, normalizing to a function that
11
+ // returns 128-bits of randomness, since that's what's usually required
12
+ var _rng;
13
+
14
+ // Node.js crypto-based RNG - http://nodejs.org/docs/v0.6.2/api/crypto.html
15
+ //
16
+ // Moderately fast, high quality
17
+ if (typeof(_global.require) == 'function') {
18
+ try {
19
+ var _rb = _global.require('crypto').randomBytes;
20
+ _rng = _rb && function() {return _rb(16);};
21
+ } catch(e) {}
22
+ }
23
+
24
+ if (!_rng && _global.crypto && crypto.getRandomValues) {
25
+ // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
26
+ //
27
+ // Moderately fast, high quality
28
+ var _rnds8 = new Uint8Array(16);
29
+ _rng = function whatwgRNG() {
30
+ crypto.getRandomValues(_rnds8);
31
+ return _rnds8;
32
+ };
33
+ }
34
+
35
+ if (!_rng) {
36
+ // Math.random()-based (RNG)
37
+ //
38
+ // If all else fails, use Math.random(). It's fast, but is of unspecified
39
+ // quality.
40
+ var _rnds = new Array(16);
41
+ _rng = function() {
42
+ for (var i = 0, r; i < 16; i++) {
43
+ if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
44
+ _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
45
+ }
46
+
47
+ return _rnds;
48
+ };
49
+ }
50
+
51
+ // Buffer class to use
52
+ var BufferClass = typeof(_global.Buffer) == 'function' ? _global.Buffer : Array;
53
+
54
+ // Maps for number <-> hex string conversion
55
+ var _byteToHex = [];
56
+ var _hexToByte = {};
57
+ for (var i = 0; i < 256; i++) {
58
+ _byteToHex[i] = (i + 0x100).toString(16).substr(1);
59
+ _hexToByte[_byteToHex[i]] = i;
60
+ }
61
+
62
+ // **`parse()` - Parse a UUID into it's component bytes**
63
+ function parse(s, buf, offset) {
64
+ var i = (buf && offset) || 0, ii = 0;
65
+
66
+ buf = buf || [];
67
+ s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) {
68
+ if (ii < 16) { // Don't overflow!
69
+ buf[i + ii++] = _hexToByte[oct];
70
+ }
71
+ });
72
+
73
+ // Zero out remaining bytes if string was short
74
+ while (ii < 16) {
75
+ buf[i + ii++] = 0;
76
+ }
77
+
78
+ return buf;
79
+ }
80
+
81
+ // **`unparse()` - Convert UUID byte array (ala parse()) into a string**
82
+ function unparse(buf, offset) {
83
+ var i = offset || 0, bth = _byteToHex;
84
+ return bth[buf[i++]] + bth[buf[i++]] +
85
+ bth[buf[i++]] + bth[buf[i++]] + '-' +
86
+ bth[buf[i++]] + bth[buf[i++]] + '-' +
87
+ bth[buf[i++]] + bth[buf[i++]] + '-' +
88
+ bth[buf[i++]] + bth[buf[i++]] + '-' +
89
+ bth[buf[i++]] + bth[buf[i++]] +
90
+ bth[buf[i++]] + bth[buf[i++]] +
91
+ bth[buf[i++]] + bth[buf[i++]];
92
+ }
93
+
94
+ // **`v1()` - Generate time-based UUID**
95
+ //
96
+ // Inspired by https://github.com/LiosK/UUID.js
97
+ // and http://docs.python.org/library/uuid.html
98
+
99
+ // random #'s we need to init node and clockseq
100
+ var _seedBytes = _rng();
101
+
102
+ // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
103
+ var _nodeId = [
104
+ _seedBytes[0] | 0x01,
105
+ _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5]
106
+ ];
107
+
108
+ // Per 4.2.2, randomize (14 bit) clockseq
109
+ var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;
110
+
111
+ // Previous uuid creation time
112
+ var _lastMSecs = 0, _lastNSecs = 0;
113
+
114
+ // See https://github.com/broofa/node-uuid for API details
115
+ function v1(options, buf, offset) {
116
+ var i = buf && offset || 0;
117
+ var b = buf || [];
118
+
119
+ options = options || {};
120
+
121
+ var clockseq = options.clockseq != null ? options.clockseq : _clockseq;
122
+
123
+ // UUID timestamps are 100 nano-second units since the Gregorian epoch,
124
+ // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
125
+ // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
126
+ // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
127
+ var msecs = options.msecs != null ? options.msecs : new Date().getTime();
128
+
129
+ // Per 4.2.1.2, use count of uuid's generated during the current clock
130
+ // cycle to simulate higher resolution clock
131
+ var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1;
132
+
133
+ // Time since last uuid creation (in msecs)
134
+ var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
135
+
136
+ // Per 4.2.1.2, Bump clockseq on clock regression
137
+ if (dt < 0 && options.clockseq == null) {
138
+ clockseq = clockseq + 1 & 0x3fff;
139
+ }
140
+
141
+ // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
142
+ // time interval
143
+ if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) {
144
+ nsecs = 0;
145
+ }
146
+
147
+ // Per 4.2.1.2 Throw error if too many uuids are requested
148
+ if (nsecs >= 10000) {
149
+ throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
150
+ }
151
+
152
+ _lastMSecs = msecs;
153
+ _lastNSecs = nsecs;
154
+ _clockseq = clockseq;
155
+
156
+ // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
157
+ msecs += 12219292800000;
158
+
159
+ // `time_low`
160
+ var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
161
+ b[i++] = tl >>> 24 & 0xff;
162
+ b[i++] = tl >>> 16 & 0xff;
163
+ b[i++] = tl >>> 8 & 0xff;
164
+ b[i++] = tl & 0xff;
165
+
166
+ // `time_mid`
167
+ var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
168
+ b[i++] = tmh >>> 8 & 0xff;
169
+ b[i++] = tmh & 0xff;
170
+
171
+ // `time_high_and_version`
172
+ b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
173
+ b[i++] = tmh >>> 16 & 0xff;
174
+
175
+ // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
176
+ b[i++] = clockseq >>> 8 | 0x80;
177
+
178
+ // `clock_seq_low`
179
+ b[i++] = clockseq & 0xff;
180
+
181
+ // `node`
182
+ var node = options.node || _nodeId;
183
+ for (var n = 0; n < 6; n++) {
184
+ b[i + n] = node[n];
185
+ }
186
+
187
+ return buf ? buf : unparse(b);
188
+ }
189
+
190
+ // **`v4()` - Generate random UUID**
191
+
192
+ // See https://github.com/broofa/node-uuid for API details
193
+ function v4(options, buf, offset) {
194
+ // Deprecated - 'format' argument, as supported in v1.2
195
+ var i = buf && offset || 0;
196
+
197
+ if (typeof(options) == 'string') {
198
+ buf = options == 'binary' ? new BufferClass(16) : null;
199
+ options = null;
200
+ }
201
+ options = options || {};
202
+
203
+ var rnds = options.random || (options.rng || _rng)();
204
+
205
+ // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
206
+ rnds[6] = (rnds[6] & 0x0f) | 0x40;
207
+ rnds[8] = (rnds[8] & 0x3f) | 0x80;
208
+
209
+ // Copy bytes to buffer, if provided
210
+ if (buf) {
211
+ for (var ii = 0; ii < 16; ii++) {
212
+ buf[i + ii] = rnds[ii];
213
+ }
214
+ }
215
+
216
+ return buf || unparse(rnds);
217
+ }
218
+
219
+ // Export public API
220
+ var uuid = v4;
221
+ uuid.v1 = v1;
222
+ uuid.v4 = v4;
223
+ uuid.parse = parse;
224
+ uuid.unparse = unparse;
225
+ uuid.BufferClass = BufferClass;
226
+
227
+ if (typeof define === 'function' && define.amd) {
228
+ // Publish as AMD module
229
+ define(function() {return uuid;});
230
+ } else if (typeof(module) != 'undefined' && module.exports) {
231
+ // Publish as node.js module
232
+ module.exports = uuid;
233
+ } else {
234
+ // Publish as global (in browsers)
235
+ var _previousRoot = _global.uuid;
236
+
237
+ // **`noConflict()` - (browser only) to reset global 'uuid' var**
238
+ uuid.noConflict = function() {
239
+ _global.uuid = _previousRoot;
240
+ return uuid;
241
+ };
242
+
243
+ _global.uuid = uuid;
244
+ }
245
+ }).call(this);
@@ -2,5 +2,9 @@
2
2
  #= require jquery.iframe-transport
3
3
  #= require cors/jquery.postmessage-transport
4
4
  #= require cors/jquery.xdr-transport
5
+ #= require _uuid
5
6
  #= require jquery.fileupload
6
7
  #= require _image_uploader
8
+ #= require _uploader_preview
9
+ #= require _gallery_uploader
10
+ #= require _manager
@@ -1,10 +1,10 @@
1
1
  @font-face {
2
2
  font-family: 'fontello';
3
- src: url('fontello.eot?99792958');
4
- src: url('fontello.eot?99792958#iefix') format('embedded-opentype'),
5
- url('fontello.woff?99792958') format('woff'),
6
- url('fontello.ttf?99792958') format('truetype'),
7
- url('fontello.svg?99792958#fontello') format('svg');
3
+ src: url('fontello.eot?18809145');
4
+ src: url('fontello.eot?18809145#iefix') format('embedded-opentype'),
5
+ url('fontello.woff?18809145') format('woff'),
6
+ url('fontello.ttf?18809145') format('truetype'),
7
+ url('fontello.svg?18809145#fontello') format('svg');
8
8
  font-weight: normal;
9
9
  font-style: normal;
10
10
  }
@@ -14,7 +14,7 @@
14
14
  @media screen and (-webkit-min-device-pixel-ratio:0) {
15
15
  @font-face {
16
16
  font-family: 'fontello';
17
- src: url('../font/fontello.svg?99792958#fontello') format('svg');
17
+ src: url('../font/fontello.svg?18809145#fontello') format('svg');
18
18
  }
19
19
  }
20
20
  */
@@ -50,4 +50,5 @@
50
50
  /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
51
51
  }
52
52
 
53
- .icon-picture-1:before { content: '\e800'; } /* '' */
53
+ .icon-picture-1:before { content: '\e800'; } /* '' */
54
+ .icon-plus-1:before { content: '\e802'; } /* '' */
@@ -3,7 +3,6 @@
3
3
 
4
4
  .uploadbox-image-uploader
5
5
  position: relative
6
- padding-bottom: 30px
7
6
 
8
7
  .btn
9
8
  background-color: #f7f7f7
@@ -15,18 +14,17 @@
15
14
  .btn
16
15
  border: 1px solid darken(#f7f7f7, 20%)
17
16
 
18
- .icon-picture-1
17
+ .icon
19
18
  opacity: .5
20
19
 
21
20
  .fileupload-exists
22
- .icon-picture-1
21
+ .icon
23
22
  display: none
24
23
 
25
- .icon-picture-1
24
+ .icon
26
25
  position: absolute
27
26
  top: 0
28
27
  left: 0
29
- font-size: 40px
30
28
  width: 100%
31
29
  height: 100%
32
30
  opacity: .3
@@ -0,0 +1,61 @@
1
+ = form.fields_for :image do
2
+ div data-component="GalleryUploader"
3
+ .uploadbox-image-uploader.uploads-many data-container="uploader" style="width: #{width}px; height: #{height}px;"
4
+ - if namespace
5
+ input name="[#{resource.class.name.underscore}][#{namespace}]#{upload_name}[]" data-item="id" type="hidden"
6
+ - else
7
+ input name="[#{resource.class.name.underscore}]#{upload_name}[]" data-item="id" type="hidden"
8
+
9
+ .fileupload data-provides="fileupload" class="fileupload-new"
10
+ .fileupload-preview.thumbnail data-version="#{version}" data-width="#{width}" data-height="#{height}" style="width: #{width}px; height: #{height}px;"
11
+
12
+ .fileupload-actions
13
+ span.btn.btn-file style="width: #{width}px; height: #{height}px;"
14
+ span.fileupload-new = choose_label
15
+ span.fileupload-exists = update_label
16
+ i.icon.icon-plus-1 style="line-height: #{height}px; font-size: #{(width * 0.4).to_i}px"
17
+
18
+ input type="file" name="image[file]" data-callback-url="#{uploadbox.images_path}" data-find-url="#{uploadbox.find_images_path(format: :json)}" data-url="https://#{ENV['S3_BUCKET']}.s3.amazonaws.com/" accept="image/png image/x-png, image/gif, image/jpeg" style="display: none; width: #{width}px; height: #{height}px;" multiple="true"
19
+ input type="hidden" name="policy" value="#{s3_policy}"
20
+ input type="hidden" name="signature" value="#{s3_signature}"
21
+ input type="hidden" name="AWSAccessKeyId" value="#{ENV['S3_KEY']}"
22
+ input type="hidden" name="acl" value="public-read"
23
+ input type="hidden" name="key"
24
+
25
+ input type="hidden" name="image[imageable_type]" value="#{resource.class}"
26
+ input type="hidden" name="image[upload_name]" value="#{upload_name}"
27
+ - if removable
28
+ - if resource.send(upload_name).present?
29
+ = link_to destroy_label, uploadbox.image_path(resource.send(upload_name)), class: 'btn fileupload-exists', remote: true, method: :delete
30
+ - else
31
+ = link_to destroy_label, '#', class: 'btn fileupload-exists', remote: true, method: :delete
32
+
33
+ - for image in resource.send(upload_name)
34
+ .uploadbox-image-uploader.uploads-many data-component="UploaderPreview" data-container="uploader" style="width: #{width}px; height: #{height}px;"
35
+ - if namespace
36
+ input name="[#{resource.class.name.underscore}][#{namespace}]#{upload_name}[]" data-item="id" type="hidden" value="#{image.id}"
37
+ - else
38
+ input name="[#{resource.class.name.underscore}]#{upload_name}[]" data-item="id" type="hidden" value="#{image.id}"
39
+
40
+ .fileupload data-provides="fileupload" class="fileupload-exists"
41
+ .fileupload-preview.thumbnail data-version="#{version}" data-width="#{width}" data-height="#{height}" style="width: #{width}px; height: #{height}px;"
42
+ = img image.send(version)
43
+
44
+ .fileupload-actions
45
+ span.btn.btn-file style="width: #{width}px; height: #{height}px;"
46
+ span.fileupload-new = choose_label
47
+ span.fileupload-exists = update_label
48
+ i.icon.icon-plus-1 style="line-height: #{height}px; font-size: #{(width * 0.4).to_i}px"
49
+
50
+ input type="file" name="image[file]" data-callback-url="#{uploadbox.images_path}" data-find-url="#{uploadbox.find_images_path(format: :json)}" data-url="https://#{ENV['S3_BUCKET']}.s3.amazonaws.com/" accept="image/png image/x-png, image/gif, image/jpeg" style="display: none; width: #{width}px; height: #{height}px;" multiple="true"
51
+ input type="hidden" name="policy" value="#{s3_policy}"
52
+ input type="hidden" name="signature" value="#{s3_signature}"
53
+ input type="hidden" name="AWSAccessKeyId" value="#{ENV['S3_KEY']}"
54
+ input type="hidden" name="acl" value="public-read"
55
+ input type="hidden" name="key"
56
+
57
+ input type="hidden" name="image[imageable_type]" value="#{resource.class}"
58
+ input type="hidden" name="image[upload_name]" value="#{upload_name}"
59
+ - if removable
60
+ = link_to destroy_label, uploadbox.image_path(image), class: 'btn fileupload-exists', remote: true, method: :delete
61
+
@@ -1,10 +1,11 @@
1
1
  = form.fields_for :image do
2
2
  - secure_random = SecureRandom.uuid
3
- .uploadbox-image-uploader data-component="ImageUploader" style="width: #{width}px; height: #{height}px;"
3
+ .uploadbox-image-uploader.uploads-one data-component="ImageUploader" style="width: #{width}px; height: #{height}px;"
4
4
  - if namespace
5
- input name="[#{namespace}]#{upload_name}_id" data-item="id" type="hidden" value="#{resource.send(upload_name).try :id}"
5
+ input name="[#{resource.class.name.underscore}][#{namespace}]#{upload_name}" data-item="id" type="hidden" value="#{resource.send(upload_name).try :id}"
6
6
  - else
7
- input name="#{upload_name}_id" data-item="id" type="hidden" value="#{resource.send(upload_name).try :id}"
7
+ input name="[#{resource.class.name.underscore}]#{upload_name}" data-item="id" type="hidden" value="#{resource.send(upload_name).try :id}"
8
+
8
9
  .fileupload data-provides="fileupload" class="fileupload-#{(resource.send("#{upload_name}?") or default) ? 'exists' : 'new'}"
9
10
  .fileupload-preview.thumbnail data-version="#{version}" data-width="#{width}" data-height="#{height}" style="width: #{width}px; height: #{height}px;"
10
11
  - if resource.send("#{upload_name}?")
@@ -16,8 +17,10 @@
16
17
  span.btn.btn-file style="width: #{width}px; height: #{height}px;"
17
18
  span.fileupload-new = choose_label
18
19
  span.fileupload-exists = update_label
19
- i.icon-picture-1 style="line-height: #{height}px"
20
- input type="file" name="image[file]" data-callback-url="#{uploadbox.images_path}" data-find-url="#{uploadbox.find_images_path(format: :json)}" data-url="https://#{ENV['S3_BUCKET']}.s3.amazonaws.com/" data-secure-random="#{secure_random}" accept="image/x-png, image/gif, image/jpeg" style="display: none; width: #{width}px; height: #{height}px;"
20
+ i.icon.icon-picture-1 style="line-height: #{height}px; font-size: #{(width * 0.4).to_i}px"
21
+
22
+
23
+ input type="file" name="image[file]" data-callback-url="#{uploadbox.images_path}" data-find-url="#{uploadbox.find_images_path(format: :json)}" data-url="https://#{ENV['S3_BUCKET']}.s3.amazonaws.com/" data-secure-random="#{secure_random}" accept="image/png image/x-png, image/gif, image/jpeg" style="display: none; width: #{width}px; height: #{height}px;"
21
24
  input type="hidden" name="policy" value="#{s3_policy}"
22
25
  input type="hidden" name="signature" value="#{s3_signature}"
23
26
  input type="hidden" name="AWSAccessKeyId" value="#{ENV['S3_KEY']}"
data/config/spring.rb ADDED
@@ -0,0 +1 @@
1
+ Spring.application_root = './spec/dummy'
@@ -28,7 +28,7 @@ module Uploadbox
28
28
  end
29
29
 
30
30
  class ActionView::Helpers::FormBuilder
31
- def uploader(upload_name, options={})
31
+ def uploads_one(upload_name, options={})
32
32
  upload_model_class = "Uploadbox::#{@object.class.to_s + upload_name.to_s.camelize}".constantize
33
33
  options.reverse_merge!(preview: upload_model_class.versions.keys.first,
34
34
  namespace: false,
@@ -37,7 +37,32 @@ class ActionView::Helpers::FormBuilder
37
37
  choose_label: 'Escolher',
38
38
  destroy_label: '&times;'.html_safe)
39
39
  dimensions = upload_model_class.versions[options[:preview]]
40
- @template.render partial: 'uploadbox/images/uploader', locals: {
40
+ @template.render partial: 'uploadbox/images/uploads_one', locals: {
41
+ upload_name: upload_name,
42
+ resource: @object,
43
+ form: self,
44
+ version: options[:preview],
45
+ width: dimensions[0],
46
+ height: dimensions[1],
47
+ namespace: options[:namespace],
48
+ default: options[:default],
49
+ removable: upload_model_class.removable?,
50
+ update_label: options[:update_label],
51
+ choose_label: options[:choose_label],
52
+ destroy_label: options[:destroy_label]
53
+ }
54
+ end
55
+
56
+ def uploads_many(upload_name, options={})
57
+ upload_model_class = "Uploadbox::#{@object.class.to_s + upload_name.to_s.camelize}".constantize
58
+ options.reverse_merge!(preview: upload_model_class.versions.keys.first,
59
+ namespace: false,
60
+ default: false,
61
+ update_label: 'Alterar',
62
+ choose_label: 'Escolher',
63
+ destroy_label: '&times;'.html_safe)
64
+ dimensions = upload_model_class.versions[options[:preview]]
65
+ @template.render partial: 'uploadbox/images/uploads_many', locals: {
41
66
  upload_name: upload_name,
42
67
  resource: @object,
43
68
  form: self,
@@ -54,4 +79,4 @@ class ActionView::Helpers::FormBuilder
54
79
  end
55
80
  end
56
81
 
57
- require 'uploadbox/image_uploader'
82
+ require 'uploadbox/image_uploader'
@@ -23,6 +23,7 @@ module Uploadbox
23
23
  upload and upload.file?
24
24
  end
25
25
 
26
+ # @post.picture
26
27
  define_method(upload_name) do
27
28
  upload = send("#{upload_name}_upload")
28
29
 
@@ -48,22 +49,15 @@ module Uploadbox
48
49
  end
49
50
  end
50
51
 
51
- # @post.attach_picture
52
- define_method("attach_#{upload_name}") do |upload_id|
53
- if upload_id.present?
54
- self.send("attach_#{upload_name}!", upload_id)
55
- end
52
+ # @post.picture=(id)
53
+ define_method("#{upload_name}=") do |upload_id|
54
+ self.send("#{upload_name}_upload=", upload_class.find(upload_id))
56
55
  end
57
56
 
58
57
  # @post.remote_picture_url=('http://exemple.com/image.jpg')
59
58
  define_method("remote_#{upload_name}_url=") do |url|
60
59
  upload = Uploadbox.const_get(upload_class_name).create!(remote_file_url: url)
61
- self.send("#{upload_name}=", upload)
62
- end
63
-
64
- # @post.attach_picture!
65
- define_method("attach_#{upload_name}!") do |upload_id|
66
- self.send("#{upload_name}=", upload_class.find(upload_id))
60
+ self.send("#{upload_name}_upload=", upload)
67
61
  end
68
62
 
69
63
  # Post.update_picture_versions!
@@ -80,6 +74,94 @@ module Uploadbox
80
74
  options[:removable]
81
75
  end
82
76
 
77
+ upload_class.instance_eval do
78
+ delegate *upload_versions.keys, to: :file
79
+
80
+ default_scope -> { where(imageable_type: imageable_type).where(upload_name: upload_name.to_s) }
81
+
82
+ # Uploabox::PostPictureUploader < UploadBox::ImgProcessing < CarrierWave
83
+ dynamic_uploader = Class.new(Uploadbox::ImageProcessingUploader)
84
+ Uploadbox.const_set(self.name.demodulize + 'Uploader', dynamic_uploader)
85
+ dynamic_uploader.class_eval do
86
+ upload_versions.each do |version_name, dimensions|
87
+ if options[:retina]
88
+ dimensions = dimensions.map{ |d| d * 2 }
89
+ end
90
+
91
+ version version_name do
92
+ process resize_to_fill: dimensions
93
+ process quality: quality = options[:quality]
94
+ end
95
+
96
+ def dimensions
97
+ model.class.versions[version_name]
98
+ end
99
+
100
+ def width
101
+ dimensions[0]
102
+ end
103
+
104
+ def height
105
+ dimensions[1]
106
+ end
107
+ end
108
+ end
109
+ mount_uploader :file, dynamic_uploader
110
+
111
+ end
112
+
113
+ has_one "#{upload_name}_upload".to_sym, as: :imageable,
114
+ class_name: "Uploadbox::#{self.to_s + upload_name.to_s.camelize}",
115
+ autosave: true
116
+ accepts_nested_attributes_for "#{upload_name}_upload".to_sym
117
+ end
118
+
119
+
120
+ def uploads_many(upload_name, options={})
121
+ default_options = {
122
+ default: false,
123
+ placeholder: false,
124
+ removable: true,
125
+ retina: Uploadbox.retina,
126
+ quality: Uploadbox.retina ? (Uploadbox.retina_quality || 40) : (Uploadbox.image_quality || 80)
127
+ }
128
+ options = options.reverse_merge(default_options)
129
+ upload_versions = options.select{ |key| default_options.keys.exclude? key }
130
+ options = options.select{ |key| default_options.keys.include? key }
131
+
132
+ imageable_type = self.to_s
133
+ upload_class_name = imageable_type + upload_name.to_s.camelize
134
+ upload_class = Class.new(Image)
135
+ Uploadbox.const_set(upload_class_name, upload_class)
136
+
137
+ # @post.images?
138
+ define_method("#{upload_name}?") do
139
+ upload = send(upload_name)
140
+ upload and upload.any?
141
+ end
142
+
143
+ # @post.images=([id, id])
144
+ define_method("#{upload_name}=") do |ids|
145
+ self.send(upload_name).send('replace', [])
146
+ for id in ids.select(&:present?)
147
+ self.send(upload_name).send('<<', upload_class.find(id))
148
+ end
149
+ end
150
+
151
+ # Post.update_images_versions!
152
+ self.define_singleton_method "update_#{upload_name}_versions!" do
153
+ Uploadbox.const_get(upload_class_name).find_each{|upload| upload.file.recreate_versions!}
154
+ end
155
+
156
+ # Uploadbox::PostImages < Image
157
+ upload_class.define_singleton_method :versions do
158
+ upload_versions
159
+ end
160
+
161
+ upload_class.define_singleton_method :removable? do
162
+ options[:removable]
163
+ end
164
+
83
165
  upload_class.instance_eval do
84
166
  delegate *upload_versions.keys, to: :file
85
167
 
@@ -115,7 +197,7 @@ module Uploadbox
115
197
  mount_uploader :file, dynamic_uploader
116
198
  end
117
199
 
118
- has_one "#{upload_name}_upload".to_sym, as: :imageable, dependent: :destroy, class_name: "Uploadbox::#{self.to_s + upload_name.to_s.camelize}"
200
+ has_many upload_name, as: :imageable, class_name: "Uploadbox::#{self.to_s + upload_name.to_s.camelize}"
119
201
  end
120
202
 
121
203
  end
@@ -1,3 +1,3 @@
1
1
  module Uploadbox
2
- VERSION = "0.0.13"
2
+ VERSION = "0.0.14"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uploadbox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.13
4
+ version: 0.0.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julio Protzek
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-10-17 00:00:00.000000000 Z
12
+ date: 2013-10-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -347,6 +347,34 @@ dependencies:
347
347
  - - ~>
348
348
  - !ruby/object:Gem::Version
349
349
  version: 0.3.2
350
+ - !ruby/object:Gem::Dependency
351
+ name: dotenv-rails
352
+ requirement: !ruby/object:Gem::Requirement
353
+ requirements:
354
+ - - '>='
355
+ - !ruby/object:Gem::Version
356
+ version: '0'
357
+ type: :development
358
+ prerelease: false
359
+ version_requirements: !ruby/object:Gem::Requirement
360
+ requirements:
361
+ - - '>='
362
+ - !ruby/object:Gem::Version
363
+ version: '0'
364
+ - !ruby/object:Gem::Dependency
365
+ name: launchy
366
+ requirement: !ruby/object:Gem::Requirement
367
+ requirements:
368
+ - - '>='
369
+ - !ruby/object:Gem::Version
370
+ version: '0'
371
+ type: :development
372
+ prerelease: false
373
+ version_requirements: !ruby/object:Gem::Requirement
374
+ requirements:
375
+ - - '>='
376
+ - !ruby/object:Gem::Version
377
+ version: '0'
350
378
  description: Uploadbox makes easy to manage files in your Rails application.
351
379
  email:
352
380
  - julio@startae.com.br
@@ -359,7 +387,11 @@ files:
359
387
  - app/assets/font/fontello.svg
360
388
  - app/assets/font/fontello.ttf
361
389
  - app/assets/font/fontello.woff
390
+ - app/assets/javascripts/_gallery_uploader.coffee
362
391
  - app/assets/javascripts/_image_uploader.coffee
392
+ - app/assets/javascripts/_manager.coffee
393
+ - app/assets/javascripts/_uploader_preview.coffee
394
+ - app/assets/javascripts/_uuid.js
363
395
  - app/assets/javascripts/cors/jquery.postmessage-transport.js
364
396
  - app/assets/javascripts/cors/jquery.xdr-transport.js
365
397
  - app/assets/javascripts/jquery.fileupload.js
@@ -367,7 +399,7 @@ files:
367
399
  - app/assets/javascripts/jquery.ui.widget.js
368
400
  - app/assets/javascripts/uploadbox.coffee
369
401
  - app/assets/stylesheets/bootstrap/_progress.css
370
- - app/assets/stylesheets/fontello.scss
402
+ - app/assets/stylesheets/fontello.css
371
403
  - app/assets/stylesheets/uploadbox.sass
372
404
  - app/controllers/uploadbox/application_controller.rb
373
405
  - app/controllers/uploadbox/images_controller.rb
@@ -377,9 +409,11 @@ files:
377
409
  - app/models/image.rb
378
410
  - app/uploaders/uploadbox/image_processing_uploader.rb
379
411
  - app/views/layouts/uploadbox/application.html.erb
380
- - app/views/uploadbox/images/_uploader.html.slim
412
+ - app/views/uploadbox/images/_uploads_many.slim
413
+ - app/views/uploadbox/images/_uploads_one.slim
381
414
  - app/views/uploadbox/images/find.json.jbuilder
382
415
  - config/routes.rb
416
+ - config/spring.rb
383
417
  - lib/form_builder.rb
384
418
  - lib/generators/uploadbox/image/image_generator.rb
385
419
  - lib/generators/uploadbox/image/templates/initializers/uploadbox.rb