unpoly-rails 0.37.0 → 0.50.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 +127 -25
- data/LICENSE +1 -1
- data/README_RAILS.md +4 -2
- data/Rakefile +6 -1
- data/dist/unpoly.js +3192 -2198
- data/dist/unpoly.min.js +4 -3
- data/lib/assets/javascripts/unpoly/browser.coffee +51 -63
- data/lib/assets/javascripts/unpoly/bus.coffee +58 -33
- data/lib/assets/javascripts/unpoly/classes/cache.coffee +117 -0
- data/lib/assets/javascripts/unpoly/{dom → classes}/extract_cascade.coffee +3 -3
- data/lib/assets/javascripts/unpoly/{dom → classes}/extract_plan.coffee +1 -1
- data/lib/assets/javascripts/unpoly/classes/field_observer.coffee +57 -0
- data/lib/assets/javascripts/unpoly/classes/follow_variant.coffee +52 -0
- data/lib/assets/javascripts/unpoly/classes/motion_tracker.coffee +95 -0
- data/lib/assets/javascripts/unpoly/classes/record.coffee +16 -0
- data/lib/assets/javascripts/unpoly/classes/request.coffee +228 -0
- data/lib/assets/javascripts/unpoly/classes/response.coffee +138 -0
- data/lib/assets/javascripts/unpoly/dom.coffee +151 -142
- data/lib/assets/javascripts/unpoly/feedback.coffee +67 -38
- data/lib/assets/javascripts/unpoly/form.coffee +156 -139
- data/lib/assets/javascripts/unpoly/history.coffee +22 -19
- data/lib/assets/javascripts/unpoly/layout.coffee +108 -90
- data/lib/assets/javascripts/unpoly/link.coffee +159 -158
- data/lib/assets/javascripts/unpoly/log.coffee +5 -5
- data/lib/assets/javascripts/unpoly/modal.coffee +93 -81
- data/lib/assets/javascripts/unpoly/motion.coffee +291 -250
- data/lib/assets/javascripts/unpoly/popup.coffee +67 -53
- data/lib/assets/javascripts/unpoly/protocol.coffee +67 -16
- data/lib/assets/javascripts/unpoly/proxy.coffee +282 -211
- data/lib/assets/javascripts/unpoly/rails.coffee +3 -14
- data/lib/assets/javascripts/unpoly/syntax.coffee +54 -49
- data/lib/assets/javascripts/unpoly/tooltip.coffee +18 -25
- data/lib/assets/javascripts/unpoly/util.coffee +236 -477
- data/lib/assets/javascripts/unpoly.coffee +1 -1
- data/lib/unpoly/rails/inspector.rb +67 -22
- data/lib/unpoly/rails/version.rb +1 -1
- data/package.json +1 -1
- data/spec_app/Gemfile.lock +13 -13
- data/spec_app/app/assets/javascripts/integration_test.coffee +1 -0
- data/spec_app/app/assets/javascripts/jasmine_specs.coffee +1 -1
- data/spec_app/app/assets/stylesheets/jasmine_specs.sass +10 -0
- data/spec_app/app/controllers/binding_test_controller.rb +19 -2
- data/spec_app/app/controllers/method_test_controller.rb +16 -0
- data/spec_app/app/views/layouts/jasmine_rails/spec_runner.html.erb +20 -0
- data/spec_app/app/views/method_test/form_target.erb +17 -0
- data/spec_app/app/views/method_test/page1.erb +11 -0
- data/spec_app/app/views/method_test/page2.erb +6 -0
- data/spec_app/app/views/pages/start.erb +33 -19
- data/spec_app/config/initializers/assets.rb +5 -0
- data/spec_app/config/routes.rb +3 -0
- data/spec_app/spec/controllers/binding_test_controller_spec.rb +82 -27
- data/spec_app/spec/javascripts/helpers/agent_detector.coffee +17 -0
- data/spec_app/spec/javascripts/helpers/async_sequence.js.coffee +102 -0
- data/spec_app/spec/javascripts/helpers/last_request.js.coffee +1 -1
- data/spec_app/spec/javascripts/helpers/mock_ajax.js.coffee +5 -2
- data/spec_app/spec/javascripts/helpers/promise_state.js +18 -0
- data/spec_app/spec/javascripts/helpers/protect_jasmine_runner.coffee +9 -0
- data/spec_app/spec/javascripts/helpers/reset_history.js.coffee +22 -0
- data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +11 -3
- data/spec_app/spec/javascripts/helpers/show_lib_versions.coffee +10 -0
- data/spec_app/spec/javascripts/helpers/to_be_error.coffee +5 -0
- data/spec_app/spec/javascripts/helpers/to_match_url.coffee +13 -0
- data/spec_app/spec/javascripts/helpers/trigger.js.coffee +13 -6
- data/spec_app/spec/javascripts/up/browser_spec.js.coffee +92 -33
- data/spec_app/spec/javascripts/up/bus_spec.js.coffee +64 -15
- data/spec_app/spec/javascripts/up/classes/.keep +0 -0
- data/spec_app/spec/javascripts/up/classes/cache_spec.js.coffee +1 -0
- data/spec_app/spec/javascripts/up/dom_spec.js.coffee +759 -551
- data/spec_app/spec/javascripts/up/feedback_spec.js.coffee +155 -82
- data/spec_app/spec/javascripts/up/form_spec.js.coffee +490 -349
- data/spec_app/spec/javascripts/up/history_spec.js.coffee +226 -179
- data/spec_app/spec/javascripts/up/layout_spec.js.coffee +253 -185
- data/spec_app/spec/javascripts/up/link_spec.js.coffee +416 -270
- data/spec_app/spec/javascripts/up/modal_spec.js.coffee +459 -330
- data/spec_app/spec/javascripts/up/motion_spec.js.coffee +198 -153
- data/spec_app/spec/javascripts/up/namespace_spec.js.coffee +9 -0
- data/spec_app/spec/javascripts/up/popup_spec.js.coffee +240 -175
- data/spec_app/spec/javascripts/up/protocol_spec.js.coffee +38 -0
- data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +777 -303
- data/spec_app/spec/javascripts/up/rails_spec.js.coffee +24 -8
- data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +40 -23
- data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +80 -66
- data/spec_app/spec/javascripts/up/util_spec.js.coffee +227 -201
- data/spec_app/vendor/asset-libs/es6-promise-4.1.6/es6-promise.auto.js +1159 -0
- metadata +30 -7
- data/spec_app/spec/javascripts/helpers/reset_path.js.coffee +0 -7
- data/spec_app/spec/javascripts/helpers/to_equal_url.coffee +0 -11
@@ -21,7 +21,7 @@ describe 'up.popup', ->
|
|
21
21
|
afterEach ->
|
22
22
|
@restoreBodyHeight()
|
23
23
|
|
24
|
-
it "loads this link's destination in a popup positioned under the given link", ->
|
24
|
+
it "loads this link's destination in a popup positioned under the given link", asyncSpec (next) ->
|
25
25
|
$container = affix('.container')
|
26
26
|
$container.css
|
27
27
|
position: 'absolute'
|
@@ -32,25 +32,33 @@ describe 'up.popup', ->
|
|
32
32
|
|
33
33
|
up.popup.attach($link)
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
35
|
+
next =>
|
36
|
+
expect(@lastRequest().url).toMatch /\/path\/to$/
|
37
|
+
@respondWith """
|
38
|
+
<div class="before">new-before</div>
|
39
|
+
<div class="middle">new-middle</div>
|
40
|
+
<div class="after">new-after</div>
|
41
|
+
"""
|
42
|
+
|
43
|
+
next =>
|
44
|
+
$popup = $('.up-popup')
|
45
|
+
expect($popup).toExist()
|
46
|
+
expect($popup.find('.middle')).toHaveText('new-middle')
|
47
|
+
expect($popup.find('.before')).not.toExist()
|
48
|
+
expect($popup.find('.after')).not.toExist()
|
49
|
+
expect($popup.css('position')).toEqual('absolute')
|
50
|
+
expect($popup).toSitBelow($link)
|
51
|
+
|
52
|
+
it 'always makes a request for the given selector, and does not "improve" the selector with a fallback', asyncSpec (next) ->
|
53
|
+
$container = affix('.container')
|
54
|
+
$link = $container.affix('a[href="/path/to"][up-popup=".content"]').text('link')
|
55
|
+
up.popup.attach($link)
|
56
|
+
next =>
|
57
|
+
expect(jasmine.Ajax.requests.count()).toEqual(1)
|
58
|
+
headers = @lastRequest().requestHeaders
|
59
|
+
expect(headers['X-Up-Target']).toEqual('.content')
|
52
60
|
|
53
|
-
it 'gives the popup { position: "fixed" } if the given link is fixed', ->
|
61
|
+
it 'gives the popup { position: "fixed" } if the given link is fixed', asyncSpec (next) ->
|
54
62
|
# Let's test the harder case where the document is scrolled
|
55
63
|
up.layout.scroll(document, 50)
|
56
64
|
$container = affix('.container')
|
@@ -61,31 +69,41 @@ describe 'up.popup', ->
|
|
61
69
|
$link = $container.affix('a[href="/path/to"][up-popup=".content"]').text('link')
|
62
70
|
|
63
71
|
up.popup.attach($link)
|
64
|
-
@respondWith('<div class="content">popup-content</div>')
|
65
|
-
$popup = $('.up-popup')
|
66
|
-
expect($popup.css('position')).toEqual('fixed')
|
67
72
|
|
68
|
-
|
73
|
+
next =>
|
74
|
+
@respondWith('<div class="content">popup-content</div>')
|
75
|
+
|
76
|
+
next =>
|
77
|
+
$popup = $('.up-popup')
|
78
|
+
expect($popup.css('position')).toEqual('fixed')
|
79
|
+
expect($popup).toSitBelow($link)
|
69
80
|
|
70
|
-
it '
|
81
|
+
it 'never resolves the open() promise and shows no error if close() was called before the response was received', asyncSpec (next) ->
|
71
82
|
$span = affix('span')
|
72
|
-
up.popup.attach($span, url: '/foo', target: '.container')
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
83
|
+
openPromise = up.popup.attach($span, url: '/foo', target: '.container')
|
84
|
+
|
85
|
+
next =>
|
86
|
+
up.popup.close()
|
87
|
+
|
88
|
+
next =>
|
89
|
+
respond = => @respondWith('<div class="container">text</div>')
|
90
|
+
expect(respond).not.toThrowError()
|
91
|
+
|
92
|
+
next.await =>
|
93
|
+
expect($('.up-toast')).not.toExist()
|
94
|
+
promise = promiseState(openPromise)
|
95
|
+
promise.then (result) => expect(result.state).toEqual('pending')
|
77
96
|
|
78
97
|
describe 'with { html } option', ->
|
79
98
|
|
80
|
-
it 'extracts the selector from the given HTML string', (
|
99
|
+
it 'extracts the selector from the given HTML string', asyncSpec (next) ->
|
81
100
|
$span = affix('span')
|
82
|
-
up.popup.attach($span, target: '.container', html: "<div class='container'>container contents</div>")
|
83
|
-
|
84
|
-
done()
|
101
|
+
next.await up.popup.attach($span, target: '.container', html: "<div class='container'>container contents</div>")
|
102
|
+
next => expect($('.up-popup')).toHaveText('container contents')
|
85
103
|
|
86
104
|
describe 'opening a popup while another modal is open', ->
|
87
105
|
|
88
|
-
it 'closes the current popup and wait for its close animation to finish before starting the open animation of a second popup', (
|
106
|
+
it 'closes the current popup and wait for its close animation to finish before starting the open animation of a second popup', asyncSpec (next) ->
|
89
107
|
$span = affix('span')
|
90
108
|
up.popup.config.openAnimation = 'fade-in'
|
91
109
|
up.popup.config.openDuration = 5
|
@@ -98,11 +116,12 @@ describe 'up.popup', ->
|
|
98
116
|
|
99
117
|
up.popup.attach($span, { target: '.target', html: '<div class="target">response1</div>' })
|
100
118
|
|
101
|
-
|
102
|
-
|
103
|
-
|
119
|
+
next =>
|
120
|
+
# First popup is starting opening animation
|
121
|
+
expect(events).toEqual ['up:popup:open']
|
122
|
+
expect($('.target')).toHaveText('response1')
|
104
123
|
|
105
|
-
|
124
|
+
next.after 80, ->
|
106
125
|
# First popup has completed opening animation
|
107
126
|
expect(events).toEqual ['up:popup:open', 'up:popup:opened']
|
108
127
|
expect($('.target')).toHaveText('response1')
|
@@ -110,35 +129,36 @@ describe 'up.popup', ->
|
|
110
129
|
# We open another popup, which will cause the first modal to start closing
|
111
130
|
up.popup.attach($span, { target: '.target', html: '<div class="target">response2</div>' })
|
112
131
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
expect($('.target')).toHaveText('response1')
|
118
|
-
|
119
|
-
u.setTimer 200, ->
|
120
|
-
|
121
|
-
# First popup has finished closing, second popup has finished opening.
|
122
|
-
expect(events).toEqual ['up:popup:open', 'up:popup:opened', 'up:popup:close', 'up:popup:closed', 'up:popup:open', 'up:popup:opened']
|
123
|
-
expect($('.target')).toHaveText('response2')
|
132
|
+
next.after 20, ->
|
133
|
+
# Second popup is still waiting for first popup's closing animation to finish.
|
134
|
+
expect(events).toEqual ['up:popup:open', 'up:popup:opened', 'up:popup:close']
|
135
|
+
expect($('.target')).toHaveText('response1')
|
124
136
|
|
125
|
-
|
137
|
+
next.after 200, ->
|
138
|
+
# First popup has finished closing, second popup has finished opening.
|
139
|
+
expect(events).toEqual ['up:popup:open', 'up:popup:opened', 'up:popup:close', 'up:popup:closed', 'up:popup:open', 'up:popup:opened']
|
140
|
+
expect($('.target')).toHaveText('response2')
|
126
141
|
|
127
142
|
describe 'up.popup.coveredUrl', ->
|
128
143
|
|
129
144
|
describeCapability 'canPushState', ->
|
130
145
|
|
131
|
-
it 'returns the URL behind the popup', (
|
146
|
+
it 'returns the URL behind the popup', asyncSpec (next) ->
|
147
|
+
up.history.config.enabled = true
|
132
148
|
up.history.replace('/foo')
|
133
149
|
expect(up.popup.coveredUrl()).toBeMissing()
|
134
150
|
|
135
151
|
$popupLink = affix('a[href="/bar"][up-popup=".container"][up-history="true"]')
|
136
152
|
Trigger.clickSequence($popupLink)
|
137
|
-
|
138
|
-
|
139
|
-
|
153
|
+
|
154
|
+
next =>
|
155
|
+
@respondWith('<div class="container">text</div>')
|
156
|
+
expect(up.popup.coveredUrl()).toMatchUrl('/foo')
|
157
|
+
|
158
|
+
next.await up.popup.close()
|
159
|
+
|
160
|
+
next =>
|
140
161
|
expect(up.popup.coveredUrl()).toBeMissing()
|
141
|
-
done()
|
142
162
|
|
143
163
|
describe 'up.popup.close', ->
|
144
164
|
|
@@ -155,38 +175,37 @@ describe 'up.popup', ->
|
|
155
175
|
beforeEach ->
|
156
176
|
@stubAttach = =>
|
157
177
|
@$link = affix('a[href="/path"][up-popup=".target"]')
|
158
|
-
@attachSpy = up.popup.knife.mock('attachAsap').and.returnValue(
|
159
|
-
@defaultSpy = up.link
|
178
|
+
@attachSpy = up.popup.knife.mock('attachAsap').and.returnValue(Promise.resolve())
|
179
|
+
@defaultSpy = spyOn(up.link, 'allowDefault').and.callFake((event) -> event.preventDefault())
|
160
180
|
|
161
|
-
it 'opens the clicked link in a popup', ->
|
181
|
+
it 'opens the clicked link in a popup', asyncSpec (next) ->
|
162
182
|
@stubAttach()
|
163
183
|
Trigger.click(@$link)
|
164
|
-
expect(@attachSpy).toHaveBeenCalledWith(@$link)
|
184
|
+
next => expect(@attachSpy).toHaveBeenCalledWith(@$link, {})
|
165
185
|
|
166
186
|
# IE does not call JavaScript and always performs the default action on right clicks
|
167
|
-
unless
|
168
|
-
it 'does nothing if the right mouse button is used', ->
|
187
|
+
unless AgentDetector.isIE() || AgentDetector.isEdge()
|
188
|
+
it 'does nothing if the right mouse button is used', asyncSpec (next) ->
|
169
189
|
@stubAttach()
|
170
190
|
Trigger.click(@$link, button: 2)
|
171
|
-
expect(@attachSpy).not.toHaveBeenCalled()
|
191
|
+
next => expect(@attachSpy).not.toHaveBeenCalled()
|
172
192
|
|
173
|
-
it 'does nothing if shift is pressed during the click', ->
|
193
|
+
it 'does nothing if shift is pressed during the click', asyncSpec (next) ->
|
174
194
|
@stubAttach()
|
175
195
|
Trigger.click(@$link, shiftKey: true)
|
176
|
-
expect(@attachSpy).not.toHaveBeenCalled()
|
196
|
+
next => expect(@attachSpy).not.toHaveBeenCalled()
|
177
197
|
|
178
|
-
it 'does nothing if ctrl is pressed during the click', ->
|
198
|
+
it 'does nothing if ctrl is pressed during the click', asyncSpec (next) ->
|
179
199
|
@stubAttach()
|
180
200
|
Trigger.click(@$link, ctrlKey: true)
|
181
|
-
expect(@attachSpy).not.toHaveBeenCalled()
|
201
|
+
next => expect(@attachSpy).not.toHaveBeenCalled()
|
182
202
|
|
183
|
-
it 'does nothing if meta is pressed during the click', ->
|
203
|
+
it 'does nothing if meta is pressed during the click', asyncSpec (next) ->
|
184
204
|
@stubAttach()
|
185
205
|
Trigger.click(@$link, metaKey: true)
|
186
|
-
expect(@attachSpy).not.toHaveBeenCalled()
|
187
|
-
|
188
|
-
it 'closes an existing popup before opening the new popup', ->
|
206
|
+
next => expect(@attachSpy).not.toHaveBeenCalled()
|
189
207
|
|
208
|
+
it 'closes an existing popup before opening the new popup', asyncSpec (next) ->
|
190
209
|
up.popup.config.openDuration = 0
|
191
210
|
up.popup.config.closeDuration = 0
|
192
211
|
|
@@ -198,15 +217,21 @@ describe 'up.popup', ->
|
|
198
217
|
up.on event, -> events.push(event)
|
199
218
|
|
200
219
|
Trigger.click($link1)
|
201
|
-
expect(events).toEqual ['up:popup:open']
|
202
|
-
@respondWith('<div class="target">text1</div>')
|
203
|
-
expect(events).toEqual ['up:popup:open', 'up:popup:opened']
|
204
220
|
|
205
|
-
|
206
|
-
|
207
|
-
|
221
|
+
next =>
|
222
|
+
expect(events).toEqual ['up:popup:open']
|
223
|
+
@respondWith('<div class="target">text1</div>')
|
224
|
+
|
225
|
+
next =>
|
226
|
+
expect(events).toEqual ['up:popup:open', 'up:popup:opened']
|
227
|
+
Trigger.click($link2)
|
228
|
+
|
229
|
+
next =>
|
230
|
+
expect(events).toEqual ['up:popup:open', 'up:popup:opened', 'up:popup:close', 'up:popup:closed', 'up:popup:open']
|
231
|
+
@respondWith('<div class="target">text1</div>')
|
208
232
|
|
209
|
-
|
233
|
+
next =>
|
234
|
+
expect(events).toEqual ['up:popup:open', 'up:popup:opened', 'up:popup:close', 'up:popup:closed', 'up:popup:open', 'up:popup:opened']
|
210
235
|
|
211
236
|
|
212
237
|
describe 'with [up-instant] modifier', ->
|
@@ -215,42 +240,44 @@ describe 'up.popup', ->
|
|
215
240
|
@stubAttach()
|
216
241
|
@$link.attr('up-instant', '')
|
217
242
|
|
218
|
-
it 'opens the modal on mousedown (instead of on click)', ->
|
243
|
+
it 'opens the modal on mousedown (instead of on click)', asyncSpec (next) ->
|
219
244
|
Trigger.mousedown(@$link)
|
220
|
-
expect(@attachSpy.calls.mostRecent().args[0]).toEqual(@$link)
|
245
|
+
next => expect(@attachSpy.calls.mostRecent().args[0]).toEqual(@$link)
|
221
246
|
|
222
|
-
it 'does nothing on mouseup', ->
|
247
|
+
it 'does nothing on mouseup', asyncSpec (next) ->
|
223
248
|
Trigger.mouseup(@$link)
|
224
|
-
expect(@attachSpy).not.toHaveBeenCalled()
|
249
|
+
next => expect(@attachSpy).not.toHaveBeenCalled()
|
225
250
|
|
226
|
-
it 'does nothing on click', ->
|
251
|
+
it 'does nothing on click', asyncSpec (next) ->
|
227
252
|
Trigger.click(@$link)
|
228
|
-
expect(@attachSpy).not.toHaveBeenCalled()
|
253
|
+
next => expect(@attachSpy).not.toHaveBeenCalled()
|
229
254
|
|
230
255
|
# IE does not call JavaScript and always performs the default action on right clicks
|
231
|
-
unless
|
232
|
-
it 'does nothing if the right mouse button is pressed down', ->
|
256
|
+
unless AgentDetector.isIE() || AgentDetector.isEdge()
|
257
|
+
it 'does nothing if the right mouse button is pressed down', asyncSpec (next) ->
|
233
258
|
Trigger.mousedown(@$link, button: 2)
|
234
|
-
expect(@attachSpy).not.toHaveBeenCalled()
|
259
|
+
next => expect(@attachSpy).not.toHaveBeenCalled()
|
235
260
|
|
236
|
-
it 'does nothing if shift is pressed during mousedown', ->
|
261
|
+
it 'does nothing if shift is pressed during mousedown', asyncSpec (next) ->
|
237
262
|
Trigger.mousedown(@$link, shiftKey: true)
|
238
|
-
expect(@attachSpy).not.toHaveBeenCalled()
|
263
|
+
next => expect(@attachSpy).not.toHaveBeenCalled()
|
239
264
|
|
240
|
-
it 'does nothing if ctrl is pressed during mousedown', ->
|
265
|
+
it 'does nothing if ctrl is pressed during mousedown', asyncSpec (next) ->
|
241
266
|
Trigger.mousedown(@$link, ctrlKey: true)
|
242
|
-
expect(@attachSpy).not.toHaveBeenCalled()
|
267
|
+
next => expect(@attachSpy).not.toHaveBeenCalled()
|
243
268
|
|
244
|
-
it 'does nothing if meta is pressed during mousedown', ->
|
269
|
+
it 'does nothing if meta is pressed during mousedown', asyncSpec (next) ->
|
245
270
|
Trigger.mousedown(@$link, metaKey: true)
|
246
|
-
expect(@attachSpy).not.toHaveBeenCalled()
|
271
|
+
next => expect(@attachSpy).not.toHaveBeenCalled()
|
247
272
|
|
248
273
|
describe 'with [up-method] modifier', ->
|
249
274
|
|
250
|
-
it 'honours the given method', ->
|
275
|
+
it 'honours the given method', asyncSpec (next) ->
|
251
276
|
$link = affix('a[href="/path"][up-popup=".target"][up-method="post"]')
|
252
277
|
Trigger.click($link)
|
253
|
-
|
278
|
+
|
279
|
+
next =>
|
280
|
+
expect(@lastRequest().method).toEqual 'POST'
|
254
281
|
|
255
282
|
describe '[up-close]', ->
|
256
283
|
|
@@ -263,70 +290,84 @@ describe 'up.popup', ->
|
|
263
290
|
|
264
291
|
describe 'when clicked inside a popup', ->
|
265
292
|
|
266
|
-
it 'closes the open popup and halts the event chain', (
|
293
|
+
it 'closes the open popup and halts the event chain', asyncSpec (next) ->
|
267
294
|
$opener = affix('a')
|
268
295
|
up.popup.attach($opener, html: '<div class="target">text</div>', target: '.target')
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
296
|
+
|
297
|
+
next =>
|
298
|
+
$popup = affix('.up-popup')
|
299
|
+
$closer = $popup.affix('a[up-close]') # link is within the popup
|
300
|
+
up.hello($closer)
|
301
|
+
Trigger.clickSequence($closer)
|
302
|
+
|
303
|
+
next =>
|
274
304
|
expect(up.popup.isOpen()).toBe(false)
|
275
305
|
expect(backgroundClicked).not.toHaveBeenCalled()
|
276
|
-
done()
|
277
306
|
|
278
307
|
describe 'when clicked inside a popup when a modal is open', ->
|
279
308
|
|
280
|
-
it 'closes the popup, but not the modal', (
|
281
|
-
|
309
|
+
it 'closes the popup, but not the modal', asyncSpec (next) ->
|
282
310
|
up.modal.extract '.modalee', '<div class="modalee"></div>'
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
311
|
+
|
312
|
+
next =>
|
313
|
+
$modalee = $('.up-modal .modalee')
|
314
|
+
$opener = $modalee.affix('a')
|
315
|
+
up.popup.attach($opener, html: '<div class="popupee">text</div>', target: '.popupee')
|
316
|
+
|
317
|
+
next =>
|
318
|
+
$popupee = $('.up-popup .popupee')
|
319
|
+
$closer = $popupee.affix('a[up-close]') # link is within the popup
|
320
|
+
up.hello($closer)
|
321
|
+
Trigger.clickSequence($closer)
|
322
|
+
|
323
|
+
next =>
|
291
324
|
expect(up.popup.isOpen()).toBe(false)
|
292
325
|
expect(up.modal.isOpen()).toBe(true)
|
293
326
|
expect(backgroundClicked).not.toHaveBeenCalled()
|
294
|
-
done()
|
295
327
|
|
296
328
|
describe 'when no popup is open', ->
|
297
329
|
|
298
|
-
it 'does nothing and allows the event chain to continue', (
|
330
|
+
it 'does nothing and allows the event chain to continue', asyncSpec (next) ->
|
299
331
|
$link = affix('a[up-close]') # link is outside the popup
|
300
332
|
up.hello($link)
|
301
333
|
Trigger.clickSequence($link)
|
302
|
-
|
334
|
+
|
335
|
+
next =>
|
303
336
|
expect(up.popup.isOpen()).toBe(false)
|
304
337
|
expect(backgroundClicked).toHaveBeenCalled()
|
305
|
-
done()
|
306
338
|
|
307
339
|
describe 'when replacing content', ->
|
308
340
|
|
309
341
|
beforeEach ->
|
310
342
|
up.motion.config.enabled = false
|
311
343
|
|
312
|
-
it 'prefers to replace a selector within the popup', ->
|
344
|
+
it 'prefers to replace a selector within the popup', asyncSpec (next) ->
|
313
345
|
$outside = affix('.foo').text('old outside')
|
314
346
|
$link = affix('.link')
|
315
347
|
up.popup.attach($link, target: '.foo', html: "<div class='foo'>old inside</div>")
|
316
|
-
up.extract('.foo', "<div class='foo'>new text</div>")
|
317
|
-
expect($outside).toBeInDOM()
|
318
|
-
expect($outside).toHaveText('old outside')
|
319
|
-
expect($('.up-popup')).toHaveText('new text')
|
320
348
|
|
321
|
-
|
349
|
+
next =>
|
350
|
+
up.extract('.foo', "<div class='foo'>new text</div>")
|
351
|
+
|
352
|
+
next =>
|
353
|
+
expect($outside).toBeInDOM()
|
354
|
+
expect($outside).toHaveText('old outside')
|
355
|
+
expect($('.up-popup')).toHaveText('new text')
|
356
|
+
|
357
|
+
it 'auto-closes the popup when a replacement from inside the popup affects a selector behind the popup', asyncSpec (next) ->
|
322
358
|
affix('.outside').text('old outside')
|
323
359
|
$link = affix('.link')
|
324
360
|
up.popup.attach($link, target: '.inside', html: "<div class='inside'>old inside</div>")
|
325
|
-
up.extract('.outside', "<div class='outside'>new outside</div>", origin: $('.inside'))
|
326
|
-
expect($('.outside')).toHaveText('new outside')
|
327
|
-
expect($('.up-popup')).not.toExist()
|
328
361
|
|
329
|
-
|
362
|
+
next =>
|
363
|
+
up.extract('.outside', "<div class='outside'>new outside</div>", origin: $('.inside'))
|
364
|
+
|
365
|
+
next =>
|
366
|
+
expect($('.outside')).toHaveText('new outside')
|
367
|
+
expect($('.up-popup')).not.toExist()
|
368
|
+
|
369
|
+
it 'does not restore the covered URL when auto-closing (since it would override the URL from the triggering update)', asyncSpec (next) ->
|
370
|
+
up.history.config.enabled = true
|
330
371
|
up.motion.config.enabled = true
|
331
372
|
up.popup.config.openDuration = 0
|
332
373
|
up.popup.config.closeDuration = 20
|
@@ -334,108 +375,132 @@ describe 'up.popup', ->
|
|
334
375
|
|
335
376
|
affix('.outside').text('old outside')
|
336
377
|
$link = affix('.link')
|
337
|
-
|
338
|
-
|
378
|
+
up.popup.attach($link, url: '/path', target: '.inside')
|
379
|
+
|
380
|
+
next =>
|
381
|
+
@respondWith("<div class='inside'>old inside</div>") # Populate pop-up
|
339
382
|
|
340
|
-
|
383
|
+
next =>
|
341
384
|
up.extract('.outside', "<div class='outside'>new outside</div>",
|
342
385
|
origin: $('.inside'), history: '/new-location') # Provoke auto-close
|
343
386
|
|
344
|
-
|
345
|
-
|
346
|
-
done()
|
387
|
+
next =>
|
388
|
+
expect(location.href).toMatchUrl '/new-location'
|
347
389
|
|
348
|
-
it 'does not auto-close the popup when a replacement from inside the popup affects a selector inside the popup', ->
|
390
|
+
it 'does not auto-close the popup when a replacement from inside the popup affects a selector inside the popup', asyncSpec (next) ->
|
349
391
|
affix('.outside').text('old outside')
|
350
392
|
$link = affix('.link')
|
351
|
-
up.popup.attach($link, target: '.inside')
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
393
|
+
up.popup.attach($link, html: "<div class='inside'>old inside</div>", target: '.inside')
|
394
|
+
|
395
|
+
next =>
|
396
|
+
up.extract('.inside', "<div class='inside'>new inside</div>", origin: $('.inside'))
|
397
|
+
|
398
|
+
next =>
|
399
|
+
expect($('.inside')).toHaveText('new inside')
|
400
|
+
expect($('.up-popup')).toExist()
|
356
401
|
|
357
|
-
it 'does not auto-close the popup when a replacement from outside the popup affects a selector outside the popup', ->
|
402
|
+
it 'does not auto-close the popup when a replacement from outside the popup affects a selector outside the popup', asyncSpec (next) ->
|
358
403
|
affix('.outside').text('old outside')
|
359
404
|
$link = affix('.link')
|
360
405
|
up.popup.attach($link, target: '.inside', html: "<div class='inside'>old inside</div>")
|
361
|
-
up.extract('.outside', "<div class='outside'>new outside</div>", origin: $('.outside'))
|
362
|
-
expect($('.outside')).toHaveText('new outside')
|
363
|
-
expect($('.up-popup')).toExist()
|
364
406
|
|
365
|
-
|
407
|
+
next =>
|
408
|
+
up.extract('.outside', "<div class='outside'>new outside</div>", origin: $('.outside'))
|
409
|
+
|
410
|
+
next =>
|
411
|
+
expect($('.outside')).toHaveText('new outside')
|
412
|
+
expect($('.up-popup')).toExist()
|
413
|
+
|
414
|
+
it 'does not auto-close the popup when a replacement from outside the popup affects a selector inside the popup', asyncSpec (next) ->
|
366
415
|
affix('.outside').text('old outside')
|
367
416
|
$link = affix('.link')
|
368
417
|
up.popup.attach($link, target: '.inside', html: "<div class='inside'>old inside</div>")
|
369
|
-
|
370
|
-
|
371
|
-
|
418
|
+
|
419
|
+
next =>
|
420
|
+
up.extract('.inside', "<div class='inside'>new inside</div>", origin: $('.outside'))
|
421
|
+
|
422
|
+
next =>
|
423
|
+
expect($('.inside')).toHaveText('new inside')
|
424
|
+
expect($('.up-popup')).toExist()
|
372
425
|
|
373
426
|
describe 'when clicking on the body', ->
|
374
427
|
|
375
428
|
beforeEach ->
|
376
429
|
up.motion.config.enabled = false
|
377
430
|
|
378
|
-
it 'closes the popup', (
|
431
|
+
it 'closes the popup', asyncSpec (next) ->
|
379
432
|
affix('.outside').text('old outside')
|
380
433
|
$link = affix('.link')
|
381
434
|
up.popup.attach($link, target: '.inside', html: "<div class='inside'>inside</div>")
|
382
|
-
|
383
|
-
|
384
|
-
|
435
|
+
|
436
|
+
next =>
|
437
|
+
expect(up.popup.isOpen()).toBe(true)
|
438
|
+
Trigger.clickSequence($('body'))
|
439
|
+
|
440
|
+
next =>
|
385
441
|
expect(up.popup.isOpen()).toBe(false)
|
386
|
-
done()
|
387
442
|
|
388
|
-
it 'closes the popup when a an [up-instant] link removes its parent (and thus a click event never bubbles up to the document)', (
|
443
|
+
it 'closes the popup when a an [up-instant] link removes its parent (and thus a click event never bubbles up to the document)', asyncSpec (next) ->
|
389
444
|
$parent = affix('.parent')
|
390
445
|
$parentReplacingLink = $parent.affix('a[href="/foo"][up-target=".parent"][up-instant]')
|
391
446
|
$popupOpener = affix('.link')
|
392
447
|
up.popup.attach($popupOpener, target: '.inside', html: "<div class='inside'>inside</div>")
|
393
|
-
|
394
|
-
|
395
|
-
|
448
|
+
|
449
|
+
next =>
|
450
|
+
expect(up.popup.isOpen()).toBe(true)
|
451
|
+
Trigger.clickSequence($parentReplacingLink)
|
452
|
+
|
453
|
+
next =>
|
396
454
|
expect(up.popup.isOpen()).toBe(false)
|
397
|
-
done()
|
398
455
|
|
399
|
-
it 'closes the popup when the user clicks on an [up-target] link outside the popup', (
|
456
|
+
it 'closes the popup when the user clicks on an [up-target] link outside the popup', asyncSpec (next) ->
|
400
457
|
$target = affix('.target')
|
401
458
|
$outsideLink = affix('a[href="/foo"][up-target=".target"]')
|
402
459
|
$popupOpener = affix('.link')
|
403
460
|
up.popup.attach($popupOpener, target: '.inside', html: "<div class='inside'>inside</div>")
|
404
|
-
|
405
|
-
|
406
|
-
|
461
|
+
|
462
|
+
next =>
|
463
|
+
expect(up.popup.isOpen()).toBe(true)
|
464
|
+
Trigger.clickSequence($outsideLink)
|
465
|
+
|
466
|
+
next =>
|
407
467
|
expect(up.popup.isOpen()).toBe(false)
|
408
|
-
done()
|
409
468
|
|
410
|
-
it 'closes the popup when the user clicks on an [up-instant] link outside the popup', (
|
469
|
+
it 'closes the popup when the user clicks on an [up-instant] link outside the popup', asyncSpec (next) ->
|
411
470
|
$target = affix('.target')
|
412
471
|
$outsideLink = affix('a[href="/foo"][up-target=".target"][up-instant]')
|
413
472
|
$popupOpener = affix('.link')
|
414
473
|
up.popup.attach($popupOpener, target: '.inside', html: "<div class='inside'>inside</div>")
|
415
|
-
|
416
|
-
|
417
|
-
|
474
|
+
|
475
|
+
next =>
|
476
|
+
expect(up.popup.isOpen()).toBe(true)
|
477
|
+
Trigger.clickSequence($outsideLink)
|
478
|
+
|
479
|
+
next =>
|
418
480
|
expect(up.popup.isOpen()).toBe(false)
|
419
|
-
done()
|
420
481
|
|
421
|
-
it 'does not close the popup if a link outside the popup is followed with the up.follow function (bugfix)', (
|
482
|
+
it 'does not close the popup if a link outside the popup is followed with the up.follow function (bugfix)', asyncSpec (next) ->
|
422
483
|
$target = affix('.target')
|
423
484
|
$outsideLink = affix('a[href="/foo"][up-target=".target"]')
|
424
485
|
$popupOpener = affix('.link')
|
425
486
|
up.popup.attach($popupOpener, target: '.inside', html: "<div class='inside'>inside</div>")
|
426
|
-
|
427
|
-
|
428
|
-
|
487
|
+
|
488
|
+
next =>
|
489
|
+
expect(up.popup.isOpen()).toBe(true)
|
490
|
+
up.follow($outsideLink)
|
491
|
+
|
492
|
+
next =>
|
429
493
|
expect(up.popup.isOpen()).toBe(true)
|
430
|
-
done()
|
431
494
|
|
432
|
-
it 'does not close the popup if a form outside the popup is followed with the up.submit function (bugfix)', (
|
495
|
+
it 'does not close the popup if a form outside the popup is followed with the up.submit function (bugfix)', asyncSpec (next) ->
|
433
496
|
$target = affix('.target')
|
434
497
|
$outsideForm = affix('form[action="/foo"][up-target=".target"]')
|
435
498
|
$popupOpener = affix('.link')
|
436
499
|
up.popup.attach($popupOpener, target: '.inside', html: "<div class='inside'>inside</div>")
|
437
|
-
|
438
|
-
|
439
|
-
|
500
|
+
|
501
|
+
next =>
|
502
|
+
expect(up.popup.isOpen()).toBe(true)
|
503
|
+
up.submit($outsideForm)
|
504
|
+
|
505
|
+
next =>
|
440
506
|
expect(up.popup.isOpen()).toBe(true)
|
441
|
-
done()
|