unpoly-rails 0.34.2 → 0.35.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.
Potentially problematic release.
This version of unpoly-rails might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -2
- data/lib/assets/javascripts/unpoly/browser.coffee +41 -48
- data/lib/assets/javascripts/unpoly/bus.coffee +2 -1
- data/lib/assets/javascripts/unpoly/dom.coffee +2 -1
- data/lib/assets/javascripts/unpoly/form.coffee +4 -18
- data/lib/assets/javascripts/unpoly/motion.coffee +2 -4
- data/lib/assets/javascripts/unpoly/protocol.coffee +15 -8
- data/lib/assets/javascripts/unpoly/util.coffee +21 -40
- data/lib/unpoly/rails/version.rb +1 -1
- data/spec_app/Gemfile.lock +1 -1
- data/spec_app/spec/javascripts/helpers/to_have_request_method.js.coffee +9 -1
- data/spec_app/spec/javascripts/up/dom_spec.js.coffee +109 -92
- data/spec_app/spec/javascripts/up/form_spec.js.coffee +7 -23
- data/spec_app/spec/javascripts/up/link_spec.js.coffee +16 -18
- data/spec_app/spec/javascripts/up/modal_spec.js.coffee +42 -46
- data/spec_app/spec/javascripts/up/motion_spec.js.coffee +249 -295
- data/spec_app/spec/javascripts/up/popup_spec.js.coffee +27 -29
- data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +3 -5
- data/spec_app/spec/javascripts/up/util_spec.js.coffee +1 -0
- metadata +2 -2
@@ -6,353 +6,319 @@ describe 'up.motion', ->
|
|
6
6
|
|
7
7
|
describe 'up.animate', ->
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
9
|
+
it 'animates the given element', (done) ->
|
10
|
+
$element = affix('.element').text('content')
|
11
|
+
up.animate($element, 'fade-in', duration: 200, easing: 'linear')
|
12
|
+
|
13
|
+
u.setTimer 0, ->
|
14
|
+
expect(u.opacity($element)).toBeAround(0.0, 0.25)
|
15
|
+
u.setTimer 100, ->
|
16
|
+
expect(u.opacity($element)).toBeAround(0.5, 0.25)
|
17
|
+
u.setTimer 200, ->
|
18
|
+
expect(u.opacity($element)).toBeAround(1.0, 0.25)
|
19
|
+
done()
|
20
|
+
|
21
|
+
it 'returns a promise that is resolved when the animation completed', (done) ->
|
22
|
+
$element = affix('.element').text('content')
|
23
|
+
resolveSpy = jasmine.createSpy('resolve')
|
24
|
+
|
25
|
+
promise = up.animate($element, 'fade-in', duration: 100, easing: 'linear')
|
26
|
+
promise.then(resolveSpy)
|
27
|
+
|
28
|
+
u.setTimer 50, ->
|
29
|
+
expect(resolveSpy).not.toHaveBeenCalled()
|
17
30
|
u.setTimer 100, ->
|
18
|
-
expect(
|
19
|
-
u.setTimer 200, ->
|
20
|
-
expect(u.opacity($element)).toBeAround(1.0, 0.25)
|
31
|
+
expect(resolveSpy).toHaveBeenCalled()
|
21
32
|
done()
|
22
33
|
|
23
|
-
|
24
|
-
|
25
|
-
|
34
|
+
it 'cancels an existing animation on the element by instantly jumping to the last frame', ->
|
35
|
+
$element = affix('.element').text('content')
|
36
|
+
up.animate($element, { 'font-size': '40px' }, duration: 10000, easing: 'linear')
|
37
|
+
up.animate($element, { 'fade-in' }, duration: 100, easing: 'linear')
|
38
|
+
expect($element.css('font-size')).toEqual('40px')
|
26
39
|
|
27
|
-
|
28
|
-
promise.then(resolveSpy)
|
40
|
+
describe 'with animations disabled globally', ->
|
29
41
|
|
30
|
-
|
31
|
-
|
32
|
-
u.setTimer 100, ->
|
33
|
-
expect(resolveSpy).toHaveBeenCalled()
|
34
|
-
done()
|
42
|
+
beforeEach ->
|
43
|
+
up.motion.config.enabled = false
|
35
44
|
|
36
|
-
it '
|
45
|
+
it "doesn't animate and directly sets the last frame instead", (done) ->
|
37
46
|
$element = affix('.element').text('content')
|
38
|
-
|
39
|
-
up.animate($element, { '
|
47
|
+
callback = jasmine.createSpy('animation done callback')
|
48
|
+
animateDone = up.animate($element, { 'font-size': '40px' }, duration: 10000, easing: 'linear')
|
49
|
+
animateDone.then(callback)
|
40
50
|
expect($element.css('font-size')).toEqual('40px')
|
51
|
+
u.nextFrame ->
|
52
|
+
expect(callback).toHaveBeenCalled()
|
53
|
+
done()
|
41
54
|
|
42
|
-
|
55
|
+
[false, null, undefined, 'none', up.motion.none()].forEach (noneAnimation) ->
|
43
56
|
|
44
|
-
|
45
|
-
up.motion.config.enabled = false
|
57
|
+
describe "when called with a `#{noneAnimation}` animation", ->
|
46
58
|
|
47
|
-
it "doesn't animate and
|
59
|
+
it "doesn't animate and resolves instantly", (done) ->
|
48
60
|
$element = affix('.element').text('content')
|
49
61
|
callback = jasmine.createSpy('animation done callback')
|
50
|
-
animateDone = up.animate($element,
|
62
|
+
animateDone = up.animate($element, noneAnimation, duration: 10000, easing: 'linear')
|
51
63
|
animateDone.then(callback)
|
52
|
-
expect($element.css('font-size')).toEqual('40px')
|
53
64
|
u.nextFrame ->
|
54
65
|
expect(callback).toHaveBeenCalled()
|
55
66
|
done()
|
56
67
|
|
57
|
-
[false, null, undefined, 'none', up.motion.none()].forEach (noneAnimation) ->
|
58
|
-
|
59
|
-
describe "when called with a `#{noneAnimation}` animation", ->
|
60
|
-
|
61
|
-
it "doesn't animate and resolves instantly", (done) ->
|
62
|
-
$element = affix('.element').text('content')
|
63
|
-
callback = jasmine.createSpy('animation done callback')
|
64
|
-
animateDone = up.animate($element, noneAnimation, duration: 10000, easing: 'linear')
|
65
|
-
animateDone.then(callback)
|
66
|
-
u.nextFrame ->
|
67
|
-
expect(callback).toHaveBeenCalled()
|
68
|
-
done()
|
69
|
-
|
70
|
-
describeFallback 'canCssTransition', ->
|
71
|
-
|
72
|
-
it "doesn't animate and directly sets the last frame instead", ->
|
73
|
-
$element = affix('.element').text('content')
|
74
|
-
up.animate($element, { 'font-size': '40px' }, duration: 10000, easing: 'linear')
|
75
|
-
expect($element.css('font-size')).toEqual('40px')
|
76
|
-
|
77
68
|
describe 'up.motion.finish', ->
|
78
69
|
|
79
70
|
describe 'when called with an element or selector', ->
|
80
71
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
expect(currentTransitionProperty).toContain('font-size')
|
118
|
-
expect(currentTransitionProperty).not.toContain('opacity')
|
119
|
-
|
120
|
-
it 'cancels an existing transition on the element by instantly jumping to the last frame', ->
|
121
|
-
$old = affix('.old').text('old content')
|
122
|
-
$new = affix('.new').text('new content')
|
123
|
-
|
124
|
-
up.morph($old, $new, 'cross-fade', duration: 2000)
|
125
|
-
expect($('.up-ghost').length).toBe(2)
|
72
|
+
it 'cancels an existing animation on the given element by instantly jumping to the last frame', ->
|
73
|
+
$element = affix('.element').text('content')
|
74
|
+
up.animate($element, { 'font-size': '40px', 'opacity': '0.33' }, duration: 10000)
|
75
|
+
up.motion.finish($element)
|
76
|
+
expect($element.css('font-size')).toEqual('40px')
|
77
|
+
expect($element.css('opacity')).toEqual('0.33')
|
78
|
+
|
79
|
+
it 'cancels animations on children of the given element', ->
|
80
|
+
$parent = affix('.element')
|
81
|
+
$child = $parent.affix('.child')
|
82
|
+
up.animate($child, { 'font-size': '40px' }, duration: 10000)
|
83
|
+
up.motion.finish($parent)
|
84
|
+
expect($child.css('font-size')).toEqual('40px')
|
85
|
+
|
86
|
+
it 'does not cancel animations on other elements', ->
|
87
|
+
$element1 = affix('.element1').text('content1')
|
88
|
+
$element2 = affix('.element2').text('content2')
|
89
|
+
up.animate($element1, 'fade-in', duration: 10000)
|
90
|
+
up.animate($element2, 'fade-in', duration: 10000)
|
91
|
+
up.motion.finish($element1)
|
92
|
+
expect(Number($element1.css('opacity'))).toEqual(1)
|
93
|
+
expect(Number($element2.css('opacity'))).toEqual(0, 0.1)
|
94
|
+
|
95
|
+
it 'restores existing transitions on the element', ->
|
96
|
+
$element = affix('.element').text('content')
|
97
|
+
$element.css('transition': 'font-size 3s ease')
|
98
|
+
oldTransitionProperty = $element.css('transition-property')
|
99
|
+
expect(oldTransitionProperty).toBeDefined()
|
100
|
+
expect(oldTransitionProperty).toContain('font-size') # be paranoid
|
101
|
+
up.animate($element, 'fade-in', duration: 10000)
|
102
|
+
up.motion.finish($element)
|
103
|
+
expect(u.opacity($element)).toEqual(1)
|
104
|
+
currentTransitionProperty = $element.css('transition-property')
|
105
|
+
expect(currentTransitionProperty).toEqual(oldTransitionProperty)
|
106
|
+
expect(currentTransitionProperty).toContain('font-size')
|
107
|
+
expect(currentTransitionProperty).not.toContain('opacity')
|
126
108
|
|
127
|
-
|
109
|
+
it 'cancels an existing transition on the element by instantly jumping to the last frame', ->
|
110
|
+
$old = affix('.old').text('old content')
|
111
|
+
$new = affix('.new').text('new content')
|
128
112
|
|
129
|
-
|
130
|
-
|
131
|
-
expect($new.css('display')).toEqual('block')
|
113
|
+
up.morph($old, $new, 'cross-fade', duration: 2000)
|
114
|
+
expect($('.up-ghost').length).toBe(2)
|
132
115
|
|
133
|
-
|
134
|
-
$old = affix('.old').text('old content')
|
135
|
-
$new = affix('.new').text('new content')
|
116
|
+
up.motion.finish($old)
|
136
117
|
|
137
|
-
|
138
|
-
|
118
|
+
expect($('.up-ghost').length).toBe(0)
|
119
|
+
expect($old.css('display')).toEqual('none')
|
120
|
+
expect($new.css('display')).toEqual('block')
|
139
121
|
|
140
|
-
|
122
|
+
it 'can be called on either element involved in a transition', ->
|
123
|
+
$old = affix('.old').text('old content')
|
124
|
+
$new = affix('.new').text('new content')
|
141
125
|
|
142
|
-
|
143
|
-
|
144
|
-
expect($new.css('display')).toEqual('block')
|
126
|
+
up.morph($old, $new, 'cross-fade', duration: 2000)
|
127
|
+
expect($('.up-ghost').length).toBe(2)
|
145
128
|
|
129
|
+
up.motion.finish($new)
|
146
130
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
$new = $parent.affix('.new').text('new content')
|
131
|
+
expect($('.up-ghost').length).toBe(0)
|
132
|
+
expect($old.css('display')).toEqual('none')
|
133
|
+
expect($new.css('display')).toEqual('block')
|
151
134
|
|
152
|
-
up.morph($old, $new, 'cross-fade', duration: 2000)
|
153
|
-
expect($('.up-ghost').length).toBe(2)
|
154
135
|
|
155
|
-
|
136
|
+
it 'cancels transitions on children of the given element', ->
|
137
|
+
$parent = affix('.parent')
|
138
|
+
$old = $parent.affix('.old').text('old content')
|
139
|
+
$new = $parent.affix('.new').text('new content')
|
156
140
|
|
157
|
-
|
158
|
-
|
159
|
-
expect($new.css('display')).toEqual('block')
|
141
|
+
up.morph($old, $new, 'cross-fade', duration: 2000)
|
142
|
+
expect($('.up-ghost').length).toBe(2)
|
160
143
|
|
161
|
-
|
144
|
+
up.motion.finish($parent)
|
162
145
|
|
163
|
-
|
146
|
+
expect($('.up-ghost').length).toBe(0)
|
147
|
+
expect($old.css('display')).toEqual('none')
|
148
|
+
expect($new.css('display')).toEqual('block')
|
164
149
|
|
165
150
|
describe 'when called without arguments', ->
|
166
151
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
$element1 = affix('.element1').text('content1')
|
171
|
-
$element2 = affix('.element2').text('content2')
|
172
|
-
|
173
|
-
up.animate($element1, 'fade-in', duration: 3000)
|
174
|
-
up.animate($element2, 'fade-in', duration: 3000)
|
175
|
-
|
176
|
-
expect(u.opacity($element1)).toBeAround(0.0, 0.1)
|
177
|
-
expect(u.opacity($element2)).toBeAround(0.0, 0.1)
|
152
|
+
it 'cancels all animations on the screen', ->
|
153
|
+
$element1 = affix('.element1').text('content1')
|
154
|
+
$element2 = affix('.element2').text('content2')
|
178
155
|
|
179
|
-
|
156
|
+
up.animate($element1, 'fade-in', duration: 3000)
|
157
|
+
up.animate($element2, 'fade-in', duration: 3000)
|
180
158
|
|
181
|
-
|
182
|
-
|
183
|
-
expect(u.opacity($element1)).toBe(1.0)
|
184
|
-
expect(u.opacity($element2)).toBe(1.0)
|
159
|
+
expect(u.opacity($element1)).toBeAround(0.0, 0.1)
|
160
|
+
expect(u.opacity($element2)).toBeAround(0.0, 0.1)
|
185
161
|
|
186
|
-
|
187
|
-
|
188
|
-
it 'does nothing'
|
162
|
+
up.motion.finish()
|
189
163
|
|
164
|
+
$element1 = $('.element1')
|
165
|
+
$element2 = $('.element2')
|
166
|
+
expect(u.opacity($element1)).toBe(1.0)
|
167
|
+
expect(u.opacity($element2)).toBe(1.0)
|
190
168
|
|
191
169
|
describe 'up.morph', ->
|
192
170
|
|
193
|
-
|
194
|
-
|
195
|
-
it 'transitions between two element by animating two copies while keeping the originals in the background', (done) ->
|
196
|
-
|
197
|
-
$old = affix('.old').text('old content').css(
|
198
|
-
position: 'absolute'
|
199
|
-
top: '10px'
|
200
|
-
left: '11px',
|
201
|
-
width: '12px',
|
202
|
-
height: '13px'
|
203
|
-
)
|
204
|
-
$new = affix('.new').text('new content').css(
|
205
|
-
position: 'absolute'
|
206
|
-
top: '20px'
|
207
|
-
left: '21px',
|
208
|
-
width: '22px',
|
209
|
-
height: '23px'
|
210
|
-
)
|
211
|
-
up.morph($old, $new, 'cross-fade', duration: 200, easing: 'linear')
|
171
|
+
it 'transitions between two element by animating two copies while keeping the originals in the background', (done) ->
|
212
172
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
173
|
+
$old = affix('.old').text('old content').css(
|
174
|
+
position: 'absolute'
|
175
|
+
top: '10px'
|
176
|
+
left: '11px',
|
177
|
+
width: '12px',
|
178
|
+
height: '13px'
|
179
|
+
)
|
180
|
+
$new = affix('.new').text('new content').css(
|
181
|
+
position: 'absolute'
|
182
|
+
top: '20px'
|
183
|
+
left: '21px',
|
184
|
+
width: '22px',
|
185
|
+
height: '23px'
|
186
|
+
)
|
187
|
+
up.morph($old, $new, 'cross-fade', duration: 200, easing: 'linear')
|
188
|
+
|
189
|
+
# The actual animation will be performed on Ghosts since
|
190
|
+
# two element usually cannot exist in the DOM at the same time
|
191
|
+
# without undesired visual effects
|
192
|
+
$oldGhost = $('.old.up-ghost')
|
193
|
+
$newGhost = $('.new.up-ghost')
|
194
|
+
expect($oldGhost).toExist()
|
195
|
+
expect($newGhost).toExist()
|
196
|
+
|
197
|
+
$oldBounds = $oldGhost.parent('.up-bounds')
|
198
|
+
$newBounds = $newGhost.parent('.up-bounds')
|
199
|
+
expect($oldBounds).toExist()
|
200
|
+
expect($newBounds).toExist()
|
201
|
+
|
202
|
+
# Ghosts should be inserted before (not after) the element
|
203
|
+
# or the browser scroll position will be too low after the
|
204
|
+
# transition ends.
|
205
|
+
expect($oldGhost.parent().next()).toEqual($old)
|
206
|
+
expect($newGhost.parent().next()).toEqual($new)
|
207
|
+
|
208
|
+
# The old element is removed from the layout flow.
|
209
|
+
# It will be removed from the DOM after the animation has ended.
|
210
|
+
expect($old.css('display')).toEqual('none')
|
211
|
+
|
212
|
+
# The new element is invisible due to an opacity of zero,
|
213
|
+
# but takes up the space in the layout flow.
|
214
|
+
expect($new.css(['display', 'opacity'])).toEqual(
|
215
|
+
display: 'block',
|
216
|
+
opacity: '0'
|
217
|
+
)
|
218
|
+
|
219
|
+
# We **must not** use `visibility: hidden` to hide the new
|
220
|
+
# element. This would delay browser painting until the element is
|
221
|
+
# shown again, causing a flicker while the browser is painting.
|
222
|
+
expect($new.css('visibility')).not.toEqual('hidden')
|
223
|
+
|
224
|
+
# Ghosts will hover over $old and $new using absolute positioning,
|
225
|
+
# matching the coordinates of the original elements.
|
226
|
+
expect($oldBounds.css(['position', 'top', 'left', 'width', 'height'])).toEqual(
|
227
|
+
position: 'absolute'
|
228
|
+
top: '10px'
|
229
|
+
left: '11px',
|
230
|
+
width: '12px',
|
231
|
+
height: '13px'
|
232
|
+
)
|
233
|
+
expect($newBounds.css(['position', 'top', 'left', 'width', 'height'])).toEqual(
|
234
|
+
position: 'absolute'
|
235
|
+
top: '20px'
|
236
|
+
left: '21px',
|
237
|
+
width: '22px',
|
238
|
+
height: '23px'
|
239
|
+
)
|
240
|
+
|
241
|
+
u.setTimer 0, ->
|
242
|
+
expect(u.opacity($newGhost)).toBeAround(0.0, 0.25)
|
243
|
+
expect(u.opacity($oldGhost)).toBeAround(1.0, 0.25)
|
244
|
+
|
245
|
+
u.setTimer 80, ->
|
246
|
+
expect(u.opacity($newGhost)).toBeAround(0.4, 0.25)
|
247
|
+
expect(u.opacity($oldGhost)).toBeAround(0.6, 0.25)
|
248
|
+
|
249
|
+
u.setTimer 140, ->
|
250
|
+
expect(u.opacity($newGhost)).toBeAround(0.7, 0.25)
|
251
|
+
expect(u.opacity($oldGhost)).toBeAround(0.3, 0.25)
|
252
|
+
|
253
|
+
u.setTimer 250, ->
|
254
|
+
# Once our two ghosts have rendered their visual effect,
|
255
|
+
# we remove them from the DOM.
|
256
|
+
expect($newGhost).not.toBeInDOM()
|
257
|
+
expect($oldGhost).not.toBeInDOM()
|
258
|
+
|
259
|
+
# The old element is still in the DOM, but hidden.
|
260
|
+
# Morphing does *not* remove the target element.
|
234
261
|
expect($old.css('display')).toEqual('none')
|
235
|
-
|
236
|
-
# The new element is invisible due to an opacity of zero,
|
237
|
-
# but takes up the space in the layout flow.
|
238
|
-
expect($new.css(['display', 'opacity'])).toEqual(
|
262
|
+
expect($new.css(['display', 'visibility'])).toEqual(
|
239
263
|
display: 'block',
|
240
|
-
|
264
|
+
visibility: 'visible'
|
241
265
|
)
|
242
266
|
|
243
|
-
|
244
|
-
# element. This would delay browser painting until the element is
|
245
|
-
# shown again, causing a flicker while the browser is painting.
|
246
|
-
expect($new.css('visibility')).not.toEqual('hidden')
|
247
|
-
|
248
|
-
# Ghosts will hover over $old and $new using absolute positioning,
|
249
|
-
# matching the coordinates of the original elements.
|
250
|
-
expect($oldBounds.css(['position', 'top', 'left', 'width', 'height'])).toEqual(
|
251
|
-
position: 'absolute'
|
252
|
-
top: '10px'
|
253
|
-
left: '11px',
|
254
|
-
width: '12px',
|
255
|
-
height: '13px'
|
256
|
-
)
|
257
|
-
expect($newBounds.css(['position', 'top', 'left', 'width', 'height'])).toEqual(
|
258
|
-
position: 'absolute'
|
259
|
-
top: '20px'
|
260
|
-
left: '21px',
|
261
|
-
width: '22px',
|
262
|
-
height: '23px'
|
263
|
-
)
|
267
|
+
done()
|
264
268
|
|
265
|
-
|
266
|
-
|
267
|
-
|
269
|
+
it 'cancels an existing transition on the element by instantly jumping to the last frame', ->
|
270
|
+
$old = affix('.old').text('old content')
|
271
|
+
$new = affix('.new').text('new content')
|
268
272
|
|
269
|
-
|
270
|
-
|
271
|
-
|
273
|
+
up.morph($old, $new, 'cross-fade', duration: 200)
|
274
|
+
$ghost1 = $('.old.up-ghost')
|
275
|
+
expect($ghost1).toHaveLength(1)
|
272
276
|
|
273
|
-
|
274
|
-
|
275
|
-
|
277
|
+
up.morph($old, $new, 'cross-fade', duration: 200)
|
278
|
+
$ghost2 = $('.old.up-ghost')
|
279
|
+
# Check that we didn't create additional ghosts
|
280
|
+
expect($ghost2).toHaveLength(1)
|
281
|
+
# Check that it's a different ghosts
|
282
|
+
expect($ghost2).not.toEqual($ghost1)
|
276
283
|
|
277
|
-
|
278
|
-
# Once our two ghosts have rendered their visual effect,
|
279
|
-
# we remove them from the DOM.
|
280
|
-
expect($newGhost).not.toBeInDOM()
|
281
|
-
expect($oldGhost).not.toBeInDOM()
|
284
|
+
describe 'with { reveal: true } option', ->
|
282
285
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
286
|
+
it 'reveals the new element while making the old element within the same viewport appear as if it would keep its scroll position', ->
|
287
|
+
$container = affix('.container[up-viewport]').css
|
288
|
+
'width': '200px'
|
289
|
+
'height': '200px'
|
290
|
+
'overflow-y': 'scroll'
|
291
|
+
'position': 'fixed'
|
292
|
+
'left': 0,
|
293
|
+
'top': 0
|
294
|
+
$old = affix('.old').appendTo($container).css(height: '600px')
|
295
|
+
$container.scrollTop(300)
|
290
296
|
|
291
|
-
|
297
|
+
$new = affix('.new').insertBefore($old).css(height: '600px')
|
292
298
|
|
293
|
-
|
294
|
-
$old = affix('.old').text('old content')
|
295
|
-
$new = affix('.new').text('new content')
|
296
|
-
|
297
|
-
up.morph($old, $new, 'cross-fade', duration: 200)
|
298
|
-
$ghost1 = $('.old.up-ghost')
|
299
|
-
expect($ghost1).toHaveLength(1)
|
300
|
-
|
301
|
-
up.morph($old, $new, 'cross-fade', duration: 200)
|
302
|
-
$ghost2 = $('.old.up-ghost')
|
303
|
-
# Check that we didn't create additional ghosts
|
304
|
-
expect($ghost2).toHaveLength(1)
|
305
|
-
# Check that it's a different ghosts
|
306
|
-
expect($ghost2).not.toEqual($ghost1)
|
307
|
-
|
308
|
-
describe 'with { reveal: true } option', ->
|
309
|
-
|
310
|
-
it 'reveals the new element while making the old element within the same viewport appear as if it would keep its scroll position', ->
|
311
|
-
$container = affix('.container[up-viewport]').css
|
312
|
-
'width': '200px'
|
313
|
-
'height': '200px'
|
314
|
-
'overflow-y': 'scroll'
|
315
|
-
'position': 'fixed'
|
316
|
-
'left': 0,
|
317
|
-
'top': 0
|
318
|
-
$old = affix('.old').appendTo($container).css(height: '600px')
|
319
|
-
$container.scrollTop(300)
|
320
|
-
|
321
|
-
$new = affix('.new').insertBefore($old).css(height: '600px')
|
322
|
-
|
323
|
-
up.morph($old, $new, 'cross-fade', duration: 50, reveal: true)
|
299
|
+
up.morph($old, $new, 'cross-fade', duration: 50, reveal: true)
|
324
300
|
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
# Container is scrolled up due to { reveal: true } option.
|
329
|
-
# Since $old and $new are sitting in the same viewport with a
|
330
|
-
# single shares scrollbar This will make the ghost for $old jump.
|
331
|
-
expect($container.scrollTop()).toEqual(0)
|
332
|
-
|
333
|
-
# See that the ghost for $new is aligned with the top edge
|
334
|
-
# of the viewport.
|
335
|
-
expect($newGhost.offset().top).toEqual(0)
|
301
|
+
$oldGhost = $('.old.up-ghost')
|
302
|
+
$newGhost = $('.new.up-ghost')
|
336
303
|
|
337
|
-
|
338
|
-
|
339
|
-
|
304
|
+
# Container is scrolled up due to { reveal: true } option.
|
305
|
+
# Since $old and $new are sitting in the same viewport with a
|
306
|
+
# single shares scrollbar This will make the ghost for $old jump.
|
307
|
+
expect($container.scrollTop()).toEqual(0)
|
340
308
|
|
309
|
+
# See that the ghost for $new is aligned with the top edge
|
310
|
+
# of the viewport.
|
311
|
+
expect($newGhost.offset().top).toEqual(0)
|
341
312
|
|
342
|
-
|
313
|
+
# The ghost for $old is shifted upwards to make it looks like it
|
314
|
+
# was at the scroll position before we revealed $new.
|
315
|
+
expect($oldGhost.offset().top).toEqual(-300)
|
343
316
|
|
344
|
-
beforeEach ->
|
345
|
-
up.motion.config.enabled = false
|
346
317
|
|
347
|
-
|
348
|
-
$old = affix('.old').text('old content')
|
349
|
-
$new = affix('.new').text('new content')
|
350
|
-
up.morph($old, $new, 'cross-fade', duration: 1000)
|
351
|
-
expect($old).toBeHidden()
|
352
|
-
expect($new).toBeVisible()
|
353
|
-
expect($new.css('opacity')).toEqual('1')
|
318
|
+
describe 'with animations disabled globally', ->
|
354
319
|
|
355
|
-
|
320
|
+
beforeEach ->
|
321
|
+
up.motion.config.enabled = false
|
356
322
|
|
357
323
|
it "doesn't animate and hides the old element instead", ->
|
358
324
|
$old = affix('.old').text('old content')
|
@@ -362,18 +328,6 @@ describe 'up.motion', ->
|
|
362
328
|
expect($new).toBeVisible()
|
363
329
|
expect($new.css('opacity')).toEqual('1')
|
364
330
|
|
365
|
-
[false, null, undefined, 'none', up.motion.none()].forEach (noneTransition) ->
|
366
|
-
|
367
|
-
describe "when called with a `#{noneTransition}` transition", ->
|
368
|
-
|
369
|
-
it "doesn't animate and hides the old element instead", ->
|
370
|
-
$old = affix('.old').text('old content')
|
371
|
-
$new = affix('.new').text('new content')
|
372
|
-
up.morph($old, $new, noneTransition, duration: 1000)
|
373
|
-
expect($old).toBeHidden()
|
374
|
-
expect($new).toBeVisible()
|
375
|
-
expect($new.css('opacity')).toEqual('1')
|
376
|
-
|
377
331
|
describe 'up.transition', ->
|
378
332
|
|
379
333
|
it 'should have tests'
|