unpoly-rails 0.57.0 → 0.60.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 (186) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +393 -1
  3. data/Gemfile.lock +5 -2
  4. data/README.md +1 -1
  5. data/README_RAILS.md +1 -1
  6. data/Rakefile +10 -1
  7. data/design/es6.js +32 -0
  8. data/design/ie11.txt +9 -0
  9. data/design/measure_jquery/element_list.js +41 -0
  10. data/design/measure_jquery/up.on_vs_addEventListener.js +56 -0
  11. data/design/todo_jquery.txt +13 -0
  12. data/dist/unpoly-bootstrap3.js +8 -8
  13. data/dist/unpoly-bootstrap3.min.js +1 -1
  14. data/dist/unpoly.css +22 -20
  15. data/dist/unpoly.js +6990 -5336
  16. data/dist/unpoly.min.css +1 -1
  17. data/dist/unpoly.min.js +4 -4
  18. data/lib/assets/javascripts/unpoly-bootstrap3/viewport-ext.coffee +5 -0
  19. data/lib/assets/javascripts/unpoly.coffee +8 -6
  20. data/lib/assets/javascripts/unpoly/browser.coffee.erb +23 -118
  21. data/lib/assets/javascripts/unpoly/classes/body_shifter.coffee +36 -0
  22. data/lib/assets/javascripts/unpoly/classes/cache.coffee +4 -4
  23. data/lib/assets/javascripts/unpoly/classes/compile_pass.coffee +45 -39
  24. data/lib/assets/javascripts/unpoly/classes/config.coffee +9 -0
  25. data/lib/assets/javascripts/unpoly/classes/css_transition.coffee +18 -27
  26. data/lib/assets/javascripts/unpoly/classes/divertible_chain.coffee +39 -0
  27. data/lib/assets/javascripts/unpoly/classes/event_listener.coffee +116 -0
  28. data/lib/assets/javascripts/unpoly/classes/extract_cascade.coffee +8 -8
  29. data/lib/assets/javascripts/unpoly/classes/extract_plan.coffee +19 -19
  30. data/lib/assets/javascripts/unpoly/classes/field_observer.coffee +54 -31
  31. data/lib/assets/javascripts/unpoly/classes/{focus_tracker.coffee → focus_follower.coffee} +2 -2
  32. data/lib/assets/javascripts/unpoly/classes/follow_variant.coffee +25 -25
  33. data/lib/assets/javascripts/unpoly/classes/html_parser.coffee +4 -11
  34. data/lib/assets/javascripts/unpoly/classes/motion_controller.coffee +157 -0
  35. data/lib/assets/javascripts/unpoly/classes/params.coffee.erb +525 -0
  36. data/lib/assets/javascripts/unpoly/classes/record.coffee +8 -2
  37. data/lib/assets/javascripts/unpoly/classes/rect.js +21 -0
  38. data/lib/assets/javascripts/unpoly/classes/request.coffee +41 -35
  39. data/lib/assets/javascripts/unpoly/classes/response.coffee +7 -3
  40. data/lib/assets/javascripts/unpoly/classes/reveal_motion.coffee +102 -0
  41. data/lib/assets/javascripts/unpoly/classes/scroll_motion.coffee +67 -0
  42. data/lib/assets/javascripts/unpoly/classes/selector.coffee +60 -0
  43. data/lib/assets/javascripts/unpoly/classes/tether.coffee +105 -0
  44. data/lib/assets/javascripts/unpoly/classes/url_set.coffee +12 -7
  45. data/lib/assets/javascripts/unpoly/element.coffee.erb +1126 -0
  46. data/lib/assets/javascripts/unpoly/event.coffee.erb +437 -0
  47. data/lib/assets/javascripts/unpoly/feedback.coffee +73 -94
  48. data/lib/assets/javascripts/unpoly/form.coffee.erb +188 -181
  49. data/lib/assets/javascripts/unpoly/{dom.coffee.erb → fragment.coffee.erb} +250 -283
  50. data/lib/assets/javascripts/unpoly/framework.coffee +67 -0
  51. data/lib/assets/javascripts/unpoly/history.coffee +29 -28
  52. data/lib/assets/javascripts/unpoly/legacy.coffee +60 -0
  53. data/lib/assets/javascripts/unpoly/link.coffee.erb +127 -119
  54. data/lib/assets/javascripts/unpoly/log.coffee +99 -19
  55. data/lib/assets/javascripts/unpoly/modal.coffee.erb +95 -118
  56. data/lib/assets/javascripts/unpoly/motion.coffee.erb +158 -138
  57. data/lib/assets/javascripts/unpoly/namespace.coffee.erb +0 -5
  58. data/lib/assets/javascripts/unpoly/popup.coffee.erb +119 -102
  59. data/lib/assets/javascripts/unpoly/protocol.coffee +11 -15
  60. data/lib/assets/javascripts/unpoly/proxy.coffee +62 -65
  61. data/lib/assets/javascripts/unpoly/radio.coffee +3 -5
  62. data/lib/assets/javascripts/unpoly/rails.coffee +8 -9
  63. data/lib/assets/javascripts/unpoly/syntax.coffee.erb +173 -125
  64. data/lib/assets/javascripts/unpoly/toast.coffee +25 -24
  65. data/lib/assets/javascripts/unpoly/tooltip.coffee +89 -79
  66. data/lib/assets/javascripts/unpoly/util.coffee.erb +579 -1074
  67. data/lib/assets/javascripts/unpoly/{layout.coffee.erb → viewport.coffee.erb} +334 -264
  68. data/lib/assets/stylesheets/unpoly/dom.sass +1 -1
  69. data/lib/assets/stylesheets/unpoly/layout.sass +2 -0
  70. data/lib/assets/stylesheets/unpoly/popup.sass +0 -1
  71. data/lib/assets/stylesheets/unpoly/tooltip.sass +17 -12
  72. data/lib/unpoly/rails/version.rb +1 -1
  73. data/package.json +1 -2
  74. data/spec_app/Gemfile +2 -1
  75. data/spec_app/Gemfile.lock +38 -27
  76. data/spec_app/app/assets/javascripts/integration_test.coffee +1 -0
  77. data/spec_app/app/assets/javascripts/jasmine_specs.coffee +1 -2
  78. data/spec_app/app/assets/stylesheets/integration_test.sass +14 -1
  79. data/spec_app/app/controllers/scroll_test_controller.rb +5 -0
  80. data/spec_app/app/views/css_test/modal.erb +6 -6
  81. data/spec_app/app/views/css_test/popup.erb +44 -18
  82. data/spec_app/app/views/css_test/tooltip.erb +23 -4
  83. data/spec_app/app/views/error_test/trigger.erb +1 -1
  84. data/spec_app/app/views/form_test/basics/new.erb +1 -3
  85. data/spec_app/app/views/pages/start.erb +9 -2
  86. data/spec_app/app/views/reveal_test/long1.erb +1 -1
  87. data/spec_app/app/views/reveal_test/long2.erb +1 -1
  88. data/spec_app/app/views/reveal_test/within_document_viewport.erb +24 -0
  89. data/spec_app/app/views/reveal_test/within_overflowing_div_viewport.erb +28 -0
  90. data/spec_app/app/views/scroll_test/long1.erb +30 -0
  91. data/spec_app/config/routes.rb +1 -0
  92. data/spec_app/spec/javascripts/helpers/agent_detector.coffee +3 -0
  93. data/spec_app/spec/javascripts/helpers/async_sequence.js.coffee +1 -0
  94. data/spec_app/spec/javascripts/helpers/browser_switches.js.coffee +17 -5
  95. data/spec_app/spec/javascripts/helpers/enable_logging.js.coffee +1 -1
  96. data/spec_app/spec/javascripts/helpers/fixture.js.coffee +25 -0
  97. data/spec_app/spec/javascripts/helpers/jquery_no_conflict.js +1 -0
  98. data/spec_app/spec/javascripts/helpers/last_request.js.coffee +1 -0
  99. data/spec_app/spec/javascripts/helpers/mock_ajax.js.coffee +1 -1
  100. data/spec_app/spec/javascripts/helpers/parse_form_data.js.coffee +2 -2
  101. data/spec_app/spec/javascripts/helpers/protect_jasmine_runner.coffee +4 -1
  102. data/spec_app/spec/javascripts/helpers/remove_body_margin.js.coffee +3 -0
  103. data/spec_app/spec/javascripts/helpers/reset_history.js.coffee +2 -1
  104. data/spec_app/spec/javascripts/helpers/reset_knife.js.coffee +2 -2
  105. data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +18 -11
  106. data/spec_app/spec/javascripts/helpers/restore_body_scroll.js.coffee +3 -0
  107. data/spec_app/spec/javascripts/helpers/show_lib_versions.coffee +3 -0
  108. data/spec_app/spec/javascripts/helpers/spec_util.coffee +47 -0
  109. data/spec_app/spec/javascripts/helpers/to_be_around.js.coffee +3 -0
  110. data/spec_app/spec/javascripts/helpers/to_be_array.coffee +5 -0
  111. data/spec_app/spec/javascripts/helpers/to_be_attached.coffee +6 -2
  112. data/spec_app/spec/javascripts/helpers/to_be_blank.js.coffee +3 -0
  113. data/spec_app/spec/javascripts/helpers/to_be_detached.coffee +6 -2
  114. data/spec_app/spec/javascripts/helpers/to_be_element.js.coffee +8 -0
  115. data/spec_app/spec/javascripts/helpers/to_be_error.coffee +3 -0
  116. data/spec_app/spec/javascripts/helpers/to_be_given.js.coffee +3 -0
  117. data/spec_app/spec/javascripts/helpers/to_be_hidden.js.coffee +8 -0
  118. data/spec_app/spec/javascripts/helpers/to_be_missing.js.coffee +3 -0
  119. data/spec_app/spec/javascripts/helpers/to_be_present.js.coffee +3 -0
  120. data/spec_app/spec/javascripts/helpers/to_be_scrolled_to.coffee +3 -0
  121. data/spec_app/spec/javascripts/helpers/to_be_visible.js.coffee +9 -0
  122. data/spec_app/spec/javascripts/helpers/to_contain.js.coffee +3 -0
  123. data/spec_app/spec/javascripts/helpers/to_end_with.js.coffee +3 -0
  124. data/spec_app/spec/javascripts/helpers/to_equal_jquery.js.coffee +1 -2
  125. data/spec_app/spec/javascripts/helpers/to_equal_node_list.coffee +7 -0
  126. data/spec_app/spec/javascripts/helpers/to_equal_via_is_equal.js.coffee +7 -0
  127. data/spec_app/spec/javascripts/helpers/to_have_class.js.coffee +10 -0
  128. data/spec_app/spec/javascripts/helpers/to_have_descendant.js.coffee +10 -0
  129. data/spec_app/spec/javascripts/helpers/to_have_length.js.coffee +8 -0
  130. data/spec_app/spec/javascripts/helpers/to_have_opacity.coffee +7 -3
  131. data/spec_app/spec/javascripts/helpers/to_have_own_property.js.coffee +3 -0
  132. data/spec_app/spec/javascripts/helpers/to_have_request_method.js.coffee +1 -0
  133. data/spec_app/spec/javascripts/helpers/to_have_text.js.coffee +9 -0
  134. data/spec_app/spec/javascripts/helpers/to_have_unhandled_rejections.coffee +0 -21
  135. data/spec_app/spec/javascripts/helpers/to_match_list.coffee +14 -0
  136. data/spec_app/spec/javascripts/helpers/to_match_selector.coffee +3 -0
  137. data/spec_app/spec/javascripts/helpers/to_match_text.js.coffee +4 -1
  138. data/spec_app/spec/javascripts/helpers/to_match_url.coffee +1 -0
  139. data/spec_app/spec/javascripts/helpers/trigger.js.coffee +91 -7
  140. data/spec_app/spec/javascripts/helpers/wait_until_dom_ready.js.coffee +3 -0
  141. data/spec_app/spec/javascripts/up/browser_spec.js.coffee +23 -90
  142. data/spec_app/spec/javascripts/up/classes/cache_spec.js.coffee +3 -0
  143. data/spec_app/spec/javascripts/up/classes/config_spec.coffee +24 -0
  144. data/spec_app/spec/javascripts/up/classes/divertible_chain_spec.coffee +45 -0
  145. data/spec_app/spec/javascripts/up/classes/focus_tracker_spec.coffee +5 -2
  146. data/spec_app/spec/javascripts/up/classes/params_spec.coffee +557 -0
  147. data/spec_app/spec/javascripts/up/classes/request_spec.coffee +7 -4
  148. data/spec_app/spec/javascripts/up/classes/scroll_motion_spec.js.coffee +51 -0
  149. data/spec_app/spec/javascripts/up/classes/store/memory_spec.js.coffee +3 -0
  150. data/spec_app/spec/javascripts/up/classes/store/session_spec.js.coffee +3 -2
  151. data/spec_app/spec/javascripts/up/element_spec.coffee +897 -0
  152. data/spec_app/spec/javascripts/up/event_spec.js.coffee +496 -0
  153. data/spec_app/spec/javascripts/up/feedback_spec.js.coffee +69 -48
  154. data/spec_app/spec/javascripts/up/form_spec.js.coffee +252 -194
  155. data/spec_app/spec/javascripts/up/{dom_spec.js.coffee → fragment_spec.js.coffee} +381 -388
  156. data/spec_app/spec/javascripts/up/history_spec.js.coffee +21 -19
  157. data/spec_app/spec/javascripts/up/jquery_spec.js.coffee +4 -0
  158. data/spec_app/spec/javascripts/up/legacy_spec.js.coffee +27 -0
  159. data/spec_app/spec/javascripts/up/link_spec.js.coffee +163 -160
  160. data/spec_app/spec/javascripts/up/log_spec.js.coffee +85 -12
  161. data/spec_app/spec/javascripts/up/modal_spec.js.coffee +141 -123
  162. data/spec_app/spec/javascripts/up/motion_spec.js.coffee +117 -113
  163. data/spec_app/spec/javascripts/up/popup_spec.js.coffee +60 -77
  164. data/spec_app/spec/javascripts/up/protocol_spec.js.coffee +1 -0
  165. data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +85 -78
  166. data/spec_app/spec/javascripts/up/radio_spec.js.coffee +29 -22
  167. data/spec_app/spec/javascripts/up/rails_spec.js.coffee +14 -13
  168. data/spec_app/spec/javascripts/up/spec_spec.js.coffee +9 -0
  169. data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +96 -66
  170. data/spec_app/spec/javascripts/up/toast_spec.js.coffee +37 -0
  171. data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +31 -47
  172. data/spec_app/spec/javascripts/up/util_spec.js.coffee +725 -562
  173. data/spec_app/spec/javascripts/up/{layout_spec.js.coffee → viewport_spec.js.coffee} +175 -149
  174. metadata +57 -19
  175. data/lib/assets/javascripts/unpoly-bootstrap3/layout-ext.coffee +0 -5
  176. data/lib/assets/javascripts/unpoly/bus.coffee.erb +0 -518
  177. data/lib/assets/javascripts/unpoly/classes/extract_step.coffee +0 -4
  178. data/lib/assets/javascripts/unpoly/classes/motion_tracker.coffee +0 -125
  179. data/lib/assets/javascripts/unpoly/params.coffee.erb +0 -522
  180. data/spec_app/spec/javascripts/helpers/append_fixture.js.coffee +0 -8
  181. data/spec_app/spec/javascripts/up/bus_spec.js.coffee +0 -210
  182. data/spec_app/spec/javascripts/up/namespace_spec.js.coffee +0 -9
  183. data/spec_app/spec/javascripts/up/params_spec.coffee +0 -768
  184. data/spec_app/vendor/asset-libs/jasmine-fixture-1.3.4/jasmine-fixture.js +0 -433
  185. data/spec_app/vendor/asset-libs/jasmine-jquery-2.1.1/.bower.json +0 -26
  186. data/spec_app/vendor/asset-libs/jasmine-jquery-2.1.1/jasmine-jquery.js +0 -838
@@ -1,6 +1,7 @@
1
- describe 'up.radio', ->
1
+ u = up.util
2
+ $ = jQuery
2
3
 
3
- u = up.util
4
+ describe 'up.radio', ->
4
5
 
5
6
  describe 'JavaScript functions', ->
6
7
 
@@ -9,8 +10,8 @@ describe 'up.radio', ->
9
10
  describe '[up-hungry]', ->
10
11
 
11
12
  it "replaces the element when it is found in a response, even when the element wasn't targeted", asyncSpec (next) ->
12
- affix('.hungry[up-hungry]').text('old hungry')
13
- affix('.target').text('old target')
13
+ $fixture('.hungry[up-hungry]').text('old hungry')
14
+ $fixture('.target').text('old target')
14
15
 
15
16
  up.replace('.target', '/path')
16
17
 
@@ -32,8 +33,8 @@ describe 'up.radio', ->
32
33
  expect('.hungry').toHaveText('new hungry')
33
34
 
34
35
  it "does not impede replacements when the element is not part of a response", asyncSpec (next) ->
35
- affix('.hungry[up-hungry]').text('old hungry')
36
- affix('.target').text('old target')
36
+ $fixture('.hungry[up-hungry]').text('old hungry')
37
+ $fixture('.target').text('old target')
37
38
 
38
39
  promise = up.replace('.target', '/path')
39
40
 
@@ -52,10 +53,10 @@ describe 'up.radio', ->
52
53
  expect(result.state).toEqual('fulfilled')
53
54
 
54
55
  it 'still reveals the element that was originally targeted', asyncSpec (next) ->
55
- affix('.hungry[up-hungry]').text('old hungry')
56
- affix('.target').text('old target')
56
+ $fixture('.hungry[up-hungry]').text('old hungry')
57
+ $fixture('.target').text('old target')
57
58
 
58
- revealStub = up.layout.knife.mock('reveal')
59
+ revealStub = up.viewport.knife.mock('reveal')
59
60
 
60
61
  up.replace('.target', '/path', reveal: true)
61
62
 
@@ -69,14 +70,14 @@ describe 'up.radio', ->
69
70
  next =>
70
71
  expect(revealStub).toHaveBeenCalled()
71
72
  revealArg = revealStub.calls.mostRecent().args[0]
72
- expect(revealArg).not.toBeMatchedBy('.hungry')
73
- expect(revealArg).toBeMatchedBy('.target')
73
+ expect(revealArg).not.toMatchSelector('.hungry')
74
+ expect(revealArg).toMatchSelector('.target')
74
75
 
75
76
 
76
77
  it 'does not change the X-Up-Target header for the request', asyncSpec (next) ->
77
- affix('.hungry[up-hungry]').text('old hungry')
78
- affix('.target').text('old target')
79
- affix('.fail-target').text('old fail target')
78
+ $fixture('.hungry[up-hungry]').text('old hungry')
79
+ $fixture('.target').text('old target')
80
+ $fixture('.fail-target').text('old fail target')
80
81
 
81
82
  up.replace('.target', '/path', failTarget: '.fail-target')
82
83
 
@@ -85,9 +86,9 @@ describe 'up.radio', ->
85
86
  expect(@lastRequest().requestHeaders['X-Up-Fail-Target']).toEqual('.fail-target')
86
87
 
87
88
  it 'does replace the element when the server responds with an error (e.g. for error flashes)', asyncSpec (next) ->
88
- affix('.hungry[up-hungry]').text('old hungry')
89
- affix('.target').text('old target')
90
- affix('.fail-target').text('old fail target')
89
+ $fixture('.hungry[up-hungry]').text('old hungry')
90
+ $fixture('.target').text('old target')
91
+ $fixture('.fail-target').text('old fail target')
91
92
 
92
93
  up.replace('.target', '/path', failTarget: '.fail-target')
93
94
 
@@ -109,9 +110,15 @@ describe 'up.radio', ->
109
110
  </div>
110
111
  """
111
112
 
113
+ next =>
114
+ expect('.target').toHaveText('old target')
115
+ expect('.fail-target').toHaveText('new fail target')
116
+ expect('.hungry').toHaveText('new hungry')
117
+
118
+
112
119
  it 'does not update [up-hungry] elements with { hungry: false } option', asyncSpec (next) ->
113
- affix('.hungry[up-hungry]').text('old hungry')
114
- affix('.target').text('old target')
120
+ $fixture('.hungry[up-hungry]').text('old hungry')
121
+ $fixture('.target').text('old target')
115
122
 
116
123
  up.replace('.target', '/path', hungry: false)
117
124
 
@@ -134,7 +141,7 @@ describe 'up.radio', ->
134
141
  up.modal.config.openDuration = 0
135
142
  up.modal.config.closeDuration = 0
136
143
 
137
- affix('.outside').text('old outside').attr('up-hungry', true)
144
+ $fixture('.outside').text('old outside').attr('up-hungry', true)
138
145
 
139
146
  closeEventHandler = jasmine.createSpy('close event handler')
140
147
  up.on('up:modal:close', closeEventHandler)
@@ -169,8 +176,8 @@ describe 'up.radio', ->
169
176
  up.popup.config.openDuration = 0
170
177
  up.popup.config.closeDuration = 0
171
178
 
172
- affix('.outside').text('old outside').attr('up-hungry', true)
173
- $popupAnchor = affix('span.link').text('link')
179
+ $fixture('.outside').text('old outside').attr('up-hungry', true)
180
+ $popupAnchor = $fixture('span.link').text('link')
174
181
 
175
182
  closeEventHandler = jasmine.createSpy('close event handler')
176
183
  up.on('up:popup:close', closeEventHandler)
@@ -1,6 +1,7 @@
1
- describe 'up.rails', ->
1
+ u = up.util
2
+ $ = jQuery
2
3
 
3
- u = up.util
4
+ describe 'up.rails', ->
4
5
 
5
6
  upAttributes = ['up-follow', 'up-target', 'up-modal', 'up-popup']
6
7
 
@@ -21,19 +22,19 @@ describe 'up.rails', ->
21
22
  describe "on an [#{upAttribute}] element", ->
22
23
 
23
24
  it "is transformed to an up-method attribute so the element isn't handled a second time by Rails UJS", ->
24
- $element = affix("a[href=\"/foo\"][#{upAttribute}][data-method=\"put\"]")
25
+ $element = $fixture("a[href=\"/foo\"][#{upAttribute}][data-method=\"put\"]")
25
26
  up.hello($element)
26
27
  expect($element.attr('data-method')).toBeUndefined()
27
28
  expect($element.attr('up-method')).toEqual('put')
28
29
 
29
30
  it "does not overwrite an existing up-method attribute, but gets deleted", ->
30
- $element = affix("a[href=\"/foo\"][#{upAttribute}][up-method=\"patch\"][data-method=\"put\"]")
31
+ $element = $fixture("a[href=\"/foo\"][#{upAttribute}][up-method=\"patch\"][data-method=\"put\"]")
31
32
  up.hello($element)
32
33
  expect($element.attr('data-method')).toBeUndefined()
33
34
  expect($element.attr('up-method')).toEqual('patch')
34
35
 
35
36
  it 'transforms an element that becomes followable through [up-expand]', ->
36
- $element = affix('a[up-expand][data-method="put"]')
37
+ $element = $fixture('a[up-expand][data-method="put"]')
37
38
  $child = $element.affix('span[up-href="/foo"][up-follow]')
38
39
  up.hello($element)
39
40
  expect($element.attr('up-href')).toEqual('/foo')
@@ -42,8 +43,8 @@ describe 'up.rails', ->
42
43
  expect($element.attr('up-method')).toEqual('put')
43
44
 
44
45
  it 'transforms an element that becomes followable through a user macro like [content-link]', ->
45
- up.macro '[user-make-followable]', ($element) -> $element.attr('up-follow', '')
46
- $element = affix('a[user-make-followable][data-method="put"]')
46
+ up.$macro '[user-make-followable]', ($element) -> $element.attr('up-follow', '')
47
+ $element = $fixture('a[user-make-followable][data-method="put"]')
47
48
  up.hello($element)
48
49
  expect($element.attr('data-method')).toBeUndefined()
49
50
  expect($element.attr('up-method')).toEqual('put')
@@ -51,7 +52,7 @@ describe 'up.rails', ->
51
52
  describe 'on an element without Unpoly attributes', ->
52
53
 
53
54
  it "is not changed", ->
54
- $element = affix("a[href=\"/foo\"][data-method=\"put\"]")
55
+ $element = $fixture("a[href=\"/foo\"][data-method=\"put\"]")
55
56
  up.hello($element)
56
57
  expect($element.attr('data-method')).toEqual('put')
57
58
 
@@ -64,7 +65,7 @@ describe 'up.rails', ->
64
65
  describe "on an [#{upAttribute}] element", ->
65
66
 
66
67
  it "is not changed", ->
67
- $element = affix("a[href=\"/foo\"][#{upAttribute}][data-method=\"put\"]")
68
+ $element = $fixture("a[href=\"/foo\"][#{upAttribute}][data-method=\"put\"]")
68
69
  up.hello($element)
69
70
  expect($element.attr('data-method')).toEqual('put')
70
71
 
@@ -85,13 +86,13 @@ describe 'up.rails', ->
85
86
  describe "on an [#{upAttribute}] element", ->
86
87
 
87
88
  it "is transformed to an up-confirm attribute so the element isn't handled a second time by Rails UJS", ->
88
- $element = affix("a[href=\"/foo\"][#{upAttribute}][data-confirm=\"Really?\"]")
89
+ $element = $fixture("a[href=\"/foo\"][#{upAttribute}][data-confirm=\"Really?\"]")
89
90
  up.hello($element)
90
91
  expect($element.attr('data-confirm')).toBeUndefined()
91
92
  expect($element.attr('up-confirm')).toEqual('Really?')
92
93
 
93
94
  it "does not overwrite an existing up-confirm attribute, but gets deleted", ->
94
- $element = affix("a[href=\"/foo\"][#{upAttribute}][up-confirm=\"Seriously?\"][data-confirm=\"Really?\"]")
95
+ $element = $fixture("a[href=\"/foo\"][#{upAttribute}][up-confirm=\"Seriously?\"][data-confirm=\"Really?\"]")
95
96
  up.hello($element)
96
97
  expect($element.attr('data-confirm')).toBeUndefined()
97
98
  expect($element.attr('up-confirm')).toEqual('Seriously?')
@@ -99,7 +100,7 @@ describe 'up.rails', ->
99
100
  describe 'on an element without Unpoly attributes', ->
100
101
 
101
102
  it "is not changed", ->
102
- $element = affix("a[href=\"/foo\"][data-confirm=\"Really?\"]")
103
+ $element = $fixture("a[href=\"/foo\"][data-confirm=\"Really?\"]")
103
104
  up.hello($element)
104
105
  expect($element.attr('data-confirm')).toEqual('Really?')
105
106
 
@@ -112,6 +113,6 @@ describe 'up.rails', ->
112
113
  describe "on an [#{upAttribute}] element", ->
113
114
 
114
115
  it "is not changed", ->
115
- $element = affix("a[href=\"/foo\"][#{upAttribute}][data-confirm=\"Really?\"]")
116
+ $element = $fixture("a[href=\"/foo\"][#{upAttribute}][data-confirm=\"Really?\"]")
116
117
  up.hello($element)
117
118
  expect($element.attr('data-confirm')).toEqual('Really?')
@@ -0,0 +1,9 @@
1
+ u = up.util
2
+ $ = jQuery
3
+
4
+ describe 'Jasmine setup', ->
5
+
6
+ it 'does not consider a jQuery collection to be equal to its contained element (which is what jasmine-jquery does and which makes out expectations too soft)', ->
7
+ element = document.createElement('div')
8
+ $element = $(element)
9
+ expect($element).not.toEqual(element)
@@ -1,30 +1,34 @@
1
+ u = up.util
2
+ $ = jQuery
3
+
1
4
  describe 'up.syntax', ->
2
5
 
3
- u = up.util
4
-
5
6
  describe 'JavaScript functions', ->
6
7
 
7
8
  describe 'up.compiler', ->
8
9
 
9
10
  it 'applies an event initializer whenever a matching fragment is inserted', ->
10
-
11
- observeClass = jasmine.createSpy()
12
- up.compiler '.child', ($element) ->
13
- observeClass($element.attr('class'))
14
-
15
- up.hello(affix('.container .child'))
11
+ observeElement = jasmine.createSpy()
12
+ up.compiler '.child', (element) -> observeElement(element)
13
+
14
+ $container = $fixture('.container')
15
+ $child = $container.affix('.child')
16
+ $otherChild = $container.affix('.other-child')
17
+
18
+ up.hello($container[0])
16
19
 
17
- expect(observeClass).not.toHaveBeenCalledWith('container')
18
- expect(observeClass).toHaveBeenCalledWith('child')
20
+ expect(observeElement).not.toHaveBeenCalledWith($container[0])
21
+ expect(observeElement).not.toHaveBeenCalledWith($otherChild[0])
22
+ expect(observeElement).toHaveBeenCalledWith($child[0])
19
23
 
20
24
  describe 'destructors', ->
21
25
 
22
26
  it 'allows compilers to return a function to call when the compiled element is destroyed', asyncSpec (next) ->
23
27
  destructor = jasmine.createSpy('destructor')
24
- up.compiler '.child', ($element) ->
28
+ up.compiler '.child', (element) ->
25
29
  destructor
26
30
 
27
- up.hello(affix('.container .child'))
31
+ up.hello(fixture('.container .child'))
28
32
 
29
33
  next =>
30
34
  expect(destructor).not.toHaveBeenCalled()
@@ -36,10 +40,10 @@ describe 'up.syntax', ->
36
40
  it 'allows compilers to return an array of functions to call when the compiled element is destroyed', asyncSpec (next) ->
37
41
  destructor1 = jasmine.createSpy('destructor1')
38
42
  destructor2 = jasmine.createSpy('destructor2')
39
- up.compiler '.child', ($element) ->
43
+ up.compiler '.child', (element) ->
40
44
  [ destructor1, destructor2 ]
41
45
 
42
- up.hello(affix('.container .child'))
46
+ up.hello(fixture('.container .child'))
43
47
 
44
48
  next =>
45
49
  expect(destructor1).not.toHaveBeenCalled()
@@ -54,10 +58,10 @@ describe 'up.syntax', ->
54
58
  it "does not consider a returned array to be a destructor unless it's comprised entirely of functions", asyncSpec (next) ->
55
59
  value1 = jasmine.createSpy('non-destructor')
56
60
  value2 = 'two'
57
- up.compiler '.child', ($element) ->
61
+ up.compiler '.child', (element) ->
58
62
  [ value1, value2 ]
59
63
 
60
- up.hello(affix('.container .child'))
64
+ up.hello(fixture('.container .child'))
61
65
 
62
66
  next =>
63
67
  expect(value1).not.toHaveBeenCalled()
@@ -69,28 +73,28 @@ describe 'up.syntax', ->
69
73
 
70
74
  it 'runs all destructors if multiple compilers are applied to the same element', asyncSpec (next) ->
71
75
  destructor1 = jasmine.createSpy('destructor1')
72
- up.compiler '.one', ($element) -> destructor1
76
+ up.compiler '.one', (element) -> destructor1
73
77
  destructor2 = jasmine.createSpy('destructor2')
74
- up.compiler '.two', ($element) -> destructor2
78
+ up.compiler '.two', (element) -> destructor2
75
79
 
76
- $element = affix('.one.two')
80
+ $element = $fixture('.one.two')
77
81
  up.hello($element)
78
82
 
79
83
  next =>
80
84
  expect(destructor1).not.toHaveBeenCalled()
81
85
  expect(destructor2).not.toHaveBeenCalled()
82
86
 
83
- up.destroy($element)
87
+ up.destroy($element[0])
84
88
 
85
89
  next =>
86
90
  expect(destructor1).toHaveBeenCalled()
87
91
  expect(destructor2).toHaveBeenCalled()
88
92
 
89
93
  it 'does not throw an error if both container and child have a destructor, and the container gets destroyed', asyncSpec (next) ->
90
- up.compiler '.container', ($element) ->
94
+ up.compiler '.container', (element) ->
91
95
  return (->)
92
96
 
93
- up.compiler '.child', ($element) ->
97
+ up.compiler '.child', (element) ->
94
98
  return (->)
95
99
 
96
100
  promise = up.destroy('.container')
@@ -102,63 +106,62 @@ describe 'up.syntax', ->
102
106
 
103
107
  it 'parses an [up-data] attribute as JSON and passes the parsed object as a second argument to the compiler', ->
104
108
  observeArgs = jasmine.createSpy()
105
- up.compiler '.child', ($element, data) ->
106
- observeArgs($element.attr('class'), data)
109
+ up.compiler '.child', (element, data) ->
110
+ observeArgs(element.className, data)
107
111
 
108
112
  data = { key1: 'value1', key2: 'value2' }
109
113
 
110
- $tag = affix(".child").attr('up-data', JSON.stringify(data))
111
- up.hello($tag)
114
+ $tag = $fixture(".child").attr('up-data', JSON.stringify(data))
115
+ up.hello($tag[0])
112
116
 
113
117
  expect(observeArgs).toHaveBeenCalledWith('child', data)
114
118
 
115
119
  it 'passes an empty object as a second argument to the compiler if there is no [up-data] attribute', ->
116
120
  observeArgs = jasmine.createSpy()
117
- up.compiler '.child', ($element, data) ->
118
- observeArgs($element.attr('class'), data)
121
+ up.compiler '.child', (element, data) ->
122
+ observeArgs(element.className, data)
119
123
 
120
- up.hello(affix(".child"))
124
+ up.hello(fixture(".child"))
121
125
 
122
126
  expect(observeArgs).toHaveBeenCalledWith('child', {})
123
127
 
124
128
  it 'does not parse an [up-data] attribute if the compiler function only takes a single argument', ->
125
129
  parseDataSpy = spyOn(up.syntax, 'data').and.returnValue({})
126
130
 
127
- $child = affix(".child")
131
+ $child = $fixture(".child")
128
132
 
129
- up.compiler '.child', ($element) -> # no-op
133
+ up.compiler '.child', (element) -> # no-op
130
134
  up.hello($child)
131
135
 
132
136
  expect(parseDataSpy).not.toHaveBeenCalled()
133
137
 
134
- it 'compiles matching elements one-by-one', ->
138
+ it 'compiles multiple matching elements one-by-one', ->
135
139
  compiler = jasmine.createSpy('compiler')
136
- up.compiler '.foo', ($element) -> compiler($element)
137
- $container = affix('.container')
140
+ up.compiler '.foo', (element) -> compiler(element)
141
+ $container = $fixture('.container')
138
142
  $first = $container.affix('.foo.first')
139
143
  $second = $container.affix('.foo.second')
140
- up.hello($container)
144
+ up.hello($container[0])
141
145
  expect(compiler.calls.count()).toEqual(2)
142
- expect(compiler).toHaveBeenCalledWith($first)
143
- expect(compiler).toHaveBeenCalledWith($second)
146
+ expect(compiler).toHaveBeenCalledWith($first[0])
147
+ expect(compiler).toHaveBeenCalledWith($second[0])
144
148
 
145
149
  describe 'with { batch } option', ->
146
150
 
147
151
  it 'compiles all matching elements at once', ->
148
152
  compiler = jasmine.createSpy('compiler')
149
- up.compiler '.foo', { batch: true }, ($element) -> compiler($element)
150
- $container = affix('.container')
151
- $first = $container.affix('.foo.first')
152
- $second = $container.affix('.foo.second')
153
- $both = $first.add($second)
153
+ up.compiler '.foo', { batch: true }, (elements) -> compiler(elements)
154
+ $container = $fixture('.container')
155
+ first = $container.affix('.foo.first')[0]
156
+ second = $container.affix('.foo.second')[0]
154
157
  up.hello($container)
155
158
  expect(compiler.calls.count()).toEqual(1)
156
- expect(compiler).toHaveBeenCalledWith($both)
159
+ expect(compiler).toHaveBeenCalledWith([first, second])
157
160
 
158
161
  it 'throws an error if the batch compiler returns a destructor', ->
159
162
  destructor = ->
160
- up.compiler '.element', { batch: true }, ($element) -> destructor
161
- $container = affix('.element')
163
+ up.compiler '.element', { batch: true }, (element) -> destructor
164
+ $container = $fixture('.element')
162
165
  compile = -> up.hello($container)
163
166
  expect(compile).toThrowError(/cannot return destructor/i)
164
167
 
@@ -171,10 +174,10 @@ describe 'up.syntax', ->
171
174
  up.compiler '.bar', { keep: false }, ->
172
175
  up.compiler '.bam', { keep: '.partner' }, ->
173
176
 
174
- $foo = up.hello(affix('.foo'))
175
- $bar = up.hello(affix('.bar'))
176
- $baz = up.hello(affix('.baz'))
177
- $bam = up.hello(affix('.bam'))
177
+ $foo = $ up.hello(fixture('.foo'))
178
+ $bar = $ up.hello(fixture('.bar'))
179
+ $baz = $ up.hello(fixture('.baz'))
180
+ $bam = $ up.hello(fixture('.bam'))
178
181
 
179
182
  expect($foo.attr('up-keep')).toEqual('')
180
183
  expect($bar.attr('up-keep')).toBeMissing()
@@ -190,7 +193,7 @@ describe 'up.syntax', ->
190
193
  up.compiler '.element', { priority: 0 }, -> traces.push('baz')
191
194
  up.compiler '.element', { priority: 3 }, -> traces.push('bam')
192
195
  up.compiler '.element', { priority: -1 }, -> traces.push('qux')
193
- up.hello(affix('.element'))
196
+ up.hello(fixture('.element'))
194
197
  expect(traces).toEqual ['bam', 'bar', 'foo', 'baz', 'qux']
195
198
 
196
199
  it 'considers priority-less compilers to be priority zero', ->
@@ -198,16 +201,30 @@ describe 'up.syntax', ->
198
201
  up.compiler '.element', { priority: 1 }, -> traces.push('foo')
199
202
  up.compiler '.element', -> traces.push('bar')
200
203
  up.compiler '.element', { priority: -1 }, -> traces.push('baz')
201
- up.hello(affix('.element'))
204
+ up.hello(fixture('.element'))
202
205
  expect(traces).toEqual ['foo', 'bar', 'baz']
203
206
 
204
207
  it 'runs two compilers with the same priority in the order in which they were registered', ->
205
208
  traces = []
206
209
  up.compiler '.element', { priority: 1 }, -> traces.push('foo')
207
210
  up.compiler '.element', { priority: 1 }, -> traces.push('bar')
208
- up.hello(affix('.element'))
211
+ up.hello(fixture('.element'))
209
212
  expect(traces).toEqual ['foo', 'bar']
210
213
 
214
+ describe 'up.$compiler', ->
215
+
216
+ it 'registers a compiler that receives the element as a jQuery collection', ->
217
+ observeElement = jasmine.createSpy()
218
+ up.$compiler '.element', ($element) -> observeElement($element)
219
+
220
+ $element = $fixture('.element')
221
+ up.hello($element)
222
+
223
+ expect(observeElement).toHaveBeenCalled()
224
+ arg = observeElement.calls.argsFor(0)[0]
225
+ expect(arg).toBeJQuery()
226
+ expect(arg).toEqual($element)
227
+
211
228
  describe 'up.macro', ->
212
229
 
213
230
  it 'registers compilers that are run before other compilers', ->
@@ -215,7 +232,7 @@ describe 'up.syntax', ->
215
232
  up.compiler '.element', { priority: 10 }, -> traces.push('foo')
216
233
  up.compiler '.element', { priority: -1000 }, -> traces.push('bar')
217
234
  up.macro '.element', -> traces.push('baz')
218
- up.hello(affix('.element'))
235
+ up.hello(fixture('.element'))
219
236
  expect(traces).toEqual ['baz', 'foo' , 'bar']
220
237
 
221
238
  it 'allows to macros to have priorities of their own', ->
@@ -226,33 +243,49 @@ describe 'up.syntax', ->
226
243
  up.macro '.element', { priority: 3 }, -> traces.push('bam')
227
244
  up.macro '.element', { priority: -1 }, -> traces.push('qux')
228
245
  up.compiler '.element', { priority: 999 }, -> traces.push('ccc')
229
- up.hello(affix('.element'))
246
+ up.hello(fixture('.element'))
230
247
  expect(traces).toEqual ['bam', 'bar', 'foo', 'baz', 'qux', 'ccc']
231
248
 
232
249
  it 'runs two macros with the same priority in the order in which they were registered', ->
233
250
  traces = []
234
251
  up.macro '.element', { priority: 1 }, -> traces.push('foo')
235
252
  up.macro '.element', { priority: 1 }, -> traces.push('bar')
236
- up.hello(affix('.element'))
253
+ up.hello(fixture('.element'))
237
254
  expect(traces).toEqual ['foo', 'bar']
238
255
 
239
256
  it 'allows users to use the built-in [up-expand] from their own macros', ->
240
- up.macro '.element', ($element) ->
241
- $element.attr('up-expand', '')
242
- $element = affix('.element a[href="/foo"][up-target=".target"]')
257
+ up.macro '.element', (element) ->
258
+ element.setAttribute('up-expand', '')
259
+ $element = $fixture('.element a[href="/foo"][up-target=".target"]')
243
260
  up.hello($element)
244
261
  expect($element.attr('up-target')).toEqual('.target')
245
262
  expect($element.attr('up-href')).toEqual('/foo')
246
263
 
247
264
  it 'allows users to use the built-in [up-dash] from their own macros', ->
248
- up.macro '.element', ($element) ->
249
- $element.attr('up-dash', '.target')
250
- $element = affix('a.element[href="/foo"]')
265
+ up.macro '.element', (element) ->
266
+ element.setAttribute('up-dash', '.target')
267
+ $element = $fixture('a.element[href="/foo"]')
251
268
  up.hello($element)
252
269
  expect($element.attr('up-target')).toEqual('.target')
253
270
  expect($element.attr('up-preload')).toEqual('')
254
271
  expect($element.attr('up-instant')).toEqual('')
255
272
 
273
+ describe 'up.$macro', ->
274
+
275
+ it 'registers a macro that receives the element as a jQuery collection', ->
276
+ observeElement = jasmine.createSpy()
277
+ up.$macro '.element', ($element) -> observeElement('macro', $element)
278
+ up.$compiler '.element', ($element) -> observeElement('compiler', $element)
279
+
280
+ $element = $fixture('.element')
281
+ up.hello($element)
282
+
283
+ expect(observeElement).toHaveBeenCalled()
284
+ args = observeElement.calls.argsFor(0)
285
+ expect(args[0]).toEqual('macro')
286
+ expect(args[1]).toBeJQuery()
287
+ expect(args[1]).toEqual($element)
288
+
256
289
  describe 'up.hello', ->
257
290
 
258
291
  it 'should have tests'
@@ -260,15 +293,12 @@ describe 'up.syntax', ->
260
293
  describe 'up.syntax.data', ->
261
294
 
262
295
  it 'returns the [up-data] attribute of the given element, parsed as JSON', ->
263
- $element = affix('.element').attr('up-data', '{ "foo": 1, "bar": 2 }')
296
+ $element = $fixture('.element').attr('up-data', '{ "foo": 1, "bar": 2 }')
264
297
  data = up.syntax.data($element)
265
298
  expect(data).toEqual(foo: 1, bar: 2)
266
299
 
267
300
  it 'returns en empty object if the given element has no [up-data] attribute', ->
268
- $element = affix('.element')
301
+ $element = $fixture('.element')
269
302
  data = up.syntax.data($element)
270
303
  expect(data).toEqual({})
271
304
 
272
- it 'returns undefined if undefined is passed instead of an element', ->
273
- data = up.syntax.data(undefined)
274
- expect(data).toBeUndefined()