upjs-rails 0.15.1 → 0.16.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -0
- data/dist/up.js +219 -110
- data/dist/up.min.js +2 -2
- data/lib/assets/javascripts/up/flow.js.coffee +22 -17
- data/lib/assets/javascripts/up/form.js.coffee +1 -1
- data/lib/assets/javascripts/up/modal.js.coffee +19 -14
- data/lib/assets/javascripts/up/motion.js.coffee +31 -2
- data/lib/assets/javascripts/up/popup.js.coffee +31 -20
- data/lib/assets/javascripts/up/proxy.js.coffee +47 -8
- data/lib/assets/javascripts/up/syntax.js.coffee +4 -2
- data/lib/assets/javascripts/up/tooltip.js.coffee +1 -1
- data/lib/assets/javascripts/up/util.js.coffee +27 -31
- data/lib/upjs/rails/version.rb +1 -1
- data/spec_app/Gemfile.lock +4 -1
- data/spec_app/spec/javascripts/up/modal_spec.js.coffee +57 -1
- data/spec_app/spec/javascripts/up/motion_spec.js.coffee +25 -0
- data/spec_app/spec/javascripts/up/popup_spec.js.coffee +77 -6
- data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +21 -1
- metadata +2 -2
@@ -304,13 +304,15 @@ up.syntax = (($) ->
|
|
304
304
|
|
305
305
|
@function up.hello
|
306
306
|
@param {String|Element|jQuery} selectorOrElement
|
307
|
+
@param {String|Element|jQuery} [options.origin]
|
307
308
|
@return {jQuery}
|
308
309
|
The compiled element
|
309
310
|
@stable
|
310
311
|
###
|
311
|
-
hello = (selectorOrElement) ->
|
312
|
+
hello = (selectorOrElement, options) ->
|
312
313
|
$element = $(selectorOrElement)
|
313
|
-
|
314
|
+
eventAttrs = u.options(options, $element: $element)
|
315
|
+
up.emit('up:fragment:inserted', eventAttrs)
|
314
316
|
$element
|
315
317
|
|
316
318
|
###*
|
@@ -149,7 +149,7 @@ up.tooltip = (($) ->
|
|
149
149
|
###*
|
150
150
|
Displays a tooltip with HTML content when hovering the mouse over this element:
|
151
151
|
|
152
|
-
<a href="/decks" up-tooltip="Show <b>all</b> decks">Decks</a>
|
152
|
+
<a href="/decks" up-tooltip-html="Show <b>all</b> decks">Decks</a>
|
153
153
|
|
154
154
|
@selector [up-tooltip-html]
|
155
155
|
@stable
|
@@ -913,37 +913,33 @@ up.util = (($) ->
|
|
913
913
|
###
|
914
914
|
cssAnimate = (elementOrSelector, lastFrame, opts) ->
|
915
915
|
$element = $(elementOrSelector)
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
transition
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
else
|
944
|
-
$element.css(lastFrame)
|
945
|
-
resolvedDeferred()
|
946
|
-
|
916
|
+
opts = options(opts,
|
917
|
+
duration: 300,
|
918
|
+
delay: 0,
|
919
|
+
easing: 'ease'
|
920
|
+
)
|
921
|
+
# We don't finish an existing animation here, since
|
922
|
+
# the public API `up.motion.animate` already does this.
|
923
|
+
deferred = $.Deferred()
|
924
|
+
transition =
|
925
|
+
'transition-property': Object.keys(lastFrame).join(', ')
|
926
|
+
'transition-duration': "#{opts.duration}ms"
|
927
|
+
'transition-delay': "#{opts.delay}ms"
|
928
|
+
'transition-timing-function': opts.easing
|
929
|
+
withoutCompositing = forceCompositing($element)
|
930
|
+
withoutTransition = temporaryCss($element, transition)
|
931
|
+
$element.css(lastFrame)
|
932
|
+
deferred.then(withoutCompositing)
|
933
|
+
deferred.then(withoutTransition)
|
934
|
+
$element.data(ANIMATION_PROMISE_KEY, deferred)
|
935
|
+
deferred.then(-> $element.removeData(ANIMATION_PROMISE_KEY))
|
936
|
+
endTimeout = setTimeout((-> deferred.resolve()), opts.duration + opts.delay)
|
937
|
+
deferred.then(-> clearTimeout(endTimeout)) # clean up in case we're canceled
|
938
|
+
# Return the whole deferred and not just return a thenable.
|
939
|
+
# Other code will need the possibility to cancel the animation
|
940
|
+
# by resolving the deferred.
|
941
|
+
deferred
|
942
|
+
|
947
943
|
ANIMATION_PROMISE_KEY = 'up-animation-promise'
|
948
944
|
|
949
945
|
###*
|
data/lib/upjs/rails/version.rb
CHANGED
data/spec_app/Gemfile.lock
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
describe 'up.modal', ->
|
2
|
+
|
3
|
+
u = up.util
|
2
4
|
|
3
5
|
describe 'Javascript functions', ->
|
4
6
|
|
@@ -64,6 +66,12 @@ describe 'up.modal', ->
|
|
64
66
|
expect(parseInt($anchoredElement.css('right'))).toBeAround(30 , 10)
|
65
67
|
done()
|
66
68
|
|
69
|
+
it 'does not explode if the modal was closed before the response was received', ->
|
70
|
+
up.modal.visit('/foo', target: '.container')
|
71
|
+
up.modal.close()
|
72
|
+
respond = => @respondWith('<div class="container">text</div>')
|
73
|
+
expect(respond).not.toThrowError()
|
74
|
+
expect($('.up-error')).not.toExist()
|
67
75
|
|
68
76
|
describe 'up.modal.coveredUrl', ->
|
69
77
|
|
@@ -134,16 +142,64 @@ describe 'up.modal', ->
|
|
134
142
|
expect(wasClosed).toBe(false)
|
135
143
|
expect(wasDefaultPrevented).toBe(false)
|
136
144
|
|
137
|
-
describe 'when
|
145
|
+
describe 'when replacing content', ->
|
146
|
+
|
147
|
+
beforeEach ->
|
148
|
+
up.motion.config.enabled = false
|
138
149
|
|
139
150
|
it 'prefers to replace a selector within the modal', ->
|
140
151
|
$outside = affix('.foo').text('old outside')
|
141
152
|
up.modal.visit('/path', target: '.foo')
|
142
153
|
@respondWith("<div class='foo'>old inside</div>")
|
143
154
|
up.flow.implant('.foo', "<div class='foo'>new text</div>")
|
155
|
+
expect($outside).toBeInDOM()
|
144
156
|
expect($outside).toHaveText('old outside')
|
145
157
|
expect($('.up-modal-content')).toHaveText('new text')
|
146
158
|
|
159
|
+
it 'auto-closes the modal when a replacement from inside the modal affects a selector behind the modal', ->
|
160
|
+
affix('.outside').text('old outside')
|
161
|
+
up.modal.visit('/path', target: '.inside')
|
162
|
+
@respondWith("<div class='inside'>old inside</div>")
|
163
|
+
up.flow.implant('.outside', "<div class='outside'>new outside</div>", origin: $('.inside'))
|
164
|
+
expect($('.outside')).toHaveText('new outside')
|
165
|
+
expect($('.up-modal')).not.toExist()
|
166
|
+
|
167
|
+
it 'does not auto-close the modal when a replacement from inside the modal affects a selector inside the modal', ->
|
168
|
+
affix('.outside').text('old outside')
|
169
|
+
up.modal.visit('/path', target: '.inside')
|
170
|
+
@respondWith("<div class='inside'>old inside</div>")
|
171
|
+
up.flow.implant('.inside', "<div class='inside'>new inside</div>", origin: $('.inside'))
|
172
|
+
expect($('.inside')).toHaveText('new inside')
|
173
|
+
expect($('.up-modal')).toExist()
|
174
|
+
|
175
|
+
it 'does not auto-close the modal when a replacement from outside the modal affects a selector outside the modal', ->
|
176
|
+
affix('.outside').text('old outside')
|
177
|
+
up.modal.visit('/path', target: '.inside')
|
178
|
+
@respondWith("<div class='inside'>old inside</div>")
|
179
|
+
up.flow.implant('.outside', "<div class='outside'>new outside</div>", origin: $('.outside'))
|
180
|
+
expect($('.outside')).toHaveText('new outside')
|
181
|
+
expect($('.up-modal')).toExist()
|
182
|
+
|
183
|
+
it 'does not auto-close the modal when a replacement from outside the modal affects a selector inside the modal', ->
|
184
|
+
affix('.outside').text('old outside')
|
185
|
+
up.modal.visit('/path', target: '.inside')
|
186
|
+
@respondWith("<div class='inside'>old inside</div>")
|
187
|
+
up.flow.implant('.inside', "<div class='inside'>new inside</div>", origin: $('.outside'))
|
188
|
+
expect($('.inside')).toHaveText('new inside')
|
189
|
+
expect($('.up-modal')).toExist()
|
190
|
+
|
191
|
+
it 'does not auto-close the modal when the new fragment is within a popup', ->
|
192
|
+
up.modal.visit('/modal', target: '.modal-content')
|
193
|
+
@respondWith("<div class='modal-content'></div>")
|
194
|
+
up.popup.attach('.modal-content', url: '/popup', target: '.popup-content')
|
195
|
+
@respondWith("<div class='popup-content'></div>")
|
196
|
+
expect($('.up-modal')).toExist()
|
197
|
+
expect($('.up-popup')).toExist()
|
198
|
+
|
199
|
+
describe 'when following links inside a modal', ->
|
200
|
+
|
201
|
+
it 'prefers to replace a selector within the modal', ->
|
202
|
+
|
147
203
|
it 'auto-closes the modal if a selector behind the modal gets replaced'
|
148
204
|
|
149
205
|
it "doesn't auto-close the modal if a selector behind the modal if the modal is sticky"
|
@@ -25,6 +25,16 @@ describe 'up.motion', ->
|
|
25
25
|
up.animate($element, { 'fade-in' }, duration: 100, easing: 'linear')
|
26
26
|
expect($element.css('font-size')).toEqual('40px')
|
27
27
|
|
28
|
+
describe 'with animations disabled globally', ->
|
29
|
+
|
30
|
+
beforeEach ->
|
31
|
+
up.motion.config.enabled = false
|
32
|
+
|
33
|
+
it "doesn't animate and directly sets the last frame instead", ->
|
34
|
+
$element = affix('.element').text('content')
|
35
|
+
up.animate($element, { 'font-size': '40px' }, duration: 10000, easing: 'linear')
|
36
|
+
expect($element.css('font-size')).toEqual('40px')
|
37
|
+
|
28
38
|
else
|
29
39
|
|
30
40
|
it "doesn't animate and directly sets the last frame instead", ->
|
@@ -185,6 +195,20 @@ describe 'up.motion', ->
|
|
185
195
|
# was at the scroll position before we revealed $new.
|
186
196
|
expect($oldGhost.offset().top).toEqual(-300)
|
187
197
|
|
198
|
+
|
199
|
+
describe 'with animations disabled globally', ->
|
200
|
+
|
201
|
+
beforeEach ->
|
202
|
+
up.motion.config.enabled = false
|
203
|
+
|
204
|
+
it "doesn't animate and hides the old element instead", ->
|
205
|
+
$old = affix('.old').text('old content')
|
206
|
+
$new = affix('.new').text('new content')
|
207
|
+
up.morph($old, $new, 'cross-fade', duration: 1000)
|
208
|
+
expect($old).toBeHidden()
|
209
|
+
expect($new).toBeVisible()
|
210
|
+
expect($new.css('opacity')).toEqual('1')
|
211
|
+
|
188
212
|
else
|
189
213
|
|
190
214
|
it "doesn't animate and hides the old element instead", ->
|
@@ -193,6 +217,7 @@ describe 'up.motion', ->
|
|
193
217
|
up.morph($old, $new, 'cross-fade', duration: 1000)
|
194
218
|
expect($old).toBeHidden()
|
195
219
|
expect($new).toBeVisible()
|
220
|
+
expect($new.css('opacity')).toEqual('1')
|
196
221
|
|
197
222
|
describe 'up.transition', ->
|
198
223
|
|
@@ -1,10 +1,18 @@
|
|
1
1
|
describe 'up.popup', ->
|
2
2
|
|
3
|
+
u = up.util
|
4
|
+
|
3
5
|
describe 'Javascript functions', ->
|
4
6
|
|
5
7
|
describe 'up.popup.attach', ->
|
6
8
|
|
7
|
-
it '
|
9
|
+
it 'does not explode if the popup was closed before the response was received', ->
|
10
|
+
$span = affix('span')
|
11
|
+
up.popup.attach($span, url: '/foo', target: '.container')
|
12
|
+
up.popup.close()
|
13
|
+
respond = => @respondWith('<div class="container">text</div>')
|
14
|
+
expect(respond).not.toThrowError()
|
15
|
+
expect($('.up-error')).not.toExist()
|
8
16
|
|
9
17
|
describe 'up.popup.coveredUrl', ->
|
10
18
|
|
@@ -34,6 +42,10 @@ describe 'up.popup', ->
|
|
34
42
|
|
35
43
|
it "loads this link's destination in a popup when clicked", ->
|
36
44
|
$link = affix('a[href="/path/to"][up-popup=".middle"]').text('link')
|
45
|
+
$link.css
|
46
|
+
position: 'fixed'
|
47
|
+
left: '100px'
|
48
|
+
top: '50px'
|
37
49
|
$link.click()
|
38
50
|
expect(@lastRequest().url).toMatch /\/path\/to$/
|
39
51
|
@respondWith """
|
@@ -41,10 +53,19 @@ describe 'up.popup', ->
|
|
41
53
|
<div class="middle">new-middle</div>
|
42
54
|
<div class="after">new-after</div>
|
43
55
|
"""
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
expect($
|
56
|
+
|
57
|
+
$popup = $('.up-popup')
|
58
|
+
|
59
|
+
expect($popup).toExist()
|
60
|
+
expect($popup.find('.middle')).toHaveText('new-middle')
|
61
|
+
expect($popup.find('.before')).not.toExist()
|
62
|
+
expect($popup.find('.after')).not.toExist()
|
63
|
+
|
64
|
+
popupDims = u.measure($popup, full: true)
|
65
|
+
linkDims = u.measure($link, full: true)
|
66
|
+
|
67
|
+
expect(popupDims.right).toBeAround(linkDims.right, 1)
|
68
|
+
expect(popupDims.top).toBeAround(linkDims.top + linkDims.height, 1)
|
48
69
|
|
49
70
|
describe '[up-close]', ->
|
50
71
|
|
@@ -80,4 +101,54 @@ describe 'up.popup', ->
|
|
80
101
|
$link.click()
|
81
102
|
expect(wasClosed).toBe(false)
|
82
103
|
expect(wasDefaultPrevented).toBe(false)
|
83
|
-
|
104
|
+
|
105
|
+
describe 'when replacing content', ->
|
106
|
+
|
107
|
+
beforeEach ->
|
108
|
+
up.motion.config.enabled = false
|
109
|
+
|
110
|
+
it 'prefers to replace a selector within the popup', ->
|
111
|
+
$outside = affix('.foo').text('old outside')
|
112
|
+
$link = affix('.link')
|
113
|
+
up.popup.attach($link, href: '/path', target: '.foo')
|
114
|
+
@respondWith("<div class='foo'>old inside</div>")
|
115
|
+
up.flow.implant('.foo', "<div class='foo'>new text</div>")
|
116
|
+
expect($outside).toBeInDOM()
|
117
|
+
expect($outside).toHaveText('old outside')
|
118
|
+
expect($('.up-popup')).toHaveText('new text')
|
119
|
+
|
120
|
+
it 'auto-closes the popup when a replacement from inside the popup affects a selector behind the popup', ->
|
121
|
+
affix('.outside').text('old outside')
|
122
|
+
$link = affix('.link')
|
123
|
+
up.popup.attach($link, href: '/path', target: '.inside')
|
124
|
+
@respondWith("<div class='inside'>old inside</div>")
|
125
|
+
up.flow.implant('.outside', "<div class='outside'>new outside</div>", origin: $('.inside'))
|
126
|
+
expect($('.outside')).toHaveText('new outside')
|
127
|
+
expect($('.up-popup')).not.toExist()
|
128
|
+
|
129
|
+
it 'does not auto-close the popup when a replacement from inside the popup affects a selector inside the popup', ->
|
130
|
+
affix('.outside').text('old outside')
|
131
|
+
$link = affix('.link')
|
132
|
+
up.popup.attach($link, href: '/path', target: '.inside')
|
133
|
+
@respondWith("<div class='inside'>old inside</div>")
|
134
|
+
up.flow.implant('.inside', "<div class='inside'>new inside</div>", origin: $('.inside'))
|
135
|
+
expect($('.inside')).toHaveText('new inside')
|
136
|
+
expect($('.up-popup')).toExist()
|
137
|
+
|
138
|
+
it 'does not auto-close the popup when a replacement from outside the popup affects a selector outside the popup', ->
|
139
|
+
affix('.outside').text('old outside')
|
140
|
+
$link = affix('.link')
|
141
|
+
up.popup.attach($link, href: '/path', target: '.inside')
|
142
|
+
@respondWith("<div class='inside'>old inside</div>")
|
143
|
+
up.flow.implant('.outside', "<div class='outside'>new outside</div>", origin: $('.outside'))
|
144
|
+
expect($('.outside')).toHaveText('new outside')
|
145
|
+
expect($('.up-popup')).toExist()
|
146
|
+
|
147
|
+
it 'does not auto-close the popup when a replacement from outside the popup affects a selector inside the popup', ->
|
148
|
+
affix('.outside').text('old outside')
|
149
|
+
$link = affix('.link')
|
150
|
+
up.popup.attach($link, href: '/path', target: '.inside')
|
151
|
+
@respondWith("<div class='inside'>old inside</div>")
|
152
|
+
up.flow.implant('.inside', "<div class='inside'>new inside</div>", origin: $('.outside'))
|
153
|
+
expect($('.inside')).toHaveText('new inside')
|
154
|
+
expect($('.up-popup')).toExist()
|
@@ -88,7 +88,7 @@ describe 'up.proxy', ->
|
|
88
88
|
u.times 2, -> up.proxy.ajax(url: '/foo', method: method, cache: true)
|
89
89
|
expect(jasmine.Ajax.requests.count()).toEqual(1)
|
90
90
|
|
91
|
-
it 'does not responses with a non-200 status code', ->
|
91
|
+
it 'does not cache responses with a non-200 status code', ->
|
92
92
|
# Send the same request for the same path, 3 minutes apart
|
93
93
|
up.proxy.ajax(url: '/foo')
|
94
94
|
|
@@ -101,6 +101,26 @@ describe 'up.proxy', ->
|
|
101
101
|
|
102
102
|
expect(jasmine.Ajax.requests.count()).toEqual(2)
|
103
103
|
|
104
|
+
describe 'with config.maxRequests set', ->
|
105
|
+
|
106
|
+
beforeEach ->
|
107
|
+
up.proxy.config.maxRequests = 1
|
108
|
+
|
109
|
+
it 'limits the number of concurrent requests', ->
|
110
|
+
responses = []
|
111
|
+
up.proxy.ajax(url: '/foo').then (html) -> responses.push(html)
|
112
|
+
up.proxy.ajax(url: '/bar').then (html) -> responses.push(html)
|
113
|
+
expect(jasmine.Ajax.requests.count()).toEqual(1) # only one request was made
|
114
|
+
@respondWith('first response', request: jasmine.Ajax.requests.at(0))
|
115
|
+
expect(responses).toEqual ['first response']
|
116
|
+
expect(jasmine.Ajax.requests.count()).toEqual(2) # a second request was made
|
117
|
+
@respondWith('second response', request: jasmine.Ajax.requests.at(1))
|
118
|
+
expect(responses).toEqual ['first response', 'second response']
|
119
|
+
|
120
|
+
# it 'considers preloading links for the request limit', ->
|
121
|
+
# up.proxy.ajax(url: '/foo', preload: true)
|
122
|
+
# up.proxy.ajax(url: '/bar')
|
123
|
+
# expect(jasmine.Ajax.requests.count()).toEqual(1)
|
104
124
|
|
105
125
|
describe 'events', ->
|
106
126
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: upjs-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henning Koch
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-01-
|
11
|
+
date: 2016-01-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|