unpoly-rails 0.55.1 → 0.56.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of unpoly-rails might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +59 -2
- data/dist/unpoly-bootstrap3.js +6 -4
- data/dist/unpoly-bootstrap3.min.js +1 -1
- data/dist/unpoly.js +1323 -805
- data/dist/unpoly.min.js +4 -3
- data/lib/assets/javascripts/unpoly-bootstrap3/{navigation-ext.coffee → feedback-ext.coffee} +2 -0
- data/lib/assets/javascripts/unpoly/browser.coffee.erb +7 -7
- data/lib/assets/javascripts/unpoly/bus.coffee.erb +5 -6
- data/lib/assets/javascripts/unpoly/classes/css_transition.coffee +127 -0
- data/lib/assets/javascripts/unpoly/classes/extract_plan.coffee +1 -1
- data/lib/assets/javascripts/unpoly/classes/motion_tracker.coffee +62 -32
- data/lib/assets/javascripts/unpoly/classes/url_set.coffee +27 -0
- data/lib/assets/javascripts/unpoly/dom.coffee.erb +78 -99
- data/lib/assets/javascripts/unpoly/feedback.coffee +147 -96
- data/lib/assets/javascripts/unpoly/form.coffee.erb +26 -2
- data/lib/assets/javascripts/unpoly/history.coffee +2 -1
- data/lib/assets/javascripts/unpoly/layout.coffee.erb +68 -12
- data/lib/assets/javascripts/unpoly/link.coffee.erb +10 -4
- data/lib/assets/javascripts/unpoly/modal.coffee.erb +11 -9
- data/lib/assets/javascripts/unpoly/{motion.coffee → motion.coffee.erb} +184 -322
- data/lib/assets/javascripts/unpoly/popup.coffee.erb +13 -12
- data/lib/assets/javascripts/unpoly/radio.coffee +1 -1
- data/lib/assets/javascripts/unpoly/syntax.coffee +8 -17
- data/lib/assets/javascripts/unpoly/tooltip.coffee +11 -11
- data/lib/assets/javascripts/unpoly/util.coffee +332 -145
- data/lib/unpoly/rails/version.rb +1 -1
- data/package.json +1 -1
- data/spec_app/Gemfile.lock +1 -1
- data/spec_app/app/assets/javascripts/integration_test.coffee +1 -0
- data/spec_app/app/assets/stylesheets/integration_test.sass +1 -0
- data/spec_app/app/assets/stylesheets/jasmine_specs.sass +4 -0
- data/spec_app/app/views/motion_test/transitions.erb +13 -0
- data/spec_app/app/views/pages/start.erb +1 -0
- data/spec_app/spec/javascripts/helpers/to_be_attached.coffee +5 -0
- data/spec_app/spec/javascripts/helpers/to_be_detached.coffee +5 -0
- data/spec_app/spec/javascripts/helpers/to_contain.js.coffee +1 -1
- data/spec_app/spec/javascripts/helpers/to_have_opacity.coffee +11 -0
- data/spec_app/spec/javascripts/helpers/to_have_own_property.js.coffee +5 -0
- data/spec_app/spec/javascripts/up/dom_spec.js.coffee +217 -102
- data/spec_app/spec/javascripts/up/feedback_spec.js.coffee +162 -44
- data/spec_app/spec/javascripts/up/layout_spec.js.coffee +97 -10
- data/spec_app/spec/javascripts/up/link_spec.js.coffee +3 -3
- data/spec_app/spec/javascripts/up/modal_spec.js.coffee +22 -20
- data/spec_app/spec/javascripts/up/motion_spec.js.coffee +344 -228
- data/spec_app/spec/javascripts/up/popup_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/util_spec.js.coffee +194 -0
- metadata +11 -4
@@ -3,60 +3,118 @@ describe 'up.feedback', ->
|
|
3
3
|
u = up.util
|
4
4
|
|
5
5
|
beforeEach ->
|
6
|
+
up.history.config.enabled = true
|
6
7
|
up.modal.config.openAnimation = 'none'
|
7
8
|
up.modal.config.closeAnimation = 'none'
|
9
|
+
up.popup.config.openAnimation = 'none'
|
10
|
+
up.popup.config.closeAnimation = 'none'
|
8
11
|
|
9
12
|
describe 'unobtrusive behavior', ->
|
10
13
|
|
11
|
-
describe '
|
14
|
+
describe '[up-nav]', ->
|
12
15
|
|
13
|
-
it 'marks a link as .up-current if it links to the current URL', ->
|
14
|
-
|
15
|
-
$
|
16
|
-
$
|
16
|
+
it 'marks a child link as .up-current if it links to the current URL', ->
|
17
|
+
up.history.replace('/foo')
|
18
|
+
$nav = affix('div[up-nav]')
|
19
|
+
$currentLink = $nav.affix('a[href="/foo"]')
|
20
|
+
$otherLink = $nav.affix('a[href="/bar"]')
|
21
|
+
up.hello($nav)
|
17
22
|
expect($currentLink).toHaveClass('up-current')
|
18
23
|
expect($otherLink).not.toHaveClass('up-current')
|
19
24
|
|
25
|
+
it 'marks the element as .up-current if it is also a link to the current URL', ->
|
26
|
+
up.history.replace('/foo')
|
27
|
+
$currentLink = affix('a[href="/foo"][up-nav]')
|
28
|
+
$otherLink = affix('a[href="/bar"][up-nav]')
|
29
|
+
up.hello($currentLink)
|
30
|
+
up.hello($otherLink)
|
31
|
+
expect($currentLink).toHaveClass('up-current')
|
32
|
+
expect($otherLink).not.toHaveClass('up-current')
|
33
|
+
|
34
|
+
it 'does not mark a link as .up-current if the link is outside an [up-nav]', ->
|
35
|
+
up.history.replace('/foo')
|
36
|
+
$nav = affix('div[up-nav]')
|
37
|
+
$currentLinkInNav = $nav.affix('a[href="/foo"]')
|
38
|
+
$currentLinkOutsideNav = affix('a[href="/foo"]')
|
39
|
+
up.hello($nav)
|
40
|
+
expect($currentLinkInNav).toHaveClass('up-current')
|
41
|
+
expect($currentLinkOutsideNav).not.toHaveClass('up-current')
|
42
|
+
|
43
|
+
it 'marks a replaced child link as .up-current if it links to the current URL', asyncSpec (next) ->
|
44
|
+
up.history.replace('/foo')
|
45
|
+
$nav = affix('div[up-nav]')
|
46
|
+
$nav.affix('a.link[href="/bar"]').text('old link')
|
47
|
+
up.hello($nav)
|
48
|
+
|
49
|
+
expect('.link').toHaveText('old link')
|
50
|
+
expect('.link').not.toHaveClass('up-current')
|
51
|
+
|
52
|
+
up.replace('.link', '/src', history: false)
|
53
|
+
|
54
|
+
next =>
|
55
|
+
@respondWith """
|
56
|
+
<a class="link" href="/foo">
|
57
|
+
new link
|
58
|
+
</a>
|
59
|
+
"""
|
60
|
+
|
61
|
+
next =>
|
62
|
+
expect('.link').toHaveText('new link')
|
63
|
+
expect('.link').toHaveClass('up-current')
|
64
|
+
|
20
65
|
it 'marks any link as .up-current if its up-href attribute matches the current URL', ->
|
21
|
-
|
22
|
-
$
|
23
|
-
$
|
66
|
+
up.history.replace('/foo')
|
67
|
+
$nav = affix('div[up-nav]')
|
68
|
+
$currentLink = $nav.affix('span[up-href="/foo"]')
|
69
|
+
$otherLink = $nav.affix('span[up-href="/bar"]')
|
70
|
+
up.hello($nav)
|
24
71
|
expect($currentLink).toHaveClass('up-current')
|
25
72
|
expect($otherLink).not.toHaveClass('up-current')
|
26
73
|
|
27
74
|
it 'matches the current and destination URLs if they only differ by a trailing slash', ->
|
28
|
-
|
29
|
-
$
|
75
|
+
up.history.replace('/foo')
|
76
|
+
$nav = affix('div[up-nav]')
|
77
|
+
$currentLink = $nav.affix('span[up-href="/foo/"]')
|
78
|
+
up.hello($nav)
|
30
79
|
expect($currentLink).toHaveClass('up-current')
|
31
80
|
|
32
81
|
it 'does not match the current and destination URLs if they differ in the search', ->
|
33
|
-
|
34
|
-
$
|
82
|
+
up.history.replace('/foo?q=1')
|
83
|
+
$nav = affix('div[up-nav]')
|
84
|
+
$currentLink = $nav.affix('span[up-href="/foo?q=2"]')
|
85
|
+
up.hello($nav)
|
35
86
|
expect($currentLink).not.toHaveClass('up-current')
|
36
87
|
|
37
88
|
it 'marks any link as .up-current if any of its space-separated up-alias values matches the current URL', ->
|
38
|
-
|
39
|
-
$
|
40
|
-
$
|
89
|
+
up.history.replace('/foo')
|
90
|
+
$nav = affix('div[up-nav]')
|
91
|
+
$currentLink = $nav.affix('a[href="/x"][up-alias="/aaa /foo /bbb"]')
|
92
|
+
$otherLink = $nav.affix('a[href="/y"][up-alias="/bar"]')
|
93
|
+
up.hello($nav)
|
41
94
|
expect($currentLink).toHaveClass('up-current')
|
42
95
|
expect($otherLink).not.toHaveClass('up-current')
|
43
96
|
|
44
97
|
it 'does not throw if the current location does not match an up-alias wildcard (bugfix)', ->
|
45
|
-
inserter = -> up.hello(affix('a[up-alias="/qqqq*"]'))
|
98
|
+
inserter = -> up.hello(affix('a[up-nav][up-alias="/qqqq*"]'))
|
46
99
|
expect(inserter).not.toThrow()
|
47
100
|
|
48
101
|
it 'does not highlight a link to "#" (commonly used for JS-only buttons)', ->
|
49
|
-
$
|
102
|
+
$nav = affix('div[up-nav]')
|
103
|
+
$link = $nav.affix('a[href="#"]')
|
104
|
+
up.hello($nav)
|
50
105
|
expect($link).not.toHaveClass('up-current')
|
51
106
|
|
52
107
|
it 'does not highlight links with unsafe methods', ->
|
53
|
-
|
54
|
-
$
|
55
|
-
$
|
56
|
-
$
|
57
|
-
$
|
58
|
-
$
|
59
|
-
$
|
108
|
+
up.history.replace('/foo')
|
109
|
+
$nav = affix('div[up-nav]')
|
110
|
+
$defaultLink = $nav.affix('a[href="/foo"]')
|
111
|
+
$getLink = $nav.affix('a[href="/foo"][up-method="get"]')
|
112
|
+
$putLink = $nav.affix('a[href="/foo"][up-method="put"]')
|
113
|
+
$patchLink = $nav.affix('a[href="/foo"][up-method="patch"]')
|
114
|
+
$postLink = $nav.affix('a[href="/foo"][up-method="post"]')
|
115
|
+
$deleteLink = $nav.affix('a[href="/foo"][up-method="delete"]')
|
116
|
+
up.hello($nav)
|
117
|
+
|
60
118
|
expect($defaultLink).toHaveClass('up-current')
|
61
119
|
expect($getLink).toHaveClass('up-current')
|
62
120
|
expect($putLink).not.toHaveClass('up-current')
|
@@ -65,27 +123,57 @@ describe 'up.feedback', ->
|
|
65
123
|
expect($deleteLink).not.toHaveClass('up-current')
|
66
124
|
|
67
125
|
it 'marks URL prefixes as .up-current if an up-alias value ends in *', ->
|
68
|
-
|
69
|
-
|
70
|
-
$
|
126
|
+
up.history.replace('/foo/123')
|
127
|
+
|
128
|
+
$nav = affix('div[up-nav]')
|
129
|
+
$currentLink = $nav.affix('a[href="/x"][up-alias="/aaa /foo/* /bbb"]')
|
130
|
+
$otherLink = $nav.affix('a[href="/y"][up-alias="/bar"]')
|
131
|
+
up.hello($nav)
|
132
|
+
|
71
133
|
expect($currentLink).toHaveClass('up-current')
|
72
134
|
expect($otherLink).not.toHaveClass('up-current')
|
73
135
|
|
74
|
-
it 'allows to configure a custom "current" class
|
75
|
-
up.feedback.config.currentClasses
|
76
|
-
|
77
|
-
$
|
78
|
-
|
136
|
+
it 'allows to configure a custom "current" class in addition to .up-current', ->
|
137
|
+
up.feedback.config.currentClasses.push('highlight')
|
138
|
+
up.history.replace('/foo')
|
139
|
+
$nav = affix('div[up-nav]')
|
140
|
+
$currentLink = $nav.affix('a[href="/foo"]')
|
141
|
+
up.hello($nav)
|
142
|
+
|
143
|
+
expect($currentLink).toHaveClass('highlight')
|
144
|
+
expect($currentLink).toHaveClass('up-current')
|
145
|
+
|
146
|
+
it 'allows to configure multiple additional "current" classes', ->
|
147
|
+
up.feedback.config.currentClasses.push('highlight1')
|
148
|
+
up.feedback.config.currentClasses.push('highlight2')
|
149
|
+
up.history.replace('/foo')
|
150
|
+
$nav = affix('div[up-nav]')
|
151
|
+
$currentLink = $nav.affix('a[href="/foo"]')
|
152
|
+
up.hello($nav)
|
153
|
+
|
154
|
+
expect($currentLink).toHaveClass('highlight1')
|
155
|
+
expect($currentLink).toHaveClass('highlight2')
|
156
|
+
expect($currentLink).toHaveClass('up-current')
|
157
|
+
|
158
|
+
it 'allows to configure additional nav selectors', ->
|
159
|
+
up.history.replace('/foo')
|
160
|
+
up.feedback.config.navs.push('.navi')
|
161
|
+
$nav = affix('div.navi')
|
162
|
+
$currentLink = $nav.affix('a[href="/foo"]')
|
163
|
+
$otherLink = $nav.affix('a[href="/bar"]')
|
164
|
+
up.hello($nav)
|
165
|
+
expect($currentLink).toHaveClass('up-current')
|
166
|
+
expect($otherLink).not.toHaveClass('up-current')
|
79
167
|
|
80
168
|
describeCapability 'canPushState', ->
|
81
169
|
|
82
170
|
describe 'updating .up-current marks wen the URL changes', ->
|
83
171
|
|
84
|
-
beforeEach ->
|
85
|
-
up.history.config.enabled = true
|
86
|
-
|
87
172
|
it 'marks a link as .up-current if it links to the current URL, but is missing a trailing slash', asyncSpec (next) ->
|
88
|
-
$
|
173
|
+
$nav = affix('div[up-nav]')
|
174
|
+
$link = $nav.affix('a[href="/foo"][up-target=".main"]')
|
175
|
+
up.hello($nav)
|
176
|
+
|
89
177
|
affix('.main')
|
90
178
|
Trigger.clickSequence($link)
|
91
179
|
|
@@ -98,7 +186,10 @@ describe 'up.feedback', ->
|
|
98
186
|
expect($link).toHaveClass('up-current')
|
99
187
|
|
100
188
|
it 'marks a link as .up-current if it links to the current URL, but has an extra trailing slash', asyncSpec (next) ->
|
101
|
-
$
|
189
|
+
$nav = affix('div[up-nav]')
|
190
|
+
$link = $nav.affix('a[href="/foo/"][up-target=".main"]')
|
191
|
+
up.hello($nav)
|
192
|
+
|
102
193
|
affix('.main')
|
103
194
|
Trigger.clickSequence($link)
|
104
195
|
|
@@ -113,9 +204,11 @@ describe 'up.feedback', ->
|
|
113
204
|
it 'marks a link as .up-current if it links to an URL currently shown either within or below the modal', asyncSpec (next) ->
|
114
205
|
up.history.replace('/foo')
|
115
206
|
|
116
|
-
$
|
117
|
-
$
|
118
|
-
$
|
207
|
+
$nav = affix('div[up-nav]')
|
208
|
+
$backgroundLink = $nav.affix('a[href="/foo"]')
|
209
|
+
$modalLink = $nav.affix('a[href="/bar"][up-modal=".main"]')
|
210
|
+
$unrelatedLink = $nav.affix('a[href="/baz"]')
|
211
|
+
up.hello($nav)
|
119
212
|
|
120
213
|
Trigger.clickSequence($modalLink)
|
121
214
|
|
@@ -133,12 +226,21 @@ describe 'up.feedback', ->
|
|
133
226
|
expect($modalLink).not.toHaveClass('up-current')
|
134
227
|
expect($unrelatedLink).not.toHaveClass('up-current')
|
135
228
|
|
136
|
-
it
|
229
|
+
it "marks a link as .up-current if it links to the URL currently either within or below the popup, even if the popup doesn't change history", asyncSpec (next) ->
|
137
230
|
up.history.replace('/foo')
|
138
231
|
|
139
|
-
|
140
|
-
|
141
|
-
|
232
|
+
# This is actually the default. Popups don't change the address bar by default,
|
233
|
+
# but we still want to cause their URL to mark links as current.
|
234
|
+
up.popup.config.history = false
|
235
|
+
|
236
|
+
$nav = affix('div[up-nav]')
|
237
|
+
$backgroundLink = $nav.affix('a[href="/foo"]')
|
238
|
+
$popupLink = $nav.affix('a[href="/bar"][up-popup=".main"]')
|
239
|
+
$unrelatedLink = $nav.affix('a[href="/baz"]')
|
240
|
+
up.hello($nav)
|
241
|
+
|
242
|
+
expect(up.browser.url()).toMatchUrl('/foo')
|
243
|
+
expect(up.popup.coveredUrl()).toBeMissing()
|
142
244
|
|
143
245
|
next =>
|
144
246
|
Trigger.clickSequence($popupLink)
|
@@ -147,6 +249,8 @@ describe 'up.feedback', ->
|
|
147
249
|
@respondWith('<div class="main">new-text</div>')
|
148
250
|
|
149
251
|
next =>
|
252
|
+
expect(up.browser.url()).toMatchUrl('/foo') # popup did not change history
|
253
|
+
expect(up.popup.url()).toMatchUrl('/bar') # popup still knows which URL it is displaying
|
150
254
|
expect($backgroundLink).toHaveClass('up-current')
|
151
255
|
expect($popupLink).toHaveClass('up-current')
|
152
256
|
expect($unrelatedLink).not.toHaveClass('up-current')
|
@@ -158,6 +262,20 @@ describe 'up.feedback', ->
|
|
158
262
|
expect($popupLink).not.toHaveClass('up-current')
|
159
263
|
expect($unrelatedLink).not.toHaveClass('up-current')
|
160
264
|
|
265
|
+
it "respects links that are added to an existing [up-nav] by a fragment update", asyncSpec (next) ->
|
266
|
+
$nav = affix('.nav[up-nav]')
|
267
|
+
$link = $nav.affix('a[href="/foo"][up-target=".main"]')
|
268
|
+
$more = $nav.affix('.more')
|
269
|
+
up.hello($nav)
|
270
|
+
|
271
|
+
up.extract '.more', '<div class="more"><a href="/bar"></div>', history: '/bar'
|
272
|
+
|
273
|
+
next =>
|
274
|
+
$moreLink = $('.more').find('a')
|
275
|
+
expect($moreLink).toExist()
|
276
|
+
expect($moreLink).toHaveClass('up-current')
|
277
|
+
|
278
|
+
|
161
279
|
describe '.up-active', ->
|
162
280
|
|
163
281
|
describeCapability 'canPushState', ->
|
@@ -9,7 +9,6 @@ describe 'up.layout', ->
|
|
9
9
|
beforeEach ->
|
10
10
|
up.layout.config.snap = 0
|
11
11
|
up.layout.config.substance = 99999
|
12
|
-
up.layout.config.viewports = [document]
|
13
12
|
|
14
13
|
describe 'when the viewport is the document', ->
|
15
14
|
|
@@ -403,7 +402,7 @@ describe 'up.layout', ->
|
|
403
402
|
|
404
403
|
it 'should have tests'
|
405
404
|
|
406
|
-
describe 'up.layout.
|
405
|
+
describe 'up.layout.viewportOf', ->
|
407
406
|
|
408
407
|
it 'seeks upwards from the given element', ->
|
409
408
|
up.layout.config.viewports = ['.viewport1', '.viewport2']
|
@@ -417,19 +416,13 @@ describe 'up.layout', ->
|
|
417
416
|
$viewport = affix('.viewport')
|
418
417
|
expect(up.layout.viewportOf($viewport)).toEqual($viewport)
|
419
418
|
|
420
|
-
it 'finds the document if
|
419
|
+
it 'finds the document if no better viewport matches', ->
|
421
420
|
# This actually tests that the hierarchy returned by `$.parent`
|
422
421
|
# is $element => ... => $('body') => $('html') => $(document)
|
423
|
-
up.layout.config.viewports = [
|
422
|
+
up.layout.config.viewports = ['.other-viewport']
|
424
423
|
$element = affix('div')
|
425
424
|
expect(up.layout.viewportOf($element)).toEqual($(document))
|
426
425
|
|
427
|
-
it 'throws an error if no viewport could be found', ->
|
428
|
-
up.layout.config.viewports = ['.does-not-exist']
|
429
|
-
$element = affix('div')
|
430
|
-
lookup = -> up.layout.viewportOf($element)
|
431
|
-
expect(lookup).toThrowError(/Could not find viewport/i)
|
432
|
-
|
433
426
|
describe 'up.layout.restoreScroll', ->
|
434
427
|
|
435
428
|
it "restores a viewport's previously saved scroll position", (done) ->
|
@@ -456,3 +449,97 @@ describe 'up.layout', ->
|
|
456
449
|
describe 'up.scroll', ->
|
457
450
|
|
458
451
|
it 'should have tests'
|
452
|
+
|
453
|
+
describe 'up.layout.absolutize', ->
|
454
|
+
|
455
|
+
afterEach ->
|
456
|
+
$('.up-bounds, .fixture').remove()
|
457
|
+
|
458
|
+
it 'absolutely positions the element, preserving visual position and size', ->
|
459
|
+
$element = affix('.element').text('element text').css(paddingTop: '20px', paddingLeft: '20px')
|
460
|
+
|
461
|
+
expect($element.css('position')).toEqual('static')
|
462
|
+
previousDims = u.measure($element)
|
463
|
+
|
464
|
+
up.layout.absolutize($element)
|
465
|
+
|
466
|
+
expect($element.closest('.up-bounds').css('position')).toEqual('absolute')
|
467
|
+
|
468
|
+
newDims = u.measure($element)
|
469
|
+
expect(newDims).toEqual(previousDims)
|
470
|
+
|
471
|
+
it 'accurately positions the ghost over an element with margins', ->
|
472
|
+
$element = affix('.element').css(margin: '40px')
|
473
|
+
previousDims = u.measure($element)
|
474
|
+
|
475
|
+
up.layout.absolutize($element)
|
476
|
+
|
477
|
+
newDims = u.measure($element)
|
478
|
+
expect(newDims).toEqual(previousDims)
|
479
|
+
|
480
|
+
it "doesn't change the position of a child whose margins no longer collapse", ->
|
481
|
+
$element = affix('.element')
|
482
|
+
$child = $('<div class="child">child text</div>').css(margin: '40px').appendTo($element)
|
483
|
+
previousChildDims = u.measure($child)
|
484
|
+
|
485
|
+
up.layout.absolutize($element)
|
486
|
+
|
487
|
+
newChildDims = u.measure($child)
|
488
|
+
expect(newChildDims).toEqual(previousChildDims)
|
489
|
+
|
490
|
+
it 'correctly positions an element within a scrolled body', ->
|
491
|
+
$body = $('body')
|
492
|
+
$element1 = $('<div class="fixture"></div>').css(height: '75px').prependTo($body)
|
493
|
+
$element2 = $('<div class="fixture"></div>').css(height: '100px').insertAfter($element1)
|
494
|
+
$body.scrollTop(33)
|
495
|
+
|
496
|
+
previousDims = u.measure($element2)
|
497
|
+
|
498
|
+
up.layout.absolutize($element2)
|
499
|
+
|
500
|
+
newDims = u.measure($element2)
|
501
|
+
expect(newDims).toEqual(previousDims)
|
502
|
+
|
503
|
+
it 'correctly positions an element within a scrolled parent element (that has overflow-y: scroll)', ->
|
504
|
+
$viewport = affix('div').css
|
505
|
+
overflowY: 'scroll'
|
506
|
+
height: '50px'
|
507
|
+
|
508
|
+
$element1 = $('<div class="fixture"></div>').css(height: '75px').prependTo($viewport)
|
509
|
+
$element2 = $('<div class="fixture"></div>').css(height: '100px').insertAfter($element1)
|
510
|
+
$viewport.scrollTop(33)
|
511
|
+
|
512
|
+
previousDims = u.measure($element2)
|
513
|
+
|
514
|
+
up.layout.absolutize($element2)
|
515
|
+
|
516
|
+
newDims = u.measure($element2)
|
517
|
+
expect(newDims).toEqual(previousDims)
|
518
|
+
|
519
|
+
it 'converts fixed elements within the copies to absolutely positioning (relative to the closest offset parent)', ->
|
520
|
+
$element = affix('.element').css
|
521
|
+
position: 'absolute'
|
522
|
+
top: '50px'
|
523
|
+
left: '50px'
|
524
|
+
$fixedChild = $('<div class="fixed-child" up-fixed></div>').css
|
525
|
+
position: 'fixed'
|
526
|
+
left: '77px'
|
527
|
+
top: '77px'
|
528
|
+
$fixedChild.appendTo($element)
|
529
|
+
up.layout.absolutize($element)
|
530
|
+
|
531
|
+
expect($fixedChild.css(['position', 'left', 'top'])).toEqual
|
532
|
+
position: 'absolute',
|
533
|
+
left: '27px',
|
534
|
+
top: '27px'
|
535
|
+
|
536
|
+
it "does not convert fixed elements outside the element's subtree (bugfix)", ->
|
537
|
+
$element = affix('.element').css(position: 'absolute')
|
538
|
+
$fixedChild = $('<div class="fixed-child" up-fixed></div>').css(position: 'fixed')
|
539
|
+
$fixedChild.appendTo($element)
|
540
|
+
$fixedSibling = affix('[up-fixed]').css(position: 'fixed')
|
541
|
+
|
542
|
+
up.layout.absolutize($element)
|
543
|
+
|
544
|
+
expect($fixedChild.css('position')).toEqual('absolute')
|
545
|
+
expect($fixedSibling.css('position')).toEqual('fixed')
|
@@ -525,7 +525,7 @@ describe 'up.link', ->
|
|
525
525
|
buildEvent = ($element, attrs) ->
|
526
526
|
event = Trigger.createMouseEvent('mousedown', attrs)
|
527
527
|
event = $.event.fix(event) # convert native event to jQuery event
|
528
|
-
event.target = u.
|
528
|
+
event.target = u.element($element)
|
529
529
|
event
|
530
530
|
|
531
531
|
it "returns true when the given event's target is the given link itself", ->
|
@@ -822,8 +822,8 @@ describe 'up.link', ->
|
|
822
822
|
@respondWith '<div class="target new">new text</div>'
|
823
823
|
|
824
824
|
next =>
|
825
|
-
@$oldGhost = $('.target.old
|
826
|
-
@$newGhost = $('.target.new
|
825
|
+
@$oldGhost = $('.target.old')
|
826
|
+
@$newGhost = $('.target.new')
|
827
827
|
expect(@$oldGhost).toExist()
|
828
828
|
expect(@$newGhost).toExist()
|
829
829
|
expect(u.opacity(@$oldGhost)).toBeAround(1, 0.15)
|
@@ -132,23 +132,27 @@ describe 'up.modal', ->
|
|
132
132
|
it "gives the scrollbar to .up-modal instead of .up-modal-viewport while animating, so we don't see scaled scrollbars in a zoom-in animation", (done) ->
|
133
133
|
openPromise = up.modal.extract('.container', '<div class="container">text</div>', animation: 'fade-in', duration: 100)
|
134
134
|
|
135
|
-
u.
|
135
|
+
u.setTimer 50, ->
|
136
136
|
$modal = $('.up-modal')
|
137
137
|
$viewport = $modal.find('.up-modal-viewport')
|
138
|
+
expect($modal).toHaveClass('up-modal-animating')
|
138
139
|
expect($modal.css('overflow-y')).toEqual('scroll')
|
139
140
|
expect($viewport.css('overflow-y')).toEqual('hidden')
|
140
141
|
|
141
142
|
openPromise.then ->
|
143
|
+
expect($modal).not.toHaveClass('up-modal-animating')
|
142
144
|
expect($modal.css('overflow-y')).not.toEqual('scroll')
|
143
145
|
expect($viewport.css('overflow-y')).toEqual('scroll')
|
144
|
-
closePromise = up.modal.close(animation: 'fade-out', duration:
|
145
|
-
|
146
|
+
closePromise = up.modal.close(animation: 'fade-out', duration: 400)
|
147
|
+
|
148
|
+
u.setTimer 50, ->
|
149
|
+
expect($modal).toHaveClass('up-modal-animating')
|
146
150
|
expect($modal.css('overflow-y')).toEqual('scroll')
|
147
151
|
expect($viewport.css('overflow-y')).toEqual('hidden')
|
148
152
|
done()
|
149
153
|
|
150
154
|
it 'does not add right padding to the body if the body has overflow-y: hidden', (done) ->
|
151
|
-
restoreBody = u.
|
155
|
+
restoreBody = u.writeTemporaryStyle($('body'), overflowY: 'hidden')
|
152
156
|
|
153
157
|
up.modal.extract('.container', '<div class="container">text</div>').then ->
|
154
158
|
$body = $('body')
|
@@ -161,8 +165,8 @@ describe 'up.modal', ->
|
|
161
165
|
done()
|
162
166
|
|
163
167
|
it 'does not add right padding to the body if the body has overflow-y: auto, but does not currently have scrollbars', (done) ->
|
164
|
-
restoreBody = u.
|
165
|
-
restoreReporter = u.
|
168
|
+
restoreBody = u.writeTemporaryStyle($('body'), overflowY: 'auto')
|
169
|
+
restoreReporter = u.writeTemporaryStyle($('.jasmine_html-reporter'), height: '100px', overflowY: 'hidden')
|
166
170
|
|
167
171
|
up.modal.extract('.container', '<div class="container">text</div>').then ->
|
168
172
|
$body = $('body')
|
@@ -243,9 +247,9 @@ describe 'up.modal', ->
|
|
243
247
|
|
244
248
|
it 'closes the current modal and wait for its close animation to finish before starting the open animation of a second modal', asyncSpec (next) ->
|
245
249
|
up.modal.config.openAnimation = 'fade-in'
|
246
|
-
up.modal.config.openDuration =
|
250
|
+
up.modal.config.openDuration = 100
|
247
251
|
up.modal.config.closeAnimation = 'fade-out'
|
248
|
-
up.modal.config.closeDuration =
|
252
|
+
up.modal.config.closeDuration = 100
|
249
253
|
|
250
254
|
events = []
|
251
255
|
u.each ['up:modal:open', 'up:modal:opened', 'up:modal:close', 'up:modal:closed'], (event) ->
|
@@ -255,40 +259,38 @@ describe 'up.modal', ->
|
|
255
259
|
up.modal.extract('.target', '<div class="target">response1</div>')
|
256
260
|
|
257
261
|
next =>
|
258
|
-
# First modal is starting opening animation (will take
|
262
|
+
# First modal is starting opening animation (will take 100 ms)
|
259
263
|
expect(events).toEqual ['up:modal:open']
|
260
264
|
expect($('.target')).toHaveText('response1')
|
261
265
|
|
262
|
-
next.after (
|
263
|
-
# First modal has completed opening animation after
|
266
|
+
next.after (100 + (timingTolerance = 100)), =>
|
267
|
+
# First modal has completed opening animation after 100 ms
|
264
268
|
expect(events).toEqual ['up:modal:open', 'up:modal:opened']
|
265
269
|
expect($('.target')).toHaveText('response1')
|
266
270
|
|
267
|
-
# We open another modal, which will cause the first modal to start closing (will take
|
271
|
+
# We open another modal, which will cause the first modal to start closing (will take 100 ms)
|
268
272
|
up.modal.extract('.target', '<div class="target">response2</div>')
|
269
273
|
|
270
|
-
next.after
|
274
|
+
next.after 50, =>
|
271
275
|
# Second modal is still waiting for first modal's closing animaton to finish.
|
272
276
|
expect(events).toEqual ['up:modal:open', 'up:modal:opened', 'up:modal:close']
|
273
277
|
expect($('.target')).toHaveText('response1')
|
274
278
|
|
275
|
-
|
276
|
-
# We need to add 200ms to make it pass all of the time.
|
277
|
-
next.after (25 + 50 + 200), =>
|
279
|
+
next.after (50 + 100 + (timingTolerance = 200)), =>
|
278
280
|
# First modal has finished closing, second modal has finished opening.
|
279
281
|
expect(events).toEqual ['up:modal:open', 'up:modal:opened', 'up:modal:close', 'up:modal:closed', 'up:modal:open', 'up:modal:opened']
|
280
282
|
expect($('.target')).toHaveText('response2')
|
281
283
|
|
282
284
|
it 'closes an opening modal if a second modal starts opening before the first modal has finished its open animation', asyncSpec (next) ->
|
283
285
|
up.modal.config.openAnimation = 'fade-in'
|
284
|
-
up.modal.config.openDuration =
|
286
|
+
up.modal.config.openDuration = 100
|
285
287
|
up.modal.config.closeAnimation = 'fade-out'
|
286
|
-
up.modal.config.closeDuration =
|
288
|
+
up.modal.config.closeDuration = 100
|
287
289
|
|
288
290
|
# Open the first modal
|
289
291
|
up.modal.extract('.target', '<div class="target">response1</div>')
|
290
292
|
|
291
|
-
next.after
|
293
|
+
next.after 50, =>
|
292
294
|
# First modal is still in its opening animation
|
293
295
|
expect($('.target')).toHaveText('response1')
|
294
296
|
|
@@ -303,7 +305,7 @@ describe 'up.modal', ->
|
|
303
305
|
# Second modal is still waiting for first modal's closing animaton to finish.
|
304
306
|
expect($('.target')).toHaveText('response1')
|
305
307
|
|
306
|
-
next.after
|
308
|
+
next.after (140 + (timingTolerance = 220)), =>
|
307
309
|
# First modal has finished closing, second modal has finished opening.
|
308
310
|
expect($('.target')).toHaveText('response2')
|
309
311
|
|