unpoly-rails 0.23.0 → 0.24.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 +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"
|