unpoly-rails 0.55.1 → 0.56.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of unpoly-rails might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +59 -2
- data/dist/unpoly-bootstrap3.js +6 -4
- data/dist/unpoly-bootstrap3.min.js +1 -1
- data/dist/unpoly.js +1323 -805
- data/dist/unpoly.min.js +4 -3
- data/lib/assets/javascripts/unpoly-bootstrap3/{navigation-ext.coffee → feedback-ext.coffee} +2 -0
- data/lib/assets/javascripts/unpoly/browser.coffee.erb +7 -7
- data/lib/assets/javascripts/unpoly/bus.coffee.erb +5 -6
- data/lib/assets/javascripts/unpoly/classes/css_transition.coffee +127 -0
- data/lib/assets/javascripts/unpoly/classes/extract_plan.coffee +1 -1
- data/lib/assets/javascripts/unpoly/classes/motion_tracker.coffee +62 -32
- data/lib/assets/javascripts/unpoly/classes/url_set.coffee +27 -0
- data/lib/assets/javascripts/unpoly/dom.coffee.erb +78 -99
- data/lib/assets/javascripts/unpoly/feedback.coffee +147 -96
- data/lib/assets/javascripts/unpoly/form.coffee.erb +26 -2
- data/lib/assets/javascripts/unpoly/history.coffee +2 -1
- data/lib/assets/javascripts/unpoly/layout.coffee.erb +68 -12
- data/lib/assets/javascripts/unpoly/link.coffee.erb +10 -4
- data/lib/assets/javascripts/unpoly/modal.coffee.erb +11 -9
- data/lib/assets/javascripts/unpoly/{motion.coffee → motion.coffee.erb} +184 -322
- data/lib/assets/javascripts/unpoly/popup.coffee.erb +13 -12
- data/lib/assets/javascripts/unpoly/radio.coffee +1 -1
- data/lib/assets/javascripts/unpoly/syntax.coffee +8 -17
- data/lib/assets/javascripts/unpoly/tooltip.coffee +11 -11
- data/lib/assets/javascripts/unpoly/util.coffee +332 -145
- data/lib/unpoly/rails/version.rb +1 -1
- data/package.json +1 -1
- data/spec_app/Gemfile.lock +1 -1
- data/spec_app/app/assets/javascripts/integration_test.coffee +1 -0
- data/spec_app/app/assets/stylesheets/integration_test.sass +1 -0
- data/spec_app/app/assets/stylesheets/jasmine_specs.sass +4 -0
- data/spec_app/app/views/motion_test/transitions.erb +13 -0
- data/spec_app/app/views/pages/start.erb +1 -0
- data/spec_app/spec/javascripts/helpers/to_be_attached.coffee +5 -0
- data/spec_app/spec/javascripts/helpers/to_be_detached.coffee +5 -0
- data/spec_app/spec/javascripts/helpers/to_contain.js.coffee +1 -1
- data/spec_app/spec/javascripts/helpers/to_have_opacity.coffee +11 -0
- data/spec_app/spec/javascripts/helpers/to_have_own_property.js.coffee +5 -0
- data/spec_app/spec/javascripts/up/dom_spec.js.coffee +217 -102
- data/spec_app/spec/javascripts/up/feedback_spec.js.coffee +162 -44
- data/spec_app/spec/javascripts/up/layout_spec.js.coffee +97 -10
- data/spec_app/spec/javascripts/up/link_spec.js.coffee +3 -3
- data/spec_app/spec/javascripts/up/modal_spec.js.coffee +22 -20
- data/spec_app/spec/javascripts/up/motion_spec.js.coffee +344 -228
- data/spec_app/spec/javascripts/up/popup_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/util_spec.js.coffee +194 -0
- metadata +11 -4
data/lib/unpoly/rails/version.rb
CHANGED
data/package.json
CHANGED
data/spec_app/Gemfile.lock
CHANGED
@@ -0,0 +1,13 @@
|
|
1
|
+
<div class="fixed-top-bar">
|
2
|
+
<% for animation in %w(cross-fade move-up move-right move-down move-left) do %>
|
3
|
+
<span class="button" onclick="up.replace('.morphed-object', 'transitions', { transition: '<%= animation %>', duration: 2000, cache: false })">
|
4
|
+
<%= animation %>
|
5
|
+
</span>
|
6
|
+
<% end %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<div class="example">
|
10
|
+
<div class="morphed-object" style="padding: 30px; background-color: #<%= SecureRandom.hex(3) %>; color: white; width: 300px; height: 200px; margin-left: 200px; margin-top: 200px">
|
11
|
+
<%= ('a'..'z').to_a.shuffle[0, 20].join %>
|
12
|
+
</div>
|
13
|
+
</div>
|
@@ -63,6 +63,7 @@
|
|
63
63
|
<li><%= link_to 'Hash links (without Unpoly)', '/hash_test/vanilla' %></li>
|
64
64
|
<li><%= link_to 'Revealing long pages', '/reveal_test/long1' %></li>
|
65
65
|
<li><%= link_to 'Animations', '/motion_test/animations' %></li>
|
66
|
+
<li><%= link_to 'Transitions', '/motion_test/transitions' %></li>
|
66
67
|
</ul>
|
67
68
|
|
68
69
|
</div>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
beforeEach ->
|
2
|
+
jasmine.addMatchers
|
3
|
+
toHaveOpacity: (util, customEqualityTesters) ->
|
4
|
+
compare: (element, expectedOpacity, tolerance = 0.0) ->
|
5
|
+
element = up.util.element(element)
|
6
|
+
actualOpacity = up.util.opacity(element)
|
7
|
+
result = {}
|
8
|
+
result.pass = Math.abs(expectedOpacity - actualOpacity) <= tolerance
|
9
|
+
unless result.pass
|
10
|
+
result.message = up.browser.sprintf("Expected %o to have opacity %o, but it was %o", element, expectedOpacity, actualOpacity)
|
11
|
+
return result
|
@@ -48,39 +48,7 @@ describe 'up.dom', ->
|
|
48
48
|
expect(resolution).toHaveBeenCalled()
|
49
49
|
expect($('.middle')).toHaveText('new-middle')
|
50
50
|
|
51
|
-
describe '
|
52
|
-
|
53
|
-
it 'calls destructors on the replaced element', asyncSpec (next) ->
|
54
|
-
destructor = jasmine.createSpy('destructor')
|
55
|
-
up.compiler '.container', -> destructor
|
56
|
-
$container = affix('.container')
|
57
|
-
up.hello($container)
|
58
|
-
up.replace('.container', '/path')
|
59
|
-
|
60
|
-
next =>
|
61
|
-
@respondWith '<div class="container">new text</div>'
|
62
|
-
|
63
|
-
next =>
|
64
|
-
expect('.container').toHaveText('new text')
|
65
|
-
expect(destructor).toHaveBeenCalled()
|
66
|
-
|
67
|
-
it 'calls destructors when the replaced element is a singleton element like <body> (bugfix)', asyncSpec (next) ->
|
68
|
-
# shouldSwapElementsDirectly() is true for body, but can't have the example replace the Jasmine test runner UI
|
69
|
-
up.dom.knife.mock('shouldSwapElementsDirectly').and.callFake ($element) -> $element.is('.container')
|
70
|
-
destructor = jasmine.createSpy('destructor')
|
71
|
-
up.compiler '.container', -> destructor
|
72
|
-
$container = affix('.container')
|
73
|
-
up.hello($container)
|
74
|
-
up.replace('.container', '/path')
|
75
|
-
|
76
|
-
next =>
|
77
|
-
@respondWith '<div class="container">new text</div>'
|
78
|
-
|
79
|
-
next =>
|
80
|
-
expect('.container').toHaveText('new text')
|
81
|
-
expect(destructor).toHaveBeenCalled()
|
82
|
-
|
83
|
-
describe 'transitions', ->
|
51
|
+
describe 'with { transition } option', ->
|
84
52
|
|
85
53
|
it 'returns a promise that will be fulfilled once the server response was received and the swap transition has completed', asyncSpec (next) ->
|
86
54
|
resolution = jasmine.createSpy()
|
@@ -99,21 +67,6 @@ describe 'up.dom', ->
|
|
99
67
|
next.after 80, =>
|
100
68
|
expect(resolution).toHaveBeenCalled()
|
101
69
|
|
102
|
-
it 'ignores a { transition } option when replacing the body element', asyncSpec (next) ->
|
103
|
-
up.dom.knife.mock('swapElementsDirectly') # can't have the example replace the Jasmine test runner UI
|
104
|
-
up.dom.knife.mock('destroy') # if we don't swap the body, up.dom will destroy it
|
105
|
-
replaceCallback = jasmine.createSpy()
|
106
|
-
promise = up.replace('body', '/path', transition: 'cross-fade', duration: 50)
|
107
|
-
promise.then(replaceCallback)
|
108
|
-
expect(replaceCallback).not.toHaveBeenCalled()
|
109
|
-
|
110
|
-
next =>
|
111
|
-
@responseText = '<body>new text</body>'
|
112
|
-
@respond()
|
113
|
-
|
114
|
-
next =>
|
115
|
-
expect(replaceCallback).toHaveBeenCalled()
|
116
|
-
|
117
70
|
describe 'with { data } option', ->
|
118
71
|
|
119
72
|
it "uses the given params as a non-GET request's payload", asyncSpec (next) ->
|
@@ -1438,15 +1391,6 @@ describe 'up.dom', ->
|
|
1438
1391
|
expect(result.value).toMatch(/Could not find selector/i)
|
1439
1392
|
done()
|
1440
1393
|
|
1441
|
-
it "ignores an element that matches the selector but also matches .up-ghost", (done) ->
|
1442
|
-
html = '<div class="foo-bar">text</div>'
|
1443
|
-
affix('.foo-bar.up-ghost')
|
1444
|
-
promise = up.extract('.foo-bar', html)
|
1445
|
-
promiseState(promise).then (result) =>
|
1446
|
-
expect(result.state).toEqual('rejected')
|
1447
|
-
expect(result.value).toMatch(/Could not find selector/i)
|
1448
|
-
done()
|
1449
|
-
|
1450
1394
|
it "ignores an element that matches the selector but also has a parent matching .up-destroying", (done) ->
|
1451
1395
|
html = '<div class="foo-bar">text</div>'
|
1452
1396
|
$parent = affix('.up-destroying')
|
@@ -1457,16 +1401,6 @@ describe 'up.dom', ->
|
|
1457
1401
|
expect(result.value).toMatch(/Could not find selector/i)
|
1458
1402
|
done()
|
1459
1403
|
|
1460
|
-
it "ignores an element that matches the selector but also has a parent matching .up-ghost", (done) ->
|
1461
|
-
html = '<div class="foo-bar">text</div>'
|
1462
|
-
$parent = affix('.up-ghost')
|
1463
|
-
$child = affix('.foo-bar').appendTo($parent)
|
1464
|
-
promise = up.extract('.foo-bar', html)
|
1465
|
-
promiseState(promise).then (result) =>
|
1466
|
-
expect(result.state).toEqual('rejected')
|
1467
|
-
expect(result.value).toMatch(/Could not find selector/i)
|
1468
|
-
done()
|
1469
|
-
|
1470
1404
|
it 'only replaces the first element matching the selector', asyncSpec (next) ->
|
1471
1405
|
html = '<div class="foo-bar">text</div>'
|
1472
1406
|
affix('.foo-bar')
|
@@ -1474,86 +1408,209 @@ describe 'up.dom', ->
|
|
1474
1408
|
up.extract('.foo-bar', html)
|
1475
1409
|
|
1476
1410
|
next =>
|
1477
|
-
elements = $('.foo-bar')
|
1478
|
-
expect($(elements.get(0)).text()).toEqual('text')
|
1479
|
-
expect($(elements.get(1)).text()).toEqual('')
|
1411
|
+
$elements = $('.foo-bar')
|
1412
|
+
expect($($elements.get(0)).text()).toEqual('text')
|
1413
|
+
expect($($elements.get(1)).text()).toEqual('')
|
1414
|
+
|
1415
|
+
it 'focuses an [autofocus] element in the new fragment', asyncSpec (next) ->
|
1416
|
+
affix('.foo-bar')
|
1417
|
+
up.extract '.foo-bar', """
|
1418
|
+
<form class='foo-bar'>
|
1419
|
+
<input class="autofocused-input" autofocus>
|
1420
|
+
</form>
|
1421
|
+
"""
|
1422
|
+
|
1423
|
+
next =>
|
1424
|
+
input = $('.autofocused-input').get(0)
|
1425
|
+
expect(input).toBeGiven()
|
1426
|
+
expect(document.activeElement).toBe(input)
|
1427
|
+
|
1428
|
+
describe 'cleaning up', ->
|
1429
|
+
|
1430
|
+
it 'calls destructors on the old element', asyncSpec (next) ->
|
1431
|
+
destructor = jasmine.createSpy('destructor')
|
1432
|
+
up.compiler '.container', ($element) ->
|
1433
|
+
-> destructor($element.text())
|
1434
|
+
$container = affix('.container').text('old text')
|
1435
|
+
up.hello($container)
|
1436
|
+
up.extract('.container', '<div class="container">new text</div>')
|
1437
|
+
|
1438
|
+
next =>
|
1439
|
+
expect('.container').toHaveText('new text')
|
1440
|
+
expect(destructor).toHaveBeenCalledWith('old text')
|
1441
|
+
|
1442
|
+
it 'calls destructors on the old element after a { transition }', (done) ->
|
1443
|
+
destructor = jasmine.createSpy('destructor')
|
1444
|
+
up.compiler '.container', ($element) ->
|
1445
|
+
-> destructor($element.text())
|
1446
|
+
$container = affix('.container').text('old text')
|
1447
|
+
up.hello($container)
|
1448
|
+
|
1449
|
+
up.extract('.container', '<div class="container">new text</div>', transition: 'cross-fade', duration: 100)
|
1450
|
+
|
1451
|
+
u.setTimer 50, =>
|
1452
|
+
expect(destructor).not.toHaveBeenCalled()
|
1453
|
+
|
1454
|
+
u.setTimer 220, =>
|
1455
|
+
expect('.container').toHaveText('new text')
|
1456
|
+
expect(destructor).toHaveBeenCalledWith('old text')
|
1457
|
+
done()
|
1458
|
+
|
1459
|
+
it 'calls destructors when the replaced element is a singleton element like <body> (bugfix)', asyncSpec (next) ->
|
1460
|
+
# shouldSwapElementsDirectly() is true for body, but can't have the example replace the Jasmine test runner UI
|
1461
|
+
up.motion.knife.mock('isSingletonElement').and.callFake ($element) -> $element.is('.container')
|
1462
|
+
destructor = jasmine.createSpy('destructor')
|
1463
|
+
up.compiler '.container', -> destructor
|
1464
|
+
$container = affix('.container')
|
1465
|
+
up.hello($container)
|
1466
|
+
up.extract('.container', '<div class="container">new text</div>')
|
1467
|
+
|
1468
|
+
next =>
|
1469
|
+
expect('.container').toHaveText('new text')
|
1470
|
+
expect(destructor).toHaveBeenCalled()
|
1471
|
+
|
1472
|
+
it 'calls destructors while the element is still attached to the DOM, so destructors see ancestry and events bubble up', asyncSpec (next) ->
|
1473
|
+
spy = jasmine.createSpy('parent spy')
|
1474
|
+
up.compiler '.element', ($element) ->
|
1475
|
+
return -> spy($element.text(), $element.parent())
|
1476
|
+
|
1477
|
+
$parent = affix('.parent')
|
1478
|
+
$element = $parent.affix('.element').text('old text')
|
1479
|
+
up.hello($element)
|
1480
|
+
|
1481
|
+
up.extract '.element', '<div class="element">new text</div>'
|
1482
|
+
|
1483
|
+
next =>
|
1484
|
+
expect(spy).toHaveBeenCalledWith('old text', $parent)
|
1485
|
+
|
1486
|
+
it 'calls destructors while the element is still attached to the DOM when also using a { transition }', (done) ->
|
1487
|
+
spy = jasmine.createSpy('parent spy')
|
1488
|
+
up.compiler '.element', ($element) ->
|
1489
|
+
return ->
|
1490
|
+
# We must seek .parent in our ancestry, because our direct parent() is an .up-bounds container
|
1491
|
+
spy($element.text(), $element.closest('.parent'))
|
1492
|
+
|
1493
|
+
$parent = affix('.parent')
|
1494
|
+
$element = $parent.affix('.element').text('old text')
|
1495
|
+
up.hello($element)
|
1496
|
+
|
1497
|
+
extractDone = up.extract('.element', '<div class="element">new text</div>', transition: 'cross-fade', duration: 30)
|
1498
|
+
|
1499
|
+
extractDone.then ->
|
1500
|
+
expect(spy).toHaveBeenCalledWith('old text', $parent)
|
1501
|
+
done()
|
1480
1502
|
|
1481
1503
|
describe 'with { transition } option', ->
|
1482
1504
|
|
1483
1505
|
it 'morphs between the old and new element', asyncSpec (next) ->
|
1484
|
-
affix('.element').text('version 1')
|
1485
|
-
up.extract('.element', '<div class="element">version 2</div>', transition: 'cross-fade', duration:
|
1506
|
+
affix('.element.v1').text('version 1')
|
1507
|
+
up.extract('.element', '<div class="element v2">version 2</div>', transition: 'cross-fade', duration: 100, easing: 'linear')
|
1508
|
+
|
1509
|
+
$old = undefined
|
1510
|
+
$new = undefined
|
1486
1511
|
|
1487
1512
|
next =>
|
1488
|
-
|
1489
|
-
|
1490
|
-
expect(u.opacity(@$ghost1)).toBeAround(1.0, 0.1)
|
1513
|
+
$old = $('.element.v1')
|
1514
|
+
$new = $('.element.v2')
|
1491
1515
|
|
1492
|
-
|
1493
|
-
expect(
|
1494
|
-
expect(u.opacity(@$ghost2)).toBeAround(0.0, 0.1)
|
1516
|
+
expect($old).toHaveLength(1)
|
1517
|
+
expect(u.opacity($old)).toBeAround(1.0, 0.2)
|
1495
1518
|
|
1496
|
-
|
1497
|
-
expect(u.opacity(
|
1498
|
-
expect(u.opacity(@$ghost2)).toBeAround(1.0, 0.3)
|
1519
|
+
expect($new).toHaveLength(1)
|
1520
|
+
expect(u.opacity($new)).toBeAround(0.0, 0.2)
|
1499
1521
|
|
1500
|
-
|
1522
|
+
next.after 50, =>
|
1523
|
+
expect(u.opacity($old)).toBeAround(0.5, 0.2)
|
1524
|
+
expect(u.opacity($new)).toBeAround(0.5, 0.2)
|
1525
|
+
|
1526
|
+
next.after 60, =>
|
1527
|
+
expect(u.opacity($new)).toBeAround(1.0, 0.1)
|
1528
|
+
expect($old).toBeDetached()
|
1529
|
+
|
1530
|
+
|
1531
|
+
it 'ignores a { transition } option when replacing a singleton element like <body>', asyncSpec (next) ->
|
1532
|
+
# shouldSwapElementsDirectly() is true for body, but can't have the example replace the Jasmine test runner UI
|
1533
|
+
up.motion.knife.mock('isSingletonElement').and.callFake ($element) -> $element.is('.container')
|
1534
|
+
|
1535
|
+
affix('.container').text('old text')
|
1536
|
+
|
1537
|
+
extractDone = jasmine.createSpy()
|
1538
|
+
promise = up.extract('.container', '<div class="container">new text</div>', transition: 'cross-fade', duration: 200)
|
1539
|
+
promise.then(extractDone)
|
1540
|
+
|
1541
|
+
next =>
|
1542
|
+
# See that we've already immediately swapped the element and ignored the duration of 200ms
|
1543
|
+
expect(extractDone).toHaveBeenCalled()
|
1544
|
+
expect($('.container').length).toEqual(1)
|
1545
|
+
expect(u.opacity($('.container'))).toEqual(1.0)
|
1546
|
+
|
1547
|
+
|
1548
|
+
it 'marks the old fragment as .up-destroying during the transition', asyncSpec (next) ->
|
1501
1549
|
affix('.element').text('version 1')
|
1502
1550
|
up.extract('.element', '<div class="element">version 2</div>', transition: 'cross-fade', duration: 200)
|
1503
1551
|
|
1504
1552
|
next =>
|
1505
|
-
$version1 = $('.element:
|
1506
|
-
$version1Ghost = $('.element.up-ghost:contains("version 1")')
|
1553
|
+
$version1 = $('.element:contains("version 1")')
|
1507
1554
|
expect($version1).toHaveLength(1)
|
1508
|
-
expect($version1Ghost).toHaveLength(1)
|
1509
1555
|
expect($version1).toHaveClass('up-destroying')
|
1510
|
-
expect($version1Ghost).toHaveClass('up-destroying')
|
1511
1556
|
|
1512
|
-
$version2 = $('.element:
|
1513
|
-
$version2Ghost = $('.element.up-ghost:contains("version 2")')
|
1557
|
+
$version2 = $('.element:contains("version 2")')
|
1514
1558
|
expect($version2).toHaveLength(1)
|
1515
|
-
expect($version2Ghost).toHaveLength(1)
|
1516
1559
|
expect($version2).not.toHaveClass('up-destroying')
|
1517
|
-
expect($version2Ghost).not.toHaveClass('up-destroying')
|
1518
1560
|
|
1519
1561
|
it 'cancels an existing transition by instantly jumping to the last frame', asyncSpec (next) ->
|
1520
|
-
affix('.element').text('version 1')
|
1521
|
-
|
1562
|
+
affix('.element.v1').text('version 1')
|
1563
|
+
|
1564
|
+
up.extract('.element', '<div class="element v2">version 2</div>', transition: 'cross-fade', duration: 200)
|
1522
1565
|
|
1523
1566
|
next =>
|
1524
|
-
$ghost1 = $('.element
|
1567
|
+
$ghost1 = $('.element:contains("version 1")')
|
1525
1568
|
expect($ghost1).toHaveLength(1)
|
1526
1569
|
expect($ghost1.css('opacity')).toBeAround(1.0, 0.1)
|
1527
1570
|
|
1528
|
-
$ghost2 = $('.element
|
1571
|
+
$ghost2 = $('.element:contains("version 2")')
|
1529
1572
|
expect($ghost2).toHaveLength(1)
|
1530
1573
|
expect($ghost2.css('opacity')).toBeAround(0.0, 0.1)
|
1531
1574
|
|
1532
1575
|
next =>
|
1533
|
-
up.extract('.element', '<div class="element">version 3</div>', transition: 'cross-fade', duration: 200)
|
1576
|
+
up.extract('.element', '<div class="element v3">version 3</div>', transition: 'cross-fade', duration: 200)
|
1534
1577
|
|
1535
1578
|
next =>
|
1536
|
-
$ghost1 = $('.element
|
1579
|
+
$ghost1 = $('.element:contains("version 1")')
|
1537
1580
|
expect($ghost1).toHaveLength(0)
|
1538
1581
|
|
1539
|
-
$ghost2 = $('.element
|
1582
|
+
$ghost2 = $('.element:contains("version 2")')
|
1540
1583
|
expect($ghost2).toHaveLength(1)
|
1541
1584
|
expect($ghost2.css('opacity')).toBeAround(1.0, 0.1)
|
1542
1585
|
|
1543
|
-
$ghost3 = $('.element
|
1586
|
+
$ghost3 = $('.element:contains("version 3")')
|
1544
1587
|
expect($ghost3).toHaveLength(1)
|
1545
1588
|
expect($ghost3.css('opacity')).toBeAround(0.0, 0.1)
|
1546
1589
|
|
1547
1590
|
it 'delays the resolution of the returned promise until the transition is over', (done) ->
|
1548
1591
|
affix('.element').text('version 1')
|
1549
1592
|
resolution = jasmine.createSpy()
|
1550
|
-
promise = up.extract('.element', '<div class="element">version 2</div>', transition: 'cross-fade', duration:
|
1593
|
+
promise = up.extract('.element', '<div class="element">version 2</div>', transition: 'cross-fade', duration: 60)
|
1551
1594
|
promise.then(resolution)
|
1552
1595
|
expect(resolution).not.toHaveBeenCalled()
|
1553
|
-
|
1596
|
+
|
1597
|
+
u.setTimer 40, ->
|
1598
|
+
expect(resolution).not.toHaveBeenCalled()
|
1599
|
+
|
1600
|
+
u.setTimer 200, ->
|
1554
1601
|
expect(resolution).toHaveBeenCalled()
|
1555
1602
|
done()
|
1556
1603
|
|
1604
|
+
it 'attaches the new element to the DOM before compilers are called, so they can see their parents and trigger bubbling events', asyncSpec (next)->
|
1605
|
+
$parent = affix('.parent')
|
1606
|
+
$element = $parent.affix('.element').text('old text')
|
1607
|
+
spy = jasmine.createSpy('parent spy')
|
1608
|
+
up.compiler '.element', ($element) -> spy($element.text(), $element.parent())
|
1609
|
+
up.extract '.element', '<div class="element">new text</div>', transition: 'cross-fade', duration: 50
|
1610
|
+
|
1611
|
+
next =>
|
1612
|
+
expect(spy).toHaveBeenCalledWith('new text', $parent)
|
1613
|
+
|
1557
1614
|
describe 'when animation is disabled', ->
|
1558
1615
|
|
1559
1616
|
beforeEach ->
|
@@ -1567,7 +1624,7 @@ describe 'up.dom', ->
|
|
1567
1624
|
expect($('.up-ghost')).toHaveLength(0)
|
1568
1625
|
|
1569
1626
|
it "replaces the elements directly, since first inserting and then removing would shift scroll positions", asyncSpec (next) ->
|
1570
|
-
swapDirectlySpy = up.
|
1627
|
+
swapDirectlySpy = up.motion.knife.mock('swapElementsDirectly')
|
1571
1628
|
affix('.element').text('version 1')
|
1572
1629
|
up.extract('.element', '<div class="element">version 2</div>', transition: false)
|
1573
1630
|
|
@@ -1896,7 +1953,7 @@ describe 'up.dom', ->
|
|
1896
1953
|
expect(insertedListener).toHaveBeenCalledWith(jasmine.anything(), $('.container'), jasmine.anything())
|
1897
1954
|
expect(keptListener).toHaveBeenCalledWith(jasmine.anything(), $('.container .keeper'), jasmine.anything())
|
1898
1955
|
|
1899
|
-
it 'emits an up:fragment:kept event on a kept element with a newData property corresponding to the up-data attribute value of the discarded element', (next) ->
|
1956
|
+
it 'emits an up:fragment:kept event on a kept element with a newData property corresponding to the up-data attribute value of the discarded element', asyncSpec (next) ->
|
1900
1957
|
keptListener = jasmine.createSpy()
|
1901
1958
|
up.on 'up:fragment:kept', (event) -> keptListener(event.$element, event.newData)
|
1902
1959
|
$container = affix('.container')
|
@@ -2009,6 +2066,64 @@ describe 'up.dom', ->
|
|
2009
2066
|
expect(document.title).toEqual('Title from options')
|
2010
2067
|
done()
|
2011
2068
|
|
2069
|
+
it 'runs an animation before removal with { animate } option', asyncSpec (next) ->
|
2070
|
+
$element = affix('.element')
|
2071
|
+
up.destroy($element, animation: 'fade-out', duration: 150, easing: 'linear')
|
2072
|
+
|
2073
|
+
next ->
|
2074
|
+
expect($element).toHaveOpacity(1.0, 0.2)
|
2075
|
+
|
2076
|
+
next.after 75, ->
|
2077
|
+
expect($element).toHaveOpacity(0.5, 0.2)
|
2078
|
+
|
2079
|
+
next.after (75 + 20), ->
|
2080
|
+
expect($element).toBeDetached()
|
2081
|
+
|
2082
|
+
it 'marks the element as .up-destroying while it is animating', asyncSpec (next) ->
|
2083
|
+
$element = affix('.element')
|
2084
|
+
up.destroy($element, animation: 'fade-out', duration: 80, easing: 'linear')
|
2085
|
+
|
2086
|
+
next ->
|
2087
|
+
expect($element).toHaveClass('up-destroying')
|
2088
|
+
|
2089
|
+
it 'emits an up:fragment:destroy event while the element is still in the DOM', asyncSpec (next) ->
|
2090
|
+
$element = affix('.element')
|
2091
|
+
expect($element).toBeAttached()
|
2092
|
+
|
2093
|
+
listener = jasmine.createSpy('event listener')
|
2094
|
+
$element.on('up:fragment:destroy', listener)
|
2095
|
+
|
2096
|
+
destroyDone = up.destroy($element, animation: 'fade-out', duration: 30)
|
2097
|
+
|
2098
|
+
next ->
|
2099
|
+
expect(listener).toHaveBeenCalledWith(jasmine.objectContaining($element: $element))
|
2100
|
+
expect($element).toBeAttached()
|
2101
|
+
|
2102
|
+
next.await(destroyDone)
|
2103
|
+
|
2104
|
+
next ->
|
2105
|
+
expect($element).toBeDetached()
|
2106
|
+
|
2107
|
+
it 'emits an up:fragment:destroyed event on the former parent element after the element has been removed from the DOM', asyncSpec (next) ->
|
2108
|
+
$parent = affix('.parent')
|
2109
|
+
$element = $parent.affix('.element')
|
2110
|
+
expect($element).toBeAttached()
|
2111
|
+
|
2112
|
+
listener = jasmine.createSpy('event listener')
|
2113
|
+
|
2114
|
+
$parent.on('up:fragment:destroyed', listener)
|
2115
|
+
|
2116
|
+
destroyDone = up.destroy($element, animation: 'fade-out', duration: 30)
|
2117
|
+
|
2118
|
+
next ->
|
2119
|
+
expect(listener).not.toHaveBeenCalled()
|
2120
|
+
expect($element).toBeAttached()
|
2121
|
+
|
2122
|
+
next.await(destroyDone)
|
2123
|
+
|
2124
|
+
next ->
|
2125
|
+
expect(listener).toHaveBeenCalledWith(jasmine.objectContaining($element: $element, $parent: $parent))
|
2126
|
+
expect($element).toBeDetached()
|
2012
2127
|
|
2013
2128
|
describe 'up.reload', ->
|
2014
2129
|
|