uploadcare-widget 0.9 → 0.11.1
Sign up to get free protection for your applications and to get access to all the features.
- data/app/assets/images/uploadcare/images/tab-icons-active.png +0 -0
- data/app/assets/images/uploadcare/images/tab-icons.png +0 -0
- data/app/assets/javascripts/uploadcare/core/boot.js.coffee +0 -1
- data/app/assets/javascripts/uploadcare/core/namespace.coffee +12 -1
- data/app/assets/javascripts/uploadcare/files.js.coffee +14 -9
- data/app/assets/javascripts/uploadcare/files/base.js.coffee +4 -1
- data/app/assets/javascripts/uploadcare/files/uploaded.js.coffee +1 -1
- data/app/assets/javascripts/uploadcare/files/url.js.coffee +1 -1
- data/app/assets/javascripts/uploadcare/locale/en.js.coffee +2 -1
- data/app/assets/javascripts/uploadcare/locale/es.js.coffee +2 -1
- data/app/assets/javascripts/uploadcare/locale/ru.js.coffee +1 -0
- data/app/assets/javascripts/uploadcare/settings.js.coffee +19 -2
- data/app/assets/javascripts/uploadcare/templates/circle-canvas.jst.ejs +1 -0
- data/app/assets/javascripts/uploadcare/templates/circle-text.jst.ejs +3 -0
- data/app/assets/javascripts/uploadcare/templates/tab-file.jst.ejs +16 -14
- data/app/assets/javascripts/uploadcare/templates/widget-button.jst.ejs +4 -4
- data/app/assets/javascripts/uploadcare/templates/widget.jst.ejs +1 -1
- data/app/assets/javascripts/uploadcare/ui/progress.js.coffee +133 -83
- data/app/assets/javascripts/uploadcare/utils/abilities.js.coffee +6 -1
- data/app/assets/javascripts/uploadcare/widget.js.coffee.erb +3 -0
- data/app/assets/javascripts/uploadcare/widget/base-widget.js.coffee +2 -1
- data/app/assets/javascripts/uploadcare/widget/dialog.js.coffee +1 -0
- data/app/assets/javascripts/uploadcare/widget/dragdrop.js.coffee +14 -5
- data/app/assets/javascripts/uploadcare/widget/tabs/file-tab.js.coffee +2 -4
- data/app/assets/javascripts/uploadcare/widget/tabs/remote-tab.js.coffee +11 -1
- data/app/assets/javascripts/uploadcare/widget/widget.js.coffee +1 -0
- data/app/assets/stylesheets/uploadcare/dialog.css.scss +3 -0
- data/app/assets/stylesheets/uploadcare/images.css.scss +2 -1
- data/app/assets/stylesheets/uploadcare/widget.css.scss +12 -12
- data/lib/uploadcare-widget/version.rb +1 -1
- data/test/dummy/Gemfile.lock +2 -2
- data/test/dummy/spec/javascripts/spec/files.js.coffee +1 -1
- metadata +6 -7
- data/app/assets/javascripts/uploadcare/core/eve.js +0 -217
- data/app/assets/javascripts/uploadcare/core/raphael.js +0 -5605
- data/app/assets/javascripts/uploadcare/templates/circle.jst.ejs +0 -3
Binary file
|
Binary file
|
@@ -18,4 +18,15 @@ uploadcare.namespace = (path, fn) ->
|
|
18
18
|
fn(target)
|
19
19
|
|
20
20
|
uploadcare.expose = (key, value) ->
|
21
|
-
|
21
|
+
parts = key.split('.')
|
22
|
+
last = parts.pop()
|
23
|
+
|
24
|
+
target = window.uploadcare
|
25
|
+
source = uploadcare
|
26
|
+
|
27
|
+
for part in parts
|
28
|
+
target[part] ||= {}
|
29
|
+
target = target[part]
|
30
|
+
source = source?[part]
|
31
|
+
|
32
|
+
target[last] = value || source[last]
|
@@ -41,18 +41,10 @@ namespace 'uploadcare', (ns) ->
|
|
41
41
|
input: (settings, input) ->
|
42
42
|
[new f.InputFile(settings, input)]
|
43
43
|
url: (settings, urls) ->
|
44
|
-
# We also accept plain UUIDs here for an internally used shortcut.
|
45
|
-
# Typically, you should use the `uploaded` converter for clarity.
|
46
44
|
unless $.isArray(urls)
|
47
45
|
urls = [urls]
|
48
46
|
for url in urls
|
49
|
-
|
50
|
-
.replace(/^https?/i, 'https?')
|
51
|
-
cdn = new RegExp("^#{cdnBase}/#{utils.uuidRegex.source}", 'i')
|
52
|
-
if utils.fullUuidRegex.test(url) || cdn.test(url)
|
53
|
-
new f.UploadedFile settings, url
|
54
|
-
else
|
55
|
-
new f.UrlFile settings, url
|
47
|
+
new f.UrlFile settings, url
|
56
48
|
uploaded: (settings, uuids) ->
|
57
49
|
unless $.isArray(uuids)
|
58
50
|
uuids = [uuids]
|
@@ -65,3 +57,16 @@ namespace 'uploadcare', (ns) ->
|
|
65
57
|
new f.ReadyFile(settings, fileData)
|
66
58
|
else
|
67
59
|
new f.DeletedFile()
|
60
|
+
|
61
|
+
# internally used shortcut
|
62
|
+
'url-or-uploaded': (settings, urls) ->
|
63
|
+
unless $.isArray(urls)
|
64
|
+
urls = [urls]
|
65
|
+
cdnBase = utils.escapeRegExp(settings.cdnBase)
|
66
|
+
.replace(/^https?/i, 'https?')
|
67
|
+
cdn = new RegExp("^#{cdnBase}/#{utils.uuidRegex.source}", 'i')
|
68
|
+
for url in urls
|
69
|
+
if utils.fullUuidRegex.test(url) || cdn.test(url)
|
70
|
+
new f.UploadedFile settings, url
|
71
|
+
else
|
72
|
+
new f.UrlFile settings, url
|
@@ -92,6 +92,9 @@ namespace 'uploadcare.files', (ns) ->
|
|
92
92
|
width: img.width
|
93
93
|
height: img.height
|
94
94
|
|
95
|
+
img.onerror = =>
|
96
|
+
@reject()
|
97
|
+
|
95
98
|
img.src = url
|
96
99
|
).promise()
|
97
100
|
|
@@ -196,6 +199,6 @@ namespace 'uploadcare.utils', (utils) ->
|
|
196
199
|
if utils.isFile(value)
|
197
200
|
value
|
198
201
|
else
|
199
|
-
uploadcare.fileFrom('url', value, settings)
|
202
|
+
uploadcare.fileFrom('url-or-uploaded', value, settings)
|
200
203
|
else
|
201
204
|
null
|
@@ -81,7 +81,7 @@ namespace 'uploadcare.files', (ns) ->
|
|
81
81
|
success: (data) =>
|
82
82
|
return if @__shutdown
|
83
83
|
@__state('progress', data)
|
84
|
-
[@fileName, @fileId] = [data.original_filename, data.
|
84
|
+
[@fileName, @fileId] = [data.original_filename, data.uuid]
|
85
85
|
@__uploadDf.resolve(this)
|
86
86
|
|
87
87
|
error: =>
|
@@ -32,7 +32,8 @@ uploadcare.namespace 'uploadcare.locale.translations', (ns) ->
|
|
32
32
|
dropbox: 'Dropbox'
|
33
33
|
gdrive: 'Google Drive'
|
34
34
|
instagram: 'Instagram'
|
35
|
-
vk: '
|
35
|
+
vk: 'VK'
|
36
|
+
evernote: 'Evernote'
|
36
37
|
url: 'Una dirección cualquiera'
|
37
38
|
url:
|
38
39
|
title: 'Archivos de la web'
|
@@ -23,14 +23,14 @@ namespace 'uploadcare.settings', (ns) ->
|
|
23
23
|
'public-key': null
|
24
24
|
'pusher-key': '79ae88bd931ea68464d9'
|
25
25
|
'social-base': 'https://social.uploadcare.com'
|
26
|
-
'tabs': 'file url facebook gdrive instagram'
|
26
|
+
'tabs': 'file url facebook gdrive instagram evernote'
|
27
27
|
'url-base': 'https://upload.uploadcare.com'
|
28
28
|
'script-base': if SCRIPT_BASE? then SCRIPT_BASE else ''
|
29
29
|
'script-ext': '.min.js'
|
30
30
|
|
31
31
|
presets =
|
32
32
|
'tabs':
|
33
|
-
all: 'file url facebook vk dropbox gdrive instagram'
|
33
|
+
all: 'file url facebook vk dropbox gdrive instagram evernote'
|
34
34
|
default: defaults.tabs
|
35
35
|
|
36
36
|
|
@@ -159,3 +159,20 @@ namespace 'uploadcare.settings', (ns) ->
|
|
159
159
|
waitForSettingsCb.add (common) ->
|
160
160
|
fn normalize $.extend({}, common, settings or {})
|
161
161
|
|
162
|
+
class ns.CssCollector
|
163
|
+
constructor: () ->
|
164
|
+
@urls = []
|
165
|
+
@styles = []
|
166
|
+
|
167
|
+
addUrl: (url) ->
|
168
|
+
if not /^https?:\/\//i.test(url)
|
169
|
+
throw new Error('Embedded urls should be absolute. ' + url)
|
170
|
+
|
171
|
+
unless url in @urls
|
172
|
+
@urls.push url
|
173
|
+
|
174
|
+
addStyle: (style) ->
|
175
|
+
@styles.push style
|
176
|
+
|
177
|
+
tabsCss = new ns.CssCollector
|
178
|
+
expose 'tabsCss', tabsCss
|
@@ -0,0 +1 @@
|
|
1
|
+
<canvas>
|
@@ -11,18 +11,20 @@
|
|
11
11
|
<div class="uploadcare-dialog-big-button" role="uploadcare-dialog-browse-file">
|
12
12
|
<%- t('dialog.tabs.file.button') %>
|
13
13
|
</div>
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
var
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
14
|
+
<% if (avalibleTabs.length > 1) { %>
|
15
|
+
<div class="uploadcare-dialog-file-or">
|
16
|
+
<%- t('dialog.tabs.file.also') %>
|
17
|
+
</div>
|
18
|
+
<div class="uploadcare-dialog-file-sources">
|
19
|
+
<% for (var i = 0; i < avalibleTabs.length; i++) {
|
20
|
+
var tab = avalibleTabs[i];
|
21
|
+
if (tab == 'file') continue; %>
|
22
|
+
<div
|
23
|
+
class="uploadcare-dialog-file-source"
|
24
|
+
role="uploadcare-dialog-switch-tab"
|
25
|
+
data-tab="<%- tab %>"
|
26
|
+
><%- t('dialog.tabs.file.tabNames.' + tab) %></div>
|
27
|
+
<% } %>
|
28
|
+
</div>
|
29
|
+
<% } %>
|
28
30
|
</div>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<
|
2
|
-
role="uploadcare-widget-buttons-<%= name %>"
|
3
|
-
class="uploadcare-widget-buttons-<%= name %>"
|
4
|
-
><%- caption %></
|
1
|
+
<div
|
2
|
+
role="uploadcare-widget-buttons-<%= name %>"
|
3
|
+
class="uploadcare-widget-button uploadcare-widget-buttons-<%= name %>"
|
4
|
+
><%- caption %></div>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<div class="uploadcare-widget">
|
2
2
|
<div role="uploadcare-widget-status"></div>
|
3
3
|
<div role="uploadcare-widget-status-text" class="uploadcare-widget-status-text"></div>
|
4
|
-
<
|
4
|
+
<div role="uploadcare-widget-buttons" class="uploadcare-widget-buttons"></div>
|
5
5
|
<div class="uploadcare-widget-dragndrop-area" role="uploadcare-drop-area"><%- t('draghere') %></div>
|
6
6
|
</div>
|
@@ -1,34 +1,21 @@
|
|
1
1
|
{
|
2
2
|
namespace,
|
3
3
|
files,
|
4
|
-
jQuery:
|
4
|
+
jQuery: $,
|
5
|
+
utils: {abilities}
|
5
6
|
} = uploadcare
|
6
7
|
|
7
8
|
{tpl} = uploadcare.templates
|
8
9
|
|
9
10
|
namespace 'uploadcare.ui.progress', (ns) ->
|
10
|
-
class ns.Circle
|
11
|
-
constructor: (@element) ->
|
12
|
-
# should work with other jqueries
|
13
|
-
@element = $(@element)
|
14
|
-
|
15
|
-
@element.html(tpl('circle'))
|
16
|
-
@pie = @element.find('@uploadcare-widget-status')
|
17
|
-
@center = @element.find('@uploadcare-circle-center')
|
18
|
-
@element.addClass 'uploadcare-widget-circle'
|
19
|
-
|
20
|
-
@setColorTheme 'default'
|
21
|
-
|
22
|
-
@size = Math.min(@element.width(), @element.height())
|
23
|
-
@pie.width(@size).height(@size)
|
24
11
|
|
25
|
-
|
26
|
-
@raphael = @__initRaphael()
|
27
|
-
@path = @raphael.path()
|
28
|
-
@path.attr(segment: 0, stroke: false)
|
29
|
-
@fullDelay = 500 # ms
|
30
|
-
@__update(0, true)
|
12
|
+
class ns.Circle
|
31
13
|
|
14
|
+
constructor: (element) ->
|
15
|
+
if abilities.canvas
|
16
|
+
@renderer = new ns.CanvasRenderer element
|
17
|
+
else
|
18
|
+
@renderer = new ns.TextRenderer element
|
32
19
|
@observed = null
|
33
20
|
|
34
21
|
listen: (file, selector = 'uploadProgress') ->
|
@@ -41,24 +28,40 @@ namespace 'uploadcare.ui.progress', (ns) ->
|
|
41
28
|
@observed = file
|
42
29
|
|
43
30
|
if @observed.state() is "resolved"
|
44
|
-
@
|
31
|
+
@renderer.setValue 1, true
|
45
32
|
else
|
46
33
|
@observed
|
47
34
|
.progress (progress) =>
|
48
35
|
# if we are still listening to this one
|
49
36
|
if file == @observed
|
50
|
-
@
|
37
|
+
@renderer.setValue selectorFn(progress)
|
51
38
|
|
52
39
|
.always (uploadedFile) =>
|
53
40
|
if file == @observed
|
54
|
-
@
|
41
|
+
@renderer.setValue 1, false
|
55
42
|
@
|
56
43
|
|
57
|
-
|
58
44
|
reset: (filled = false) ->
|
59
45
|
@observed = null
|
60
|
-
@
|
46
|
+
@renderer.setValue (if filled then 1 else 0), true
|
47
|
+
|
48
|
+
setColorTheme: (theme) ->
|
49
|
+
@renderer.setColorTheme theme
|
50
|
+
|
51
|
+
|
61
52
|
|
53
|
+
|
54
|
+
class ns.BaseRenderer
|
55
|
+
constructor: (el) ->
|
56
|
+
@element = $ el
|
57
|
+
@element.data 'uploadcare-progress-renderer', this
|
58
|
+
@element.addClass 'uploadcare-widget-circle'
|
59
|
+
@size = Math.min(@element.width(), @element.height())
|
60
|
+
setColorTheme: (theme) ->
|
61
|
+
if $.type(theme) is 'string'
|
62
|
+
theme = @colorThemes[theme]
|
63
|
+
@colorTheme = $.extend {}, @colorThemes.default, theme
|
64
|
+
setValue: (value, instant=false) -> throw new Error 'not implemented'
|
62
65
|
colorThemes:
|
63
66
|
default:
|
64
67
|
back: '#e1e5e7'
|
@@ -71,65 +74,112 @@ namespace 'uploadcare.ui.progress', (ns) ->
|
|
71
74
|
back: '#bfbfbf'
|
72
75
|
front: '#8c8c8c'
|
73
76
|
|
77
|
+
|
78
|
+
class ns.TextRenderer extends ns.BaseRenderer
|
79
|
+
constructor: ->
|
80
|
+
super
|
81
|
+
|
82
|
+
$.extend true, @colorThemes, {
|
83
|
+
default:
|
84
|
+
front: '#000'
|
85
|
+
grey:
|
86
|
+
front: '#888'
|
87
|
+
darkGrey:
|
88
|
+
front: '#555'
|
89
|
+
}
|
90
|
+
|
91
|
+
@element.addClass 'uploadcare-widget-circle--text'
|
92
|
+
@element.html(tpl('circle-text'))
|
93
|
+
@background = @element.find('@uploadcare-circle-back')
|
94
|
+
@text = @element.find('@uploadcare-circle-text')
|
95
|
+
@setColorTheme 'default'
|
96
|
+
|
97
|
+
|
74
98
|
setColorTheme: (theme) ->
|
75
|
-
|
76
|
-
|
77
|
-
@
|
78
|
-
|
79
|
-
@pie.css 'background', @colorTheme.back
|
80
|
-
@center.css 'background', @colorTheme.center
|
99
|
+
super
|
100
|
+
@background.css 'background', @colorTheme.back
|
101
|
+
@text.css 'color', @colorTheme.front
|
81
102
|
|
82
|
-
|
83
|
-
|
103
|
+
setValue: (val) ->
|
104
|
+
val = Math.round(val * 100)
|
105
|
+
@text.html "#{val} %"
|
84
106
|
|
85
|
-
__update: (val = @currentVal, instant = false) -> # val in [0..1]
|
86
|
-
val = 1 if val > 1
|
87
|
-
@currentVal = val
|
88
|
-
delay = @fullDelay * Math.abs(val - @value)
|
89
|
-
@value = val
|
90
107
|
|
91
|
-
|
92
|
-
@path.attr(segment: @__segmentVal(@value))
|
93
|
-
else do (value = @value) =>
|
94
|
-
@path.animate {segment: @__segmentVal(value)}, delay, 'linear', =>
|
95
|
-
# Revert value to current if changed during animation
|
96
|
-
@__update(@value, true) if @value != value
|
97
|
-
|
98
|
-
__segmentVal: (value) ->
|
99
|
-
# Supposed to be = 360 * value,
|
100
|
-
# but filling to 360 sometimes doesn't work to IE.
|
101
|
-
# There probably is a correct solution to this.
|
102
|
-
360 * if value < 1 then value else 0.99999999
|
103
|
-
|
104
|
-
__initRaphael: ->
|
105
|
-
raphael = uploadcare.Raphael @pie.get(0), @size, @size
|
106
|
-
size = @size
|
107
|
-
angleOffset = @angleOffset
|
108
|
-
|
109
|
-
getColor = =>
|
110
|
-
@colorTheme.front
|
111
|
-
|
112
|
-
raphael.customAttributes.segment = (angle) ->
|
113
|
-
x = size / 2
|
114
|
-
y = size / 2
|
115
|
-
r = size / 2
|
116
|
-
a1 = 0
|
117
|
-
a2 = angle
|
118
|
-
a1 += angleOffset
|
119
|
-
a2 += angleOffset
|
120
|
-
|
121
|
-
flag = (a2 - a1) > 180
|
122
|
-
a1 = (a1 % 360) * Math.PI / 180
|
123
|
-
a2 -= 0.00001
|
124
|
-
a2 = (a2 % 360) * Math.PI / 180
|
125
|
-
|
126
|
-
{
|
127
|
-
path: [
|
128
|
-
["M", x, y]
|
129
|
-
["l", r * Math.cos(a1), r * Math.sin(a1)]
|
130
|
-
["A", r, r, 0, +flag, 1, x + r * Math.cos(a2), y + r * Math.sin(a2)], ["z"]
|
131
|
-
]
|
132
|
-
fill: getColor()
|
133
|
-
}
|
134
|
-
return raphael
|
108
|
+
class ns.CanvasRenderer extends ns.BaseRenderer
|
135
109
|
|
110
|
+
constructor: ->
|
111
|
+
super
|
112
|
+
|
113
|
+
@canvasSize = @size * 2
|
114
|
+
|
115
|
+
@element.addClass 'uploadcare-widget-circle--canvas'
|
116
|
+
@element.html(tpl('circle-canvas'))
|
117
|
+
|
118
|
+
@setColorTheme 'default'
|
119
|
+
@setValue 0, true
|
120
|
+
|
121
|
+
@canvasEl = @element.find('canvas')
|
122
|
+
.css(width: @size, height: @size)
|
123
|
+
.prop(width: @canvasSize, height: @canvasSize)
|
124
|
+
@canvasCtx = @canvasEl.get(0).getContext '2d'
|
125
|
+
|
126
|
+
@__reRender()
|
127
|
+
|
128
|
+
setColorTheme: (theme) ->
|
129
|
+
super
|
130
|
+
@__reRender()
|
131
|
+
|
132
|
+
__reRender: ->
|
133
|
+
if @canvasCtx
|
134
|
+
ctx = @canvasCtx
|
135
|
+
halfSize = @canvasSize/2
|
136
|
+
|
137
|
+
# Clear
|
138
|
+
ctx.clearRect 0, 0, @canvasSize, @canvasSize
|
139
|
+
|
140
|
+
# Background circle
|
141
|
+
ctx.fillStyle = @colorTheme.back
|
142
|
+
ctx.beginPath()
|
143
|
+
ctx.arc(halfSize, halfSize, halfSize, 0, 2*Math.PI)
|
144
|
+
ctx.fill()
|
145
|
+
|
146
|
+
# Progress circle
|
147
|
+
offset = -Math.PI / 2
|
148
|
+
ctx.fillStyle = @colorTheme.front
|
149
|
+
ctx.beginPath()
|
150
|
+
ctx.moveTo(halfSize, halfSize)
|
151
|
+
ctx.arc(halfSize, halfSize, halfSize, offset, 2*Math.PI * @val + offset)
|
152
|
+
ctx.fill()
|
153
|
+
|
154
|
+
# Center circle
|
155
|
+
ctx.fillStyle = @colorTheme.center
|
156
|
+
ctx.beginPath()
|
157
|
+
ctx.arc(halfSize, halfSize, @canvasSize/15, 0, 2*Math.PI)
|
158
|
+
ctx.fill()
|
159
|
+
|
160
|
+
__animateValue: (targetValue) ->
|
161
|
+
perStep = if targetValue > @val then 0.05 else -0.05
|
162
|
+
@__animIntervalId = setInterval =>
|
163
|
+
newValue = @val + perStep
|
164
|
+
if (perStep > 0 and newValue > targetValue) or (perStep < 0 and newValue < targetValue)
|
165
|
+
newValue = targetValue
|
166
|
+
if newValue == targetValue
|
167
|
+
@__stopAnimation()
|
168
|
+
@__setValue newValue
|
169
|
+
, 25
|
170
|
+
|
171
|
+
__stopAnimation: ->
|
172
|
+
if @__animIntervalId
|
173
|
+
clearInterval @__animIntervalId
|
174
|
+
@__animIntervalId = null
|
175
|
+
|
176
|
+
__setValue: (val) ->
|
177
|
+
@val = val
|
178
|
+
@__reRender()
|
179
|
+
|
180
|
+
setValue: (val, instant = false) ->
|
181
|
+
@__stopAnimation()
|
182
|
+
if instant
|
183
|
+
@__setValue(val)
|
184
|
+
else
|
185
|
+
@__animateValue(val)
|