unpoly-rails 0.28.1 → 0.29.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.

Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +19 -1
  3. data/dist/unpoly.js +376 -259
  4. data/dist/unpoly.min.js +3 -3
  5. data/lib/assets/javascripts/unpoly/browser.js.coffee +2 -2
  6. data/lib/assets/javascripts/unpoly/bus.js.coffee +40 -13
  7. data/lib/assets/javascripts/unpoly/flow.js.coffee +9 -9
  8. data/lib/assets/javascripts/unpoly/form.js.coffee +18 -18
  9. data/lib/assets/javascripts/unpoly/history.js.coffee +1 -1
  10. data/lib/assets/javascripts/unpoly/layout.js.coffee +9 -9
  11. data/lib/assets/javascripts/unpoly/link.js.coffee +34 -24
  12. data/lib/assets/javascripts/unpoly/modal.js.coffee +38 -37
  13. data/lib/assets/javascripts/unpoly/motion.js.coffee +20 -23
  14. data/lib/assets/javascripts/unpoly/navigation.js.coffee +101 -37
  15. data/lib/assets/javascripts/unpoly/popup.js.coffee +24 -16
  16. data/lib/assets/javascripts/unpoly/proxy.js.coffee +3 -3
  17. data/lib/assets/javascripts/unpoly/syntax.js.coffee +29 -37
  18. data/lib/assets/javascripts/unpoly/tooltip.js.coffee +18 -9
  19. data/lib/assets/javascripts/unpoly/util.js.coffee +15 -7
  20. data/lib/unpoly/rails/version.rb +1 -1
  21. data/spec_app/Gemfile.lock +1 -1
  22. data/spec_app/spec/javascripts/helpers/trigger.js.coffee +6 -0
  23. data/spec_app/spec/javascripts/up/bus_spec.js.coffee +9 -8
  24. data/spec_app/spec/javascripts/up/form_spec.js.coffee +10 -10
  25. data/spec_app/spec/javascripts/up/link_spec.js.coffee +25 -20
  26. data/spec_app/spec/javascripts/up/modal_spec.js.coffee +53 -44
  27. data/spec_app/spec/javascripts/up/navigation_spec.js.coffee +8 -8
  28. data/spec_app/spec/javascripts/up/popup_spec.js.coffee +92 -44
  29. data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +46 -4
  30. metadata +2 -2
@@ -342,7 +342,7 @@ describe 'up.link', ->
342
342
  $form = affix('form[up-target]')
343
343
  up.hello($form)
344
344
  followSpy = up.link.knife.mock('follow').and.returnValue(u.resolvedPromise())
345
- $form.click()
345
+ Trigger.clickSequence($form)
346
346
  expect(followSpy).not.toHaveBeenCalled()
347
347
 
348
348
  describeCapability 'canPushState', ->
@@ -350,7 +350,7 @@ describe 'up.link', ->
350
350
  it 'adds a history entry', ->
351
351
  affix('.target')
352
352
  $link = affix('a[href="/path"][up-target=".target"]')
353
- $link.click()
353
+ Trigger.clickSequence($link)
354
354
  @respondWith('<div class="target">new text</div>')
355
355
  expect($('.target')).toHaveText('new text')
356
356
  expect(location.pathname).toEqual('/path')
@@ -358,35 +358,41 @@ describe 'up.link', ->
358
358
  it 'respects a X-Up-Location header that the server sends in case of a redirect', ->
359
359
  affix('.target')
360
360
  $link = affix('a[href="/path"][up-target=".target"]')
361
- $link.click()
361
+ Trigger.clickSequence($link)
362
362
  @respondWith
363
363
  responseText: '<div class="target">new text</div>'
364
364
  responseHeaders: { 'X-Up-Location': '/other/path' }
365
365
  expect($('.target')).toHaveText('new text')
366
366
  expect(location.pathname).toEqual('/other/path')
367
367
 
368
- it 'prefers to update a container in the same layer as the clicked link', ->
368
+ it 'prefers to update a container in the same layer as the clicked link', (done) ->
369
369
  up.motion.config.enabled = false
370
370
 
371
371
  $popupOpener = affix('a[href="/popup"]')
372
372
  up.popup.attach($popupOpener, html: "<div class='target'>old popup text</div>", target: '.target')
373
-
374
373
  affix('.document').affix('.target').text('old document text')
375
- $linkInDocument = affix('a[href="/foo"][up-target=".target"]')
376
- $linkInDocument.click()
377
374
 
378
- @respondWith '<div class="target">new text from document link</div>'
375
+ $linkInDocument = affix('a[href="/foo"][up-target=".target"]')
376
+ $linkInPopup = $('.up-popup').affix('a[href="/bar"][up-target=".target"]')
379
377
 
380
- expect($('.document .target')).toHaveText('new text from document link')
378
+ expect($('.document .target')).toHaveText('old document text')
381
379
  expect($('.up-popup .target')).toHaveText('old popup text')
382
380
 
383
- $linkInPopup = $('.up-popup').affix('a[href="/bar"][up-target=".target"]')
384
- $linkInPopup.click()
381
+ u.nextFrame =>
382
+
383
+ Trigger.clickSequence($linkInPopup)
385
384
 
386
- @respondWith '<div class="target">new text from popup link</div>'
385
+ u.nextFrame =>
386
+ @respondWith '<div class="target">new text from popup link</div>'
387
387
 
388
- expect($('.document .target')).toHaveText('new text from document link')
389
- expect($('.up-popup .target')).toHaveText('new text from popup link')
388
+ expect($('.document .target')).toHaveText('old document text')
389
+ expect($('.up-popup .target')).toHaveText('new text from popup link')
390
+ Trigger.clickSequence($linkInDocument)
391
+
392
+ u.nextFrame =>
393
+ @respondWith '<div class="target">new text from document link</div>'
394
+ expect($('.document .target')).toHaveText('new text from document link')
395
+ done()
390
396
 
391
397
 
392
398
  describe 'with [up-transition] modifier', ->
@@ -396,7 +402,7 @@ describe 'up.link', ->
396
402
  it 'morphs between the old and new target element', (done) ->
397
403
  affix('.target.old')
398
404
  $link = affix('a[href="/path"][up-target=".target"][up-transition="cross-fade"][up-duration="500"][up-easing="linear"]')
399
- $link.click()
405
+ Trigger.clickSequence($link)
400
406
  @respondWith '<div class="target new">new text</div>'
401
407
 
402
408
  $oldGhost = $('.target.old.up-ghost')
@@ -414,7 +420,7 @@ describe 'up.link', ->
414
420
  oldPathname = location.pathname
415
421
  affix('.target')
416
422
  $link = affix('a[href="/path"][up-target=".target"][up-history="false"]')
417
- $link.click()
423
+ Trigger.clickSequence($link)
418
424
  @respondWith
419
425
  responseText: '<div class="target">new text</div>'
420
426
  responseHeaders: { 'X-Up-Location': '/other/path' }
@@ -562,15 +568,14 @@ describe 'up.link', ->
562
568
  $area = affix('div[up-expand] a[href="/path"]')
563
569
  up.hello($area)
564
570
  spyOn(up, 'replace')
565
- $area.get(0).click()
571
+ Trigger.clickSequence($area)
566
572
  expect(up.replace).toHaveBeenCalled()
567
573
 
568
574
  it 'does not trigger multiple replaces when the user clicks on the expanded area of an up-instant link (bugfix)', ->
569
- $area = affix('div[up-expand] a[href="/path"][up-instant]')
575
+ $area = affix('div[up-expand] a[href="/path"][up-follow][up-instant]')
570
576
  up.hello($area)
571
577
  spyOn(up, 'replace')
572
- Trigger.mousedown($area)
573
- Trigger.click($area)
578
+ Trigger.clickSequence($area)
574
579
  expect(up.replace.calls.count()).toEqual(1)
575
580
 
576
581
  it 'does not add an up-follow attribute if the expanded link is [up-dash] with a selector (bugfix)', ->
@@ -420,66 +420,54 @@ describe 'up.modal', ->
420
420
 
421
421
  describe '[up-close]', ->
422
422
 
423
+ backgroundClicked = undefined
424
+
425
+ beforeEach ->
426
+ up.motion.config.enabled = false
427
+ backgroundClicked = jasmine.createSpy('background clicked')
428
+ up.on 'click', backgroundClicked
429
+
423
430
  describe 'when clicked inside a modal', ->
424
431
 
425
- it 'closes the open modal and prevents the default action', (done) ->
432
+ it 'closes the open modal and halts the event chain', (done) ->
426
433
  up.modal.extract('.target', '<div class="target"><a up-close>text</a></div>', animation: false)
427
434
  $link = $('.up-modal a[up-close]') # link is within the modal
428
- wasDefaultPrevented = false
429
- wasClosed = false
430
- up.on 'click', 'a[up-close]', (event) ->
431
- wasDefaultPrevented = event.isDefaultPrevented()
432
- true # the line above might return false and cancel propagation / prevent default
433
- up.on 'up:modal:close', ->
434
- wasClosed = true
435
- $link.click()
435
+ Trigger.clickSequence($link)
436
436
  u.nextFrame ->
437
- expect(wasClosed).toBe(true)
438
- expect(wasDefaultPrevented).toBe(true)
437
+ expect(up.modal.isOpen()).toBe(false)
438
+ expect(backgroundClicked).not.toHaveBeenCalled()
439
439
  done()
440
440
 
441
441
  describe 'when no modal is open', ->
442
442
 
443
- it 'does neither close the modal nor prevent the default action', ->
443
+ it 'does nothing and allows the event chain to continue', (done) ->
444
444
  $link = affix('a[up-close]') # link is outside the modal
445
445
  up.hello($link)
446
- wasDefaultPrevented = false
447
- wasClosed = false
448
- up.on 'click', 'a[up-close]', (event) ->
449
- wasDefaultPrevented = event.isDefaultPrevented()
450
- true # the line above might return false and cancel propagation / prevent default
451
- up.on 'up:modal:close', ->
452
- wasClosed = true
453
- $link.click()
454
- expect(wasClosed).toBe(false)
455
- expect(wasDefaultPrevented).toBe(false)
446
+ Trigger.clickSequence($link)
447
+ u.nextFrame ->
448
+ expect(backgroundClicked).toHaveBeenCalled()
449
+ done()
456
450
 
457
451
  describe 'template behavior', ->
458
452
 
459
453
  it 'closes the modal on close icon click', (done) ->
460
- wasClosed = false
461
454
  up.modal.extract('.modal', '<div class="modal">Modal content</div>', animation: false)
462
455
 
463
- closeIcon = $('.up-modal-close')
464
- up.on 'up:modal:close', ->
465
- wasClosed = true
456
+ $closeIcon = $('.up-modal-close')
466
457
 
467
- closeIcon.click()
458
+ Trigger.clickSequence($closeIcon)
468
459
  u.nextFrame ->
469
- expect(wasClosed).toBe(true)
460
+ expect(up.modal.isOpen()).toBe(false)
470
461
  done()
471
462
 
472
463
  it 'closes the modal on backdrop click', (done) ->
473
- wasClosed = false
474
464
  up.modal.extract('.modal', '<div class="modal">Modal content</div>', animation: false)
475
465
 
476
- backdrop = $('.up-modal-backdrop')
477
- up.on 'up:modal:close', ->
478
- wasClosed = true
466
+ $backdrop = $('.up-modal-backdrop')
479
467
 
480
- backdrop.click()
468
+ Trigger.clickSequence($backdrop)
481
469
  u.nextFrame ->
482
- expect(wasClosed).toBe(true)
470
+ expect(up.modal.isOpen()).toBe(false)
483
471
  done()
484
472
 
485
473
  it 'closes the modal when the user presses the escape key', (done) ->
@@ -503,28 +491,22 @@ describe 'up.modal', ->
503
491
  expect(modal).not.toContainElement('.up-modal-close')
504
492
 
505
493
  it 'does not close the modal on backdrop click', (done) ->
506
- wasClosed = false
507
494
  up.modal.extract('.modal', '<div class="modal">Modal content</div>', animation: false, closable: false)
508
495
 
509
- backdrop = $('.up-modal-backdrop')
510
- up.on 'up:modal:close', ->
511
- wasClosed = true
496
+ $backdrop = $('.up-modal-backdrop')
512
497
 
513
- backdrop.click()
498
+ Trigger.clickSequence($backdrop)
514
499
  u.nextFrame ->
515
- expect(wasClosed).toBe(false)
500
+ expect(up.modal.isOpen()).toBe(true)
516
501
  done()
517
502
 
518
503
  it 'does not close the modal when the user presses the escape key', (done) ->
519
- wasClosed = false
520
504
  up.modal.extract('.modal', '<div class="modal">Modal content</div>', animation: false, closable: false)
521
- up.on 'up:modal:close', ->
522
- wasClosed = true
523
505
 
524
506
  escapeEvent = $.Event('keydown', keyCode: 27)
525
507
  $('body').trigger(escapeEvent)
526
508
  u.nextFrame ->
527
- expect(wasClosed).toBe(false)
509
+ expect(up.modal.isOpen()).toBe(true)
528
510
  done()
529
511
 
530
512
  describe 'when replacing content', ->
@@ -597,3 +579,30 @@ describe 'up.modal', ->
597
579
  @respondWith("<div class='popup-content'></div>")
598
580
  expect($('.up-modal')).toExist()
599
581
  expect($('.up-popup')).toExist()
582
+
583
+ it 'does not close the modal when a clicked [up-target] link within the modal links to cached content (bugfix)', (done) ->
584
+
585
+ up.modal.extract '.content', """
586
+ <div class="content">
587
+ <a href="/foo" up-target=".content">link</a>
588
+ </div>
589
+ """
590
+ $link = $('.up-modal .content a')
591
+ expect($link).toExist()
592
+ whenPreloaded = up.proxy.preload($link)
593
+
594
+ @respondWith """
595
+ <div class="content">
596
+ new text
597
+ </div>
598
+ """
599
+
600
+ whenPreloaded.then ->
601
+
602
+ Trigger.clickSequence($link)
603
+
604
+ u.nextFrame ->
605
+ expect($('.up-modal')).toExist()
606
+ expect($('.up-modal .content')).toHaveText('new text')
607
+
608
+ done()
@@ -67,7 +67,7 @@ describe 'up.navigation', ->
67
67
  it 'marks a link as .up-current if it links to the current URL, but is missing a trailing slash', ->
68
68
  $link = affix('a[href="/foo"][up-target=".main"]')
69
69
  affix('.main')
70
- $link.click()
70
+ Trigger.clickSequence($link)
71
71
  @respondWith
72
72
  responseHeaders: { 'X-Up-Location': '/foo/' }
73
73
  responseText: '<div class="main">new-text</div>'
@@ -76,7 +76,7 @@ describe 'up.navigation', ->
76
76
  it 'marks a link as .up-current if it links to the current URL, but has an extra trailing slash', ->
77
77
  $link = affix('a[href="/foo/"][up-target=".main"]')
78
78
  affix('.main')
79
- $link.click()
79
+ Trigger.clickSequence($link)
80
80
  @respondWith
81
81
  responseHeaders: { 'X-Up-Location': '/foo' }
82
82
  responseText: '<div class="main">new-text</div>'
@@ -106,7 +106,7 @@ describe 'up.navigation', ->
106
106
  $popupLink = affix('a[href="/bar"][up-popup=".main"]')
107
107
  $unrelatedLink = affix('a[href="/baz]')
108
108
 
109
- $popupLink.click()
109
+ Trigger.clickSequence($popupLink)
110
110
  @respondWith('<div class="main">new-text</div>')
111
111
  expect($backgroundLink).toHaveClass('up-current')
112
112
  expect($popupLink).toHaveClass('up-current')
@@ -127,7 +127,7 @@ describe 'up.navigation', ->
127
127
  it 'marks clicked links as .up-active until the request finishes', ->
128
128
  $link = affix('a[href="/foo"][up-target=".main"]')
129
129
  affix('.main')
130
- $link.click()
130
+ Trigger.clickSequence($link)
131
131
  expect($link).toHaveClass('up-active')
132
132
  @respondWith('<div class="main">new-text</div>')
133
133
  expect($link).not.toHaveClass('up-active')
@@ -145,7 +145,7 @@ describe 'up.navigation', ->
145
145
  up.hello($area)
146
146
  $link = $area.find('a')
147
147
  affix('.main')
148
- $link.click()
148
+ Trigger.clickSequence($link)
149
149
  expect($link).not.toHaveClass('up-active')
150
150
  expect($area).toHaveClass('up-active')
151
151
  @respondWith('<div class="main">new-text</div>')
@@ -154,7 +154,7 @@ describe 'up.navigation', ->
154
154
  it 'marks clicked modal openers as .up-active while the modal is loading', ->
155
155
  $link = affix('a[href="/foo"][up-modal=".main"]')
156
156
  affix('.main')
157
- $link.click()
157
+ Trigger.clickSequence($link)
158
158
  expect($link).toHaveClass('up-active')
159
159
  @respondWith('<div class="main">new-text</div>')
160
160
  expect($link).not.toHaveClass('up-active')
@@ -163,7 +163,7 @@ describe 'up.navigation', ->
163
163
  $link = affix('a[href="/foo"][up-modal=".main"]')
164
164
  up.proxy.preload($link)
165
165
  @respondWith('<div class="main">new-text</div>')
166
- $link.click()
166
+ Trigger.clickSequence($link)
167
167
  expect('.up-modal .main').toHaveText('new-text')
168
168
  expect($link).not.toHaveClass('up-active')
169
169
 
@@ -172,7 +172,7 @@ describe 'up.navigation', ->
172
172
  affix('.main')
173
173
  up.proxy.preload($link)
174
174
  @respondWith('<div class="main">new-text</div>')
175
- $link.click()
175
+ Trigger.clickSequence($link)
176
176
  expect('.main').toHaveText('new-text')
177
177
  expect($link).not.toHaveClass('up-active')
178
178
 
@@ -134,7 +134,7 @@ describe 'up.popup', ->
134
134
  expect(up.popup.coveredUrl()).toBeMissing()
135
135
 
136
136
  $popupLink = affix('a[href="/bar"][up-popup=".container"][up-history="true"]')
137
- $popupLink.click()
137
+ Trigger.clickSequence($popupLink)
138
138
  @respondWith('<div class="container">text</div>')
139
139
  expect(up.popup.coveredUrl()).toEndWith('/foo')
140
140
  up.popup.close().then ->
@@ -255,42 +255,37 @@ describe 'up.popup', ->
255
255
 
256
256
  describe '[up-close]', ->
257
257
 
258
+ backgroundClicked = undefined
259
+
260
+ beforeEach ->
261
+ up.motion.config.enabled = false
262
+ backgroundClicked = jasmine.createSpy('background clicked')
263
+ up.on 'click', backgroundClicked
264
+
258
265
  describe 'when clicked inside a popup', ->
259
266
 
260
- it 'closes the open popup and prevents the default action', (done) ->
261
- $link = affix('a')
262
- up.popup.attach($link, html: '<div class="target">text</div>', target: '.target').then ->
263
- $popup = affix('.up-popup')
264
- $link = $popup.affix('a[up-close]') # link is within the popup
265
- up.hello($link)
266
- wasDefaultPrevented = false
267
- wasClosed = false
268
- up.on 'click', 'a[up-close]', (event) ->
269
- wasDefaultPrevented = event.isDefaultPrevented()
270
- true # the line above might return false and cancel propagation / prevent default
271
- up.on 'up:popup:close', ->
272
- wasClosed = true
273
- $link.click()
274
- u.nextFrame ->
275
- expect(wasClosed).toBe(true)
276
- expect(wasDefaultPrevented).toBe(true)
277
- done()
267
+ it 'closes the open popup and halts the event chain', (done) ->
268
+ $opener = affix('a')
269
+ up.popup.attach($opener, html: '<div class="target">text</div>', target: '.target')
270
+ $popup = affix('.up-popup')
271
+ $closer = $popup.affix('a[up-close]') # link is within the popup
272
+ up.hello($closer)
273
+ Trigger.clickSequence($closer)
274
+ u.nextFrame ->
275
+ expect(up.popup.isOpen()).toBe(false)
276
+ expect(backgroundClicked).not.toHaveBeenCalled()
277
+ done()
278
278
 
279
279
  describe 'when no popup is open', ->
280
280
 
281
- it 'does neither close the popup nor prevent the default action', ->
281
+ it 'does nothing and allows the event chain to continue', (done) ->
282
282
  $link = affix('a[up-close]') # link is outside the popup
283
283
  up.hello($link)
284
- wasDefaultPrevented = false
285
- wasClosed = false
286
- up.on 'click', 'a[up-close]', (event) ->
287
- wasDefaultPrevented = event.isDefaultPrevented()
288
- true # the line above might return false and cancel propagation / prevent default
289
- up.on 'up:popup:close', ->
290
- wasClosed = true
291
- $link.click()
292
- expect(wasClosed).toBe(false)
293
- expect(wasDefaultPrevented).toBe(false)
284
+ Trigger.clickSequence($link)
285
+ u.nextFrame ->
286
+ expect(up.popup.isOpen()).toBe(false)
287
+ expect(backgroundClicked).toHaveBeenCalled()
288
+ done()
294
289
 
295
290
  describe 'when replacing content', ->
296
291
 
@@ -300,8 +295,7 @@ describe 'up.popup', ->
300
295
  it 'prefers to replace a selector within the popup', ->
301
296
  $outside = affix('.foo').text('old outside')
302
297
  $link = affix('.link')
303
- up.popup.attach($link, target: '.foo')
304
- @respondWith("<div class='foo'>old inside</div>")
298
+ up.popup.attach($link, target: '.foo', html: "<div class='foo'>old inside</div>")
305
299
  up.extract('.foo', "<div class='foo'>new text</div>")
306
300
  expect($outside).toBeInDOM()
307
301
  expect($outside).toHaveText('old outside')
@@ -310,8 +304,7 @@ describe 'up.popup', ->
310
304
  it 'auto-closes the popup when a replacement from inside the popup affects a selector behind the popup', ->
311
305
  affix('.outside').text('old outside')
312
306
  $link = affix('.link')
313
- up.popup.attach($link, target: '.inside')
314
- @respondWith("<div class='inside'>old inside</div>")
307
+ up.popup.attach($link, target: '.inside', html: "<div class='inside'>old inside</div>")
315
308
  up.extract('.outside', "<div class='outside'>new outside</div>", origin: $('.inside'))
316
309
  expect($('.outside')).toHaveText('new outside')
317
310
  expect($('.up-popup')).not.toExist()
@@ -325,7 +318,7 @@ describe 'up.popup', ->
325
318
  affix('.outside').text('old outside')
326
319
  $link = affix('.link')
327
320
  whenPopupOpen = up.popup.attach($link, url: '/path', target: '.inside')
328
- @respondWith("<div class='inside'>old inside</div>") # Populate popup
321
+ @respondWith("<div class='inside'>old inside</div>")
329
322
 
330
323
  whenPopupOpen.then ->
331
324
  up.extract('.outside', "<div class='outside'>new outside</div>",
@@ -347,8 +340,7 @@ describe 'up.popup', ->
347
340
  it 'does not auto-close the popup when a replacement from outside the popup affects a selector outside the popup', ->
348
341
  affix('.outside').text('old outside')
349
342
  $link = affix('.link')
350
- up.popup.attach($link, target: '.inside')
351
- @respondWith("<div class='inside'>old inside</div>")
343
+ up.popup.attach($link, target: '.inside', html: "<div class='inside'>old inside</div>")
352
344
  up.extract('.outside', "<div class='outside'>new outside</div>", origin: $('.outside'))
353
345
  expect($('.outside')).toHaveText('new outside')
354
346
  expect($('.up-popup')).toExist()
@@ -356,8 +348,7 @@ describe 'up.popup', ->
356
348
  it 'does not auto-close the popup when a replacement from outside the popup affects a selector inside the popup', ->
357
349
  affix('.outside').text('old outside')
358
350
  $link = affix('.link')
359
- up.popup.attach($link, target: '.inside')
360
- @respondWith("<div class='inside'>old inside</div>")
351
+ up.popup.attach($link, target: '.inside', html: "<div class='inside'>old inside</div>")
361
352
  up.extract('.inside', "<div class='inside'>new inside</div>", origin: $('.outside'))
362
353
  expect($('.inside')).toHaveText('new inside')
363
354
  expect($('.up-popup')).toExist()
@@ -367,10 +358,67 @@ describe 'up.popup', ->
367
358
  beforeEach ->
368
359
  up.motion.config.enabled = false
369
360
 
370
- it 'closes a popup on mousedown (in case an [up-instant] link removes its parent and thus a click event never fires)', ->
361
+ it 'closes the popup', (done) ->
371
362
  affix('.outside').text('old outside')
372
363
  $link = affix('.link')
373
- up.popup.attach($link, target: '.inside')
374
- @respondWith("<div class='inside'>inside</div>")
375
- Trigger.mousedown($('body'))
376
- expect($('.up-popup')).not.toExist()
364
+ up.popup.attach($link, target: '.inside', html: "<div class='inside'>inside</div>")
365
+ expect(up.popup.isOpen()).toBe(true)
366
+ Trigger.clickSequence($('body'))
367
+ u.nextFrame ->
368
+ expect(up.popup.isOpen()).toBe(false)
369
+ done()
370
+
371
+ it 'closes the popup when a an [up-instant] link removes its parent (and thus a click event never bubbles up to the document)', (done) ->
372
+ $parent = affix('.parent')
373
+ $parentReplacingLink = $parent.affix('a[href="/foo"][up-target=".parent"][up-instant]')
374
+ $popupOpener = affix('.link')
375
+ up.popup.attach($popupOpener, target: '.inside', html: "<div class='inside'>inside</div>")
376
+ expect(up.popup.isOpen()).toBe(true)
377
+ Trigger.clickSequence($parentReplacingLink)
378
+ u.nextFrame ->
379
+ expect(up.popup.isOpen()).toBe(false)
380
+ done()
381
+
382
+ it 'closes the popup when the user clicks on an [up-target] link outside the popup', (done) ->
383
+ $target = affix('.target')
384
+ $outsideLink = affix('a[href="/foo"][up-target=".target"]')
385
+ $popupOpener = affix('.link')
386
+ up.popup.attach($popupOpener, target: '.inside', html: "<div class='inside'>inside</div>")
387
+ expect(up.popup.isOpen()).toBe(true)
388
+ Trigger.clickSequence($outsideLink)
389
+ u.nextFrame ->
390
+ expect(up.popup.isOpen()).toBe(false)
391
+ done()
392
+
393
+ it 'closes the popup when the user clicks on an [up-instant] link outside the popup', (done) ->
394
+ $target = affix('.target')
395
+ $outsideLink = affix('a[href="/foo"][up-target=".target"][up-instant]')
396
+ $popupOpener = affix('.link')
397
+ up.popup.attach($popupOpener, target: '.inside', html: "<div class='inside'>inside</div>")
398
+ expect(up.popup.isOpen()).toBe(true)
399
+ Trigger.clickSequence($outsideLink)
400
+ u.nextFrame ->
401
+ expect(up.popup.isOpen()).toBe(false)
402
+ done()
403
+
404
+ it 'does not close the popup if a link outside the popup is followed with the up.follow function (bugfix)', (done) ->
405
+ $target = affix('.target')
406
+ $outsideLink = affix('a[href="/foo"][up-target=".target"]')
407
+ $popupOpener = affix('.link')
408
+ up.popup.attach($popupOpener, target: '.inside', html: "<div class='inside'>inside</div>")
409
+ expect(up.popup.isOpen()).toBe(true)
410
+ up.follow($outsideLink)
411
+ u.nextFrame ->
412
+ expect(up.popup.isOpen()).toBe(true)
413
+ done()
414
+
415
+ it 'does not close the popup if a form outside the popup is followed with the up.submit function (bugfix)', (done) ->
416
+ $target = affix('.target')
417
+ $outsideForm = affix('form[action="/foo"][up-target=".target"]')
418
+ $popupOpener = affix('.link')
419
+ up.popup.attach($popupOpener, target: '.inside', html: "<div class='inside'>inside</div>")
420
+ expect(up.popup.isOpen()).toBe(true)
421
+ up.submit($outsideForm)
422
+ u.nextFrame ->
423
+ expect(up.popup.isOpen()).toBe(true)
424
+ done()