unpoly-rails 0.55.1 → 0.56.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 +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
|
|