unpoly-rails 0.23.0 → 0.24.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 +68 -0
- data/dist/unpoly-bootstrap3.js +1 -1
- data/dist/unpoly-bootstrap3.min.js +1 -1
- data/dist/unpoly.css +18 -8
- data/dist/unpoly.js +498 -265
- data/dist/unpoly.min.css +1 -1
- data/dist/unpoly.min.js +3 -3
- data/lib/assets/javascripts/unpoly-bootstrap3/modal-ext.js.coffee +5 -2
- data/lib/assets/javascripts/unpoly/flow.js.coffee +3 -1
- data/lib/assets/javascripts/unpoly/form.js.coffee +3 -6
- data/lib/assets/javascripts/unpoly/layout.js.coffee +1 -1
- data/lib/assets/javascripts/unpoly/link.js.coffee +4 -2
- data/lib/assets/javascripts/unpoly/log.js.coffee +2 -2
- data/lib/assets/javascripts/unpoly/modal.js.coffee +125 -36
- data/lib/assets/javascripts/unpoly/motion.js.coffee +75 -37
- data/lib/assets/javascripts/unpoly/navigation.js.coffee +38 -26
- data/lib/assets/javascripts/unpoly/proxy.js.coffee +77 -52
- data/lib/assets/javascripts/unpoly/syntax.js.coffee +1 -0
- data/lib/assets/javascripts/unpoly/tooltip.js.coffee +2 -0
- data/lib/assets/javascripts/unpoly/util.js.coffee +138 -46
- data/lib/assets/stylesheets/unpoly/link.css.sass +1 -1
- data/lib/assets/stylesheets/unpoly/modal.css.sass +28 -15
- data/lib/unpoly/rails/version.rb +1 -1
- data/spec_app/Gemfile.lock +7 -7
- data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +2 -0
- data/spec_app/spec/javascripts/helpers/to_contain.js.coffee +5 -0
- data/spec_app/spec/javascripts/up/flow_spec.js.coffee +2 -2
- data/spec_app/spec/javascripts/up/history_spec.js.coffee +6 -4
- data/spec_app/spec/javascripts/up/link_spec.js.coffee +114 -5
- data/spec_app/spec/javascripts/up/modal_spec.js.coffee +28 -18
- data/spec_app/spec/javascripts/up/motion_spec.js.coffee +112 -7
- data/spec_app/spec/javascripts/up/navigation_spec.js.coffee +157 -121
- data/spec_app/spec/javascripts/up/popup_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +42 -3
- data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +1 -2
- data/spec_app/spec/javascripts/up/util_spec.js.coffee +26 -1
- data/spec_app/vendor/assets/bower_components/jquery/.bower.json +1 -1
- metadata +3 -3
- data/spec_app/spec/javascripts/helpers/set_timer.js.coffee +0 -3
@@ -1,2 +1,2 @@
|
|
1
|
-
[up-href]
|
1
|
+
[up-href]
|
2
2
|
cursor: pointer
|
@@ -1,35 +1,50 @@
|
|
1
|
-
$stratum:
|
2
|
-
$
|
3
|
-
|
4
|
-
|
1
|
+
$stratum-backdrop: 10000
|
2
|
+
$stratum-elements: 11000
|
3
|
+
|
4
|
+
// These could actually be 1000, 2000, 3000 and 4000 since the `fixed` position of some elements defines
|
5
|
+
// a stacking context for all contained z-indexes.
|
6
|
+
//
|
7
|
+
// However, let's keep the option open that these elements will one day not have its stacking context.
|
8
|
+
//
|
9
|
+
// Also let's not do 1, 2, 3 and 4 so other elements have a chance to move themselves between the layers.
|
10
|
+
$substratum-dialog: 12000
|
11
|
+
$substratum-content: 13000
|
12
|
+
$substratum-close: 14000
|
5
13
|
|
6
14
|
$close-height: 36px
|
7
15
|
$close-width: 36px
|
8
16
|
$close-font-size: 34px
|
9
17
|
|
10
|
-
=transform($transform)
|
11
|
-
transform: $transform
|
12
|
-
-ms-transform: $transform // IE9
|
13
|
-
-webkit-transform: $transform // Safari, Some Android
|
14
|
-
|
15
18
|
.up-modal
|
19
|
+
|
20
|
+
.up-modal-backdrop
|
21
|
+
z-index: $stratum-backdrop
|
22
|
+
background-color: rgba(90, 90, 90, 0.4)
|
23
|
+
position: fixed
|
24
|
+
top: 0
|
25
|
+
right: 0
|
26
|
+
bottom: 0
|
27
|
+
left: 0
|
28
|
+
|
29
|
+
.up-modal-viewport
|
30
|
+
z-index: $stratum-elements
|
16
31
|
position: fixed
|
17
32
|
top: 0
|
18
33
|
left: 0
|
19
34
|
bottom: 0
|
20
35
|
right: 0
|
21
|
-
z-index: $stratum
|
22
|
-
background-color: rgba(90, 90, 90, 0.4)
|
23
36
|
overflow-x: hidden
|
24
|
-
overflow-y:
|
37
|
+
overflow-y: hidden
|
25
38
|
// We prefer centering the dialog as an `inline-block`
|
26
39
|
// to giving it a horizontal margin of `auto`. This way
|
27
40
|
// the width of `.up-modal-dialog` is controlled by the
|
28
41
|
// contents of `.up-modal-content`.
|
29
42
|
text-align: center
|
30
43
|
|
44
|
+
.up-modal.up-modal-ready &
|
45
|
+
overflow-y: scroll
|
46
|
+
|
31
47
|
.up-modal-dialog
|
32
|
-
// The z-index lives in the stacking context of .up-modal
|
33
48
|
z-index: $substratum-dialog
|
34
49
|
// Make sure .up-modal-close is relative to the dialog
|
35
50
|
position: relative
|
@@ -47,14 +62,12 @@ $close-font-size: 34px
|
|
47
62
|
text-align: left
|
48
63
|
|
49
64
|
.up-modal-content
|
50
|
-
// The z-index lives in the stacking context of .up-modal
|
51
65
|
z-index: $substratum-content
|
52
66
|
padding: 20px
|
53
67
|
background-color: #fff
|
54
68
|
box-shadow: 0 0 10px 1px rgba(0, 0, 0, 0.3)
|
55
69
|
|
56
70
|
.up-modal-close
|
57
|
-
// The z-index lives in the stacking context of .up-modal
|
58
71
|
z-index: $substratum-close
|
59
72
|
position: absolute
|
60
73
|
right: 0
|
data/lib/unpoly/rails/version.rb
CHANGED
data/spec_app/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
unpoly-rails (0.
|
4
|
+
unpoly-rails (0.23.1)
|
5
5
|
rails (>= 3)
|
6
6
|
|
7
7
|
GEM
|
@@ -88,8 +88,8 @@ GEM
|
|
88
88
|
phantomjs (>= 1.9)
|
89
89
|
railties (>= 3.2.0)
|
90
90
|
sprockets-rails
|
91
|
-
jquery-rails (4.
|
92
|
-
rails-dom-testing (
|
91
|
+
jquery-rails (4.1.1)
|
92
|
+
rails-dom-testing (>= 1, < 3)
|
93
93
|
railties (>= 4.2.0)
|
94
94
|
thor (>= 0.14, < 2.0)
|
95
95
|
json (1.8.3)
|
@@ -100,9 +100,9 @@ GEM
|
|
100
100
|
mime-types (>= 1.16, < 3)
|
101
101
|
mime-types (2.99)
|
102
102
|
mini_portile2 (2.0.0)
|
103
|
-
minitest (5.8.
|
103
|
+
minitest (5.8.4)
|
104
104
|
multi_json (1.11.2)
|
105
|
-
nokogiri (1.6.7.
|
105
|
+
nokogiri (1.6.7.2)
|
106
106
|
mini_portile2 (~> 2.0.0.rc2)
|
107
107
|
phantomjs (1.9.8.0)
|
108
108
|
rack (1.6.4)
|
@@ -125,14 +125,14 @@ GEM
|
|
125
125
|
activesupport (>= 4.2.0.beta, < 5.0)
|
126
126
|
nokogiri (~> 1.6.0)
|
127
127
|
rails-deprecated_sanitizer (>= 1.0.1)
|
128
|
-
rails-html-sanitizer (1.0.
|
128
|
+
rails-html-sanitizer (1.0.3)
|
129
129
|
loofah (~> 2.0)
|
130
130
|
railties (4.2.0)
|
131
131
|
actionpack (= 4.2.0)
|
132
132
|
activesupport (= 4.2.0)
|
133
133
|
rake (>= 0.8.7)
|
134
134
|
thor (>= 0.18.1, < 2.0)
|
135
|
-
rake (
|
135
|
+
rake (11.1.2)
|
136
136
|
ref (1.0.5)
|
137
137
|
rspec-core (3.4.1)
|
138
138
|
rspec-support (~> 3.4.0)
|
@@ -480,7 +480,7 @@ describe 'up.flow', ->
|
|
480
480
|
expect($ghost2).toHaveLength(1)
|
481
481
|
expect($ghost2.css('opacity')).toBeAround(0.0, 0.1)
|
482
482
|
|
483
|
-
|
483
|
+
u.setTimer 40, ->
|
484
484
|
expect($ghost1.css('opacity')).toBeAround(0.0, 0.2)
|
485
485
|
expect($ghost2.css('opacity')).toBeAround(1.0, 0.2)
|
486
486
|
done()
|
@@ -534,7 +534,7 @@ describe 'up.flow', ->
|
|
534
534
|
promise = up.extract('.element', '<div class="element">version 2</div>', transition: 'cross-fade', duration: 30)
|
535
535
|
promise.then(resolution)
|
536
536
|
expect(resolution).not.toHaveBeenCalled()
|
537
|
-
|
537
|
+
u.setTimer 50, ->
|
538
538
|
expect(resolution).toHaveBeenCalled()
|
539
539
|
done()
|
540
540
|
|
@@ -1,4 +1,6 @@
|
|
1
1
|
describe 'up.history', ->
|
2
|
+
|
3
|
+
u = up.util
|
2
4
|
|
3
5
|
describe 'Javascript functions', ->
|
4
6
|
|
@@ -74,23 +76,23 @@ describe 'up.history', ->
|
|
74
76
|
$('.viewport').scrollTop(250)
|
75
77
|
|
76
78
|
history.back()
|
77
|
-
|
79
|
+
u.setTimer 50, ->
|
78
80
|
respond() # we need to respond since we've never requested /two with the popTarget
|
79
81
|
expect($('.viewport').scrollTop()).toBe(150)
|
80
82
|
|
81
83
|
history.back()
|
82
|
-
|
84
|
+
u.setTimer 50, ->
|
83
85
|
respond() # we need to respond since we've never requested /one with the popTarget
|
84
86
|
expect($('.viewport').scrollTop()).toBe(50)
|
85
87
|
|
86
88
|
history.forward()
|
87
|
-
|
89
|
+
u.setTimer 50, ->
|
88
90
|
# No need to respond since we requested /two with the popTarget
|
89
91
|
# when we went backwards
|
90
92
|
expect($('.viewport').scrollTop()).toBe(150)
|
91
93
|
|
92
94
|
history.forward()
|
93
|
-
|
95
|
+
u.setTimer 50, ->
|
94
96
|
respond() # we need to respond since we've never requested /three with the popTarget
|
95
97
|
expect($('.viewport').scrollTop()).toBe(250)
|
96
98
|
done()
|
@@ -83,21 +83,21 @@ describe 'up.link', ->
|
|
83
83
|
expect(document.title).toEqual('title from three')
|
84
84
|
|
85
85
|
history.back()
|
86
|
-
|
86
|
+
u.setTimer 50, ->
|
87
87
|
respondWith('restored text from two', 'restored title from two')
|
88
88
|
expect($('.target')).toHaveText('restored text from two')
|
89
89
|
expect(location.pathname).toEqual('/two')
|
90
90
|
expect(document.title).toEqual('restored title from two')
|
91
91
|
|
92
92
|
history.back()
|
93
|
-
|
93
|
+
u.setTimer 50, ->
|
94
94
|
respondWith('restored text from one', 'restored title from one')
|
95
95
|
expect($('.target')).toHaveText('restored text from one')
|
96
96
|
expect(location.pathname).toEqual('/one')
|
97
97
|
expect(document.title).toEqual('restored title from one')
|
98
98
|
|
99
99
|
history.forward()
|
100
|
-
|
100
|
+
u.setTimer 50, ->
|
101
101
|
# Since the response is cached, we don't have to respond
|
102
102
|
expect($('.target')).toHaveText('restored text from two', 'restored title from two')
|
103
103
|
expect(location.pathname).toEqual('/two')
|
@@ -105,6 +105,115 @@ describe 'up.link', ->
|
|
105
105
|
|
106
106
|
done()
|
107
107
|
|
108
|
+
it 'does not add additional history entries when linking to the current URL', (done) ->
|
109
|
+
|
110
|
+
# By default, up.history will replace the <body> tag when
|
111
|
+
# the user presses the back-button. We reconfigure this
|
112
|
+
# so we don't lose the Jasmine runner interface.
|
113
|
+
up.history.config.popTargets = ['.container']
|
114
|
+
|
115
|
+
up.proxy.config.cacheExpiry = 0
|
116
|
+
|
117
|
+
respondWith = (text) =>
|
118
|
+
@respondWith """
|
119
|
+
<div class="container">
|
120
|
+
<div class='target'>#{text}</div>
|
121
|
+
</div>
|
122
|
+
"""
|
123
|
+
|
124
|
+
followAndRespond = ($link, text) =>
|
125
|
+
promise = up.follow($link)
|
126
|
+
respondWith(text)
|
127
|
+
promise
|
128
|
+
|
129
|
+
$link1 = affix('a[href="/one"][up-target=".target"]')
|
130
|
+
$link2 = affix('a[href="/two"][up-target=".target"]')
|
131
|
+
$container = affix('.container')
|
132
|
+
$target = affix('.target').appendTo($container).text('original text')
|
133
|
+
|
134
|
+
followAndRespond($link1, 'text from one').then =>
|
135
|
+
expect($('.target')).toHaveText('text from one')
|
136
|
+
expect(location.pathname).toEqual('/one')
|
137
|
+
|
138
|
+
followAndRespond($link2, 'text from two').then =>
|
139
|
+
expect($('.target')).toHaveText('text from two')
|
140
|
+
expect(location.pathname).toEqual('/two')
|
141
|
+
|
142
|
+
followAndRespond($link2, 'text from two').then =>
|
143
|
+
expect($('.target')).toHaveText('text from two')
|
144
|
+
expect(location.pathname).toEqual('/two')
|
145
|
+
|
146
|
+
history.back()
|
147
|
+
u.setTimer 50, ->
|
148
|
+
respondWith('restored text from one')
|
149
|
+
expect($('.target')).toHaveText('restored text from one')
|
150
|
+
expect(location.pathname).toEqual('/one')
|
151
|
+
|
152
|
+
history.forward()
|
153
|
+
u.setTimer 50, ->
|
154
|
+
respondWith('restored text from two')
|
155
|
+
expect($('.target')).toHaveText('restored text from two')
|
156
|
+
expect(location.pathname).toEqual('/two')
|
157
|
+
|
158
|
+
done()
|
159
|
+
|
160
|
+
it 'does adds additional history entries when linking to the current URL, but with a different hash', (done) ->
|
161
|
+
|
162
|
+
# By default, up.history will replace the <body> tag when
|
163
|
+
# the user presses the back-button. We reconfigure this
|
164
|
+
# so we don't lose the Jasmine runner interface.
|
165
|
+
up.history.config.popTargets = ['.container']
|
166
|
+
|
167
|
+
up.proxy.config.cacheExpiry = 0
|
168
|
+
|
169
|
+
respondWith = (text) =>
|
170
|
+
@respondWith """
|
171
|
+
<div class="container">
|
172
|
+
<div class='target'>#{text}</div>
|
173
|
+
</div>
|
174
|
+
"""
|
175
|
+
|
176
|
+
followAndRespond = ($link, text) =>
|
177
|
+
promise = up.follow($link)
|
178
|
+
respondWith(text)
|
179
|
+
promise
|
180
|
+
|
181
|
+
$link1 = affix('a[href="/one"][up-target=".target"]')
|
182
|
+
$link2 = affix('a[href="/two"][up-target=".target"]')
|
183
|
+
$link2WithHash = affix('a[href="/two#hash"][up-target=".target"]')
|
184
|
+
$container = affix('.container')
|
185
|
+
$target = affix('.target').appendTo($container).text('original text')
|
186
|
+
|
187
|
+
followAndRespond($link1, 'text from one').then =>
|
188
|
+
expect($('.target')).toHaveText('text from one')
|
189
|
+
expect(location.pathname).toEqual('/one')
|
190
|
+
expect(location.hash).toEqual('')
|
191
|
+
|
192
|
+
followAndRespond($link2, 'text from two').then =>
|
193
|
+
expect($('.target')).toHaveText('text from two')
|
194
|
+
expect(location.pathname).toEqual('/two')
|
195
|
+
expect(location.hash).toEqual('')
|
196
|
+
|
197
|
+
followAndRespond($link2WithHash, 'text from two with hash').then =>
|
198
|
+
expect($('.target')).toHaveText('text from two with hash')
|
199
|
+
expect(location.pathname).toEqual('/two')
|
200
|
+
expect(location.hash).toEqual('#hash')
|
201
|
+
|
202
|
+
history.back()
|
203
|
+
u.setTimer 50, ->
|
204
|
+
respondWith('restored text from two')
|
205
|
+
expect($('.target')).toHaveText('restored text from two')
|
206
|
+
expect(location.pathname).toEqual('/two')
|
207
|
+
expect(location.hash).toEqual('')
|
208
|
+
|
209
|
+
history.forward()
|
210
|
+
u.setTimer 50, ->
|
211
|
+
respondWith('restored text from two with hash')
|
212
|
+
expect($('.target')).toHaveText('restored text from two with hash')
|
213
|
+
expect(location.pathname).toEqual('/two')
|
214
|
+
expect(location.hash).toEqual('#hash')
|
215
|
+
done()
|
216
|
+
|
108
217
|
describe 'with { restoreScroll: true } option', ->
|
109
218
|
|
110
219
|
it 'does not reveal, but instead restores the scroll positions of all viewports around the target', ->
|
@@ -230,7 +339,7 @@ describe 'up.link', ->
|
|
230
339
|
it 'does not follow a form with up-target attribute (bugfix)', ->
|
231
340
|
$form = affix('form[up-target]')
|
232
341
|
up.hello($form)
|
233
|
-
followSpy = up.link.knife.mock('follow')
|
342
|
+
followSpy = up.link.knife.mock('follow').and.returnValue(u.resolvedPromise())
|
234
343
|
$form.click()
|
235
344
|
expect(followSpy).not.toHaveBeenCalled()
|
236
345
|
|
@@ -269,7 +378,7 @@ describe 'up.link', ->
|
|
269
378
|
|
270
379
|
beforeEach ->
|
271
380
|
@$link = affix('a[href="/path"][up-follow]')
|
272
|
-
@followSpy = up.link.knife.mock('follow')
|
381
|
+
@followSpy = up.link.knife.mock('follow').and.returnValue(u.resolvedPromise())
|
273
382
|
@defaultSpy = up.link.knife.mock('allowDefault').and.callFake((event) -> event.preventDefault())
|
274
383
|
|
275
384
|
it "calls up.follow with the clicked link", ->
|
@@ -26,6 +26,25 @@ describe 'up.modal', ->
|
|
26
26
|
expect($('.up-modal-dialog .after')).not.toExist()
|
27
27
|
done()
|
28
28
|
|
29
|
+
describe 'up.modal.extract', ->
|
30
|
+
|
31
|
+
it 'opens a modal by extracting the given selector from the given HTML string', ->
|
32
|
+
oldHref = location.href
|
33
|
+
up.modal.extract '.middle', """
|
34
|
+
<div class="before">new-before</div>
|
35
|
+
<div class="middle">new-middle</div>
|
36
|
+
<div class="after">new-after</div>
|
37
|
+
"""
|
38
|
+
expect($('.up-modal')).toExist()
|
39
|
+
expect($('.up-modal-dialog')).toExist()
|
40
|
+
expect($('.up-modal-dialog .middle')).toExist()
|
41
|
+
expect($('.up-modal-dialog .middle')).toHaveText('new-middle')
|
42
|
+
expect($('.up-modal-dialog .before')).not.toExist()
|
43
|
+
expect($('.up-modal-dialog .after')).not.toExist()
|
44
|
+
|
45
|
+
# Can't change URLs
|
46
|
+
expect(location.href).toEqual(oldHref)
|
47
|
+
|
29
48
|
describe 'up.modal.visit', ->
|
30
49
|
|
31
50
|
it "brings its own scrollbar, padding the body on the right in order to prevent jumping", (done) ->
|
@@ -34,11 +53,11 @@ describe 'up.modal', ->
|
|
34
53
|
@respondWith('<div class="container">text</div>')
|
35
54
|
|
36
55
|
promise.then ->
|
37
|
-
|
38
56
|
$modal = $('.up-modal')
|
57
|
+
$viewport = $modal.find('.up-modal-viewport')
|
39
58
|
$body = $('body')
|
40
59
|
expect($modal).toExist()
|
41
|
-
expect($
|
60
|
+
expect($viewport.css('overflow-y')).toEqual('scroll')
|
42
61
|
expect($body.css('overflow-y')).toEqual('hidden')
|
43
62
|
expect(parseInt($body.css('padding-right'))).toBeAround(assumedScrollbarWidth, 10)
|
44
63
|
|
@@ -80,12 +99,13 @@ describe 'up.modal', ->
|
|
80
99
|
it 'returns the URL behind the modal overlay', (done) ->
|
81
100
|
up.history.replace('/foo')
|
82
101
|
expect(up.modal.coveredUrl()).toBeUndefined()
|
83
|
-
up.modal.visit('/bar', target: '.container')
|
102
|
+
visitPromise = up.modal.visit('/bar', target: '.container')
|
84
103
|
@respondWith('<div class="container">text</div>')
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
104
|
+
visitPromise.then ->
|
105
|
+
expect(up.modal.coveredUrl()).toEndWith('/foo')
|
106
|
+
up.modal.close().then ->
|
107
|
+
expect(up.modal.coveredUrl()).toBeUndefined()
|
108
|
+
done()
|
89
109
|
|
90
110
|
|
91
111
|
describe 'up.modal.close', ->
|
@@ -104,7 +124,7 @@ describe 'up.modal', ->
|
|
104
124
|
|
105
125
|
beforeEach ->
|
106
126
|
@$link = affix('a[href="/path"][up-modal=".target"]')
|
107
|
-
@followSpy = up.modal.knife.mock('follow')
|
127
|
+
@followSpy = up.modal.knife.mock('follow').and.returnValue(u.resolvedPromise())
|
108
128
|
@defaultSpy = up.link.knife.mock('allowDefault').and.callFake((event) -> event.preventDefault())
|
109
129
|
|
110
130
|
it 'opens the clicked link in a modal', ->
|
@@ -253,13 +273,3 @@ describe 'up.modal', ->
|
|
253
273
|
@respondWith("<div class='popup-content'></div>")
|
254
274
|
expect($('.up-modal')).toExist()
|
255
275
|
expect($('.up-popup')).toExist()
|
256
|
-
|
257
|
-
describe 'when following links inside a modal', ->
|
258
|
-
|
259
|
-
it 'prefers to replace a selector within the modal', ->
|
260
|
-
|
261
|
-
it 'auto-closes the modal if a selector behind the modal gets replaced'
|
262
|
-
|
263
|
-
it "doesn't auto-close the modal if a selector behind the modal if the modal is sticky"
|
264
|
-
|
265
|
-
it "doesn't auto-close the modal if the new fragment is a popup"
|