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
@@ -2,23 +2,27 @@
2
2
  Fragment update API
3
3
  ===================
4
4
 
5
- This module exposes a low-level Javascript API to [change](/up.replace) or
5
+ The `up.fragment` module exposes a high-level Javascript API to [update](/up.replace) or
6
6
  [destroy](/up.destroy) page fragments.
7
7
 
8
+ Fragments are [compiled](/up.compiler) elements that can be updated from a server URL.
9
+ They also exist on a layer (page, modal, popup).
10
+
8
11
  Most of Unpoly's functionality (like [fragment links](/up.link) or [modals](/up.modal))
9
- is built from these functions. You can use them to extend Unpoly from your
12
+ is built from `up.fragment` functions. You may use them to extend Unpoly from your
10
13
  [custom Javascript](/up.syntax).
11
14
 
12
- @class up.dom
15
+ @module up.fragment
13
16
  ###
14
- up.dom = (($) ->
17
+ up.fragment = do ->
15
18
 
16
19
  u = up.util
20
+ e = up.element
17
21
 
18
22
  ###**
19
23
  Configures defaults for fragment insertion.
20
24
 
21
- @property up.dom.config
25
+ @property up.fragment.config
22
26
  @param {string} [options.fallbacks=['body']]
23
27
  When a fragment updates cannot find the requested element, Unpoly will try this list of alternative selectors.
24
28
 
@@ -34,7 +38,7 @@ up.dom = (($) ->
34
38
  By default this is not set and the original replacement's transition is used.
35
39
  @stable
36
40
  ###
37
- config = u.config
41
+ config = new up.Config
38
42
  fallbacks: ['body']
39
43
  fallbackTransition: null
40
44
 
@@ -43,48 +47,22 @@ up.dom = (($) ->
43
47
 
44
48
  setSource = (element, sourceUrl) ->
45
49
  unless sourceUrl is false
46
- $element = $(element)
47
50
  sourceUrl = u.normalizeUrl(sourceUrl) if u.isPresent(sourceUrl)
48
- $element.attr("up-source", sourceUrl)
51
+ element.setAttribute("up-source", sourceUrl)
49
52
 
50
53
  ###**
51
54
  Returns the URL the given element was retrieved from.
52
55
 
53
- @method up.dom.source
56
+ @method up.fragment.source
54
57
  @param {string|Element|jQuery} selectorOrElement
55
58
  @experimental
56
59
  ###
57
60
  source = (selectorOrElement) ->
58
- $element = $(selectorOrElement).closest('[up-source]')
59
- u.presence($element.attr("up-source")) || up.browser.url()
60
-
61
- ###**
62
- Resolves the given CSS selector (which might contain `&` references)
63
- to a full CSS selector without ampersands.
64
-
65
- If passed an `Element` or `jQuery` element, returns a CSS selector string
66
- for that element.
67
-
68
- @function up.dom.resolveSelector
69
- @param {string|Element|jQuery} selectorOrElement
70
- @param {string|Element|jQuery} origin
71
- The element that this selector resolution is relative to.
72
- That element's selector will be substituted for `&` ([like in Sass](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector)).
73
- @return {string}
74
- @internal
75
- ###
76
- resolveSelector = (selectorOrElement, origin) ->
77
- if u.isString(selectorOrElement)
78
- selector = selectorOrElement
79
- if u.contains(selector, '&')
80
- if u.isPresent(origin) # isPresent returns false for empty jQuery collection
81
- originSelector = u.selectorForElement(origin)
82
- selector = selector.replace(/\&/, originSelector)
83
- else
84
- up.fail("Found origin reference (%s) in selector %s, but no origin was given", '&', selector)
61
+ element = e.get(selectorOrElement)
62
+ if element = e.closest(element, '[up-source]')
63
+ element.getAttribute("up-source")
85
64
  else
86
- selector = u.selectorForElement(selectorOrElement)
87
- selector
65
+ up.browser.url()
88
66
 
89
67
  ###**
90
68
  Replaces elements on the current page with corresponding elements
@@ -103,7 +81,7 @@ up.dom = (($) ->
103
81
 
104
82
  We now replace the second `<div>`:
105
83
 
106
- up.replace('.two', '/new');
84
+ up.replace('.two', '/new')
107
85
 
108
86
  The server renders a response for `/new`:
109
87
 
@@ -181,7 +159,7 @@ up.dom = (($) ->
181
159
  @param {string} [options.method='get']
182
160
  The HTTP method to use for the request.
183
161
  @param {Object|FormData|string|Array} [options.params]
184
- [Parameters](/up.params) that should be sent as the request's payload.
162
+ [Parameters](/up.Params) that should be sent as the request's payload.
185
163
  @param {string} [options.transition='none']
186
164
  @param {string|boolean} [options.history=true]
187
165
  If a string is given, it is used as the URL the browser's location bar and history.
@@ -196,6 +174,8 @@ up.dom = (($) ->
196
174
  Whether to [reveal](/up.reveal) the new fragment when the server responds with an error.
197
175
 
198
176
  You can also pass a CSS selector for the element to reveal.
177
+ @param {number} [options.revealPadding}
178
+
199
179
  @param {boolean} [options.restoreScroll=false]
200
180
  If set to true, Unpoly will try to restore the scroll position
201
181
  of all the viewports around or below the updated element. The position
@@ -254,23 +234,25 @@ up.dom = (($) ->
254
234
  try
255
235
  improvedTarget = bestPreflightSelector(selectorOrElement, successOptions)
256
236
  improvedFailTarget = bestPreflightSelector(options.failTarget, failureOptions)
257
- catch e
237
+ catch error
258
238
  # Since we're an async function, we should not throw exceptions but return a rejected promise.
259
239
  # http://2ality.com/2016/03/promise-rejections-vs-exceptions.html
260
- return Promise.reject(e)
261
-
262
- request = new up.Request(
240
+ return Promise.reject(error)
241
+
242
+ requestAttrs = u.only options,
243
+ 'method',
244
+ 'data', # deprecated
245
+ 'params',
246
+ 'cache',
247
+ 'preload',
248
+ 'headers',
249
+ 'timeout'
250
+ u.assign requestAttrs,
263
251
  url: url
264
- method: options.method
265
- data: options.data # deprecated, use { params }
266
- params: options.params
267
252
  target: improvedTarget
268
253
  failTarget: improvedFailTarget
269
- cache: options.cache
270
- preload: options.preload
271
- headers: options.headers
272
- timeout: options.timeout
273
- )
254
+
255
+ request = new up.Request(requestAttrs)
274
256
 
275
257
  onSuccess = (response) ->
276
258
  processResponse(true, improvedTarget, request, response, successOptions)
@@ -343,7 +325,7 @@ up.dom = (($) ->
343
325
  html = '<div class="one">new one</div>' +
344
326
  '<div class="two">new two</div>';
345
327
 
346
- up.extract('.two', html);
328
+ up.extract('.two', html)
347
329
 
348
330
  Unpoly looks for the selector `.two` in the strings and updates its
349
331
  contents in the current page. The current page now looks like this:
@@ -371,7 +353,7 @@ up.dom = (($) ->
371
353
  keep: true
372
354
  layer: 'auto'
373
355
 
374
- up.layout.saveScroll() unless options.saveScroll == false
356
+ up.viewport.saveScroll() unless options.saveScroll == false
375
357
 
376
358
  u.rejectOnError ->
377
359
  # Allow callers to create the targeted element right before we swap.
@@ -391,22 +373,20 @@ up.dom = (($) ->
391
373
  # async swapElements() is scheduled for the next microtask and we must not change the options
392
374
  # for the previous iteration.
393
375
  swapOptions = u.merge(options, u.only(step, 'origin', 'reveal'))
394
-
395
- responseDoc.prepareForInsertion(step.$new)
396
-
397
- swapPromise = swapElements(step.$old, step.$new, step.pseudoClass, step.transition, swapOptions)
376
+ responseDoc.prepareForInsertion(step.newElement)
377
+ swapPromise = swapElements(step.oldElement, step.newElement, step.pseudoClass, step.transition, swapOptions)
398
378
  swapPromises.push(swapPromise)
399
379
 
400
380
  # Delay all further links in the promise chain until all fragments have been swapped
401
381
  Promise.all(swapPromises)
402
382
 
403
- bestPreflightSelector = (selector, options) ->
404
- cascade = new up.ExtractCascade(selector, options)
383
+ bestPreflightSelector = (selectorOrElement, options) ->
384
+ cascade = new up.ExtractCascade(selectorOrElement, options)
405
385
  cascade.bestPreflightSelector()
406
386
 
407
- bestMatchingSteps = (selector, response, options) ->
387
+ bestMatchingSteps = (selectorOrElement, response, options) ->
408
388
  options = u.merge(options, { response })
409
- cascade = new up.ExtractCascade(selector, options)
389
+ cascade = new up.ExtractCascade(selectorOrElement, options)
410
390
  cascade.bestMatchingSteps()
411
391
 
412
392
  updateHistoryAndTitle = (options) ->
@@ -414,47 +394,50 @@ up.dom = (($) ->
414
394
  up.history[options.historyMethod](options.history) if options.history
415
395
  document.title = options.title if u.isString(options.title)
416
396
 
417
- swapElements = ($old, $new, pseudoClass, transition, options) ->
397
+ swapElements = (oldElement, newElement, pseudoClass, transition, options) ->
418
398
  transition ||= 'none'
419
399
 
420
400
  # When the server responds with an error, or when the request method is not
421
401
  # reloadable (not GET), we keep the same source as before.
422
402
  if options.source == 'keep'
423
- options = u.merge(options, source: source($old))
403
+ options = u.merge(options, source: source(oldElement))
424
404
 
425
- # Remember where the element came from in case someone needs to up.reload($new) later.
426
- setSource($new, options.source)
405
+ # Remember where the element came from in case someone needs to up.reload(newElement) later.
406
+ setSource(newElement, options.source)
427
407
 
428
408
  if pseudoClass
429
409
  # Text nodes are wrapped in a .up-insertion container so we can
430
410
  # animate them and measure their position/size for scrolling.
431
411
  # This is not possible for container-less text nodes.
432
- $wrapper = $new.contents().wrapAll('<div class="up-insertion"></div>').parent()
412
+ wrapper = e.createFromSelector('.up-insertion')
413
+ while childNode = newElement.firstChild
414
+ wrapper.appendChild(childNode)
433
415
 
434
416
  # Note that since we're prepending/appending instead of replacing,
435
- # `$new` will not actually be inserted into the DOM, only its children.
417
+ # newElement will not actually be inserted into the DOM, only its children.
436
418
  if pseudoClass == 'before'
437
- $old.prepend($wrapper)
419
+ oldElement.insertAdjacentElement('afterbegin', wrapper)
438
420
  else
439
- $old.append($wrapper)
421
+ oldElement.insertAdjacentElement('beforeend', wrapper)
440
422
 
441
- hello($wrapper.children(), options)
423
+ for child in wrapper.children
424
+ hello(child, options)
442
425
 
443
426
  # Reveal element that was being prepended/appended.
444
427
  # Since we will animate (not morph) it's OK to allow animation of scrolling
445
- # if the user has configured up.layout.config.duration.
446
- promise = up.layout.scrollAfterInsertFragment($wrapper, options)
428
+ # if options.scrollBehavior is given.
429
+ promise = up.viewport.scrollAfterInsertFragment(wrapper, options)
447
430
 
448
431
  # Since we're adding content instead of replacing, we'll only
449
- # animate $new instead of morphing between $old and $new
450
- promise = promise.then -> up.animate($wrapper, transition, options)
432
+ # animate newElement instead of morphing between oldElement and newElement
433
+ promise = u.always(promise, up.animate(wrapper, transition, options))
451
434
 
452
435
  # Remove the wrapper now that is has served it purpose
453
- promise = promise.then -> u.unwrapElement($wrapper)
436
+ promise = promise.then -> e.unwrap(wrapper)
454
437
 
455
438
  return promise
456
439
 
457
- else if keepPlan = findKeepPlan($old, $new, options)
440
+ else if keepPlan = findKeepPlan(oldElement, newElement, options)
458
441
  # Since we're keeping the element that was requested to be swapped,
459
442
  # there is nothing left to do here, except notify event listeners.
460
443
  emitFragmentKept(keepPlan)
@@ -463,66 +446,70 @@ up.dom = (($) ->
463
446
  else
464
447
  # This needs to happen before prepareClean() below.
465
448
  # Otherwise we would collect destructors for elements we want to keep.
466
- options.keepPlans = transferKeepableElements($old, $new, options)
449
+ options.keepPlans = transferKeepableElements(oldElement, newElement, options)
467
450
 
468
- $parent = $old.parent()
451
+ parent = oldElement.parentNode
469
452
 
470
453
  morphOptions = u.merge options,
471
454
  beforeStart: ->
472
- markElementAsDestroying($old)
473
- emitFragmentDestroy($old, log: false)
455
+ markElementAsDestroying(oldElement)
474
456
  afterInsert: ->
475
- up.hello($new, options)
457
+ up.hello(newElement, options)
476
458
  beforeDetach: ->
477
- up.syntax.clean($old)
459
+ up.syntax.clean(oldElement)
478
460
  afterDetach: ->
479
- $old.remove() # clean up jQuery data
480
- emitFragmentDestroyed($old, $parent: $parent, log: false)
461
+ e.remove(oldElement) # clean up jQuery data
462
+ emitFragmentDestroyed(oldElement, parent: parent, log: false)
481
463
 
482
- return up.morph($old, $new, transition, morphOptions)
464
+ return up.morph(oldElement, newElement, transition, morphOptions)
483
465
 
484
466
 
485
- # This will find all [up-keep] descendants in $old an, overwrite their partner
486
- # element in $new and leave a visually identical clone in $old for a later transition.
467
+ # This will find all [up-keep] descendants in oldElement, overwrite their partner
468
+ # element in newElement and leave a visually identical clone in oldElement for a later transition.
487
469
  # Returns an array of keepPlans.
488
- transferKeepableElements = ($old, $new, options) ->
470
+ transferKeepableElements = (oldElement, newElement, options) ->
489
471
  keepPlans = []
490
472
  if options.keep
491
- for keepable in $old.find('[up-keep]')
492
- $keepable = $(keepable)
493
- if plan = findKeepPlan($keepable, $new, u.merge(options, descendantsOnly: true))
494
- # Replace $keepable with its clone so it looks good in a transition between
495
- # $old and $new. Note that $keepable will still point to the same element
473
+ for keepable in oldElement.querySelectorAll('[up-keep]')
474
+ if plan = findKeepPlan(keepable, newElement, u.merge(options, descendantsOnly: true))
475
+ # plan.oldElement is now keepable
476
+
477
+ # Replace keepable with its clone so it looks good in a transition between
478
+ # oldElement and newElement. Note that keepable will still point to the same element
496
479
  # after the replacement, which is now detached.
497
- $keepableClone = $keepable.clone()
498
- u.detachWith($keepable, $keepableClone)
480
+ keepableClone = keepable.cloneNode(true)
481
+ e.replace(keepable, keepableClone)
499
482
 
500
- # $keepable.replaceWith($keepableClone)
501
- # Since we're going to swap the entire $old and $new containers afterwards,
502
- # replace the matching element with $keepable so it will eventually return to the DOM.
503
- plan.$newElement.replaceWith($keepable)
483
+ # Since we're going to swap the entire oldElement and newElement containers afterwards,
484
+ # replace the matching element with keepable so it will eventually return to the DOM.
485
+ e.replace(plan.newElement, keepable)
504
486
  keepPlans.push(plan)
505
487
  keepPlans
506
488
 
507
489
 
508
- findKeepPlan = ($element, $new, options) ->
490
+ findKeepPlan = (element, newElement, options) ->
509
491
  if options.keep
510
- $keepable = $element
511
- if partnerSelector = u.castedAttr($keepable, 'up-keep')
492
+ keepable = element
493
+ if partnerSelector = e.booleanOrStringAttr(keepable, 'up-keep')
512
494
  u.isString(partnerSelector) or partnerSelector = '&'
513
- partnerSelector = resolveSelector(partnerSelector, $keepable)
495
+ partnerSelector = e.resolveSelector(partnerSelector, keepable)
514
496
  if options.descendantsOnly
515
- $partner = $new.find(partnerSelector)
497
+ partner = e.first(newElement, partnerSelector)
516
498
  else
517
- $partner = u.selectInSubtree($new, partnerSelector)
518
- $partner = $partner.first()
519
- if $partner.length && $partner.is('[up-keep]')
499
+ partner = e.subtree(newElement, partnerSelector)[0]
500
+ if partner && e.matches(partner, '[up-keep]')
520
501
  plan =
521
- $element: $keepable # the element that should be kept
522
- $newElement: $partner # the element that would have replaced it but now does not
523
- newData: up.syntax.data($partner) # the parsed up-data attribute of the element we will discard
524
- keepEventArgs = u.merge(plan, message: ['Keeping element %o', $keepable.get(0)])
525
- if up.bus.nobodyPrevents('up:fragment:keep', keepEventArgs)
502
+ oldElement: keepable # the element that should be kept
503
+ newElement: partner # the element that would have replaced it but now does not
504
+ newData: up.syntax.data(partner) # the parsed up-data attribute of the element we will discard
505
+
506
+ keepEventArgs =
507
+ target: keepable
508
+ newFragment: partner
509
+ newData: plan.newData
510
+ log: ['Keeping element %o', keepable]
511
+
512
+ if up.event.nobodyPrevents('up:fragment:keep', keepEventArgs)
526
513
  plan
527
514
 
528
515
  ###**
@@ -554,13 +541,13 @@ up.dom = (($) ->
554
541
  On the client we can achieve this by listening to an `up:keep:fragment` event
555
542
  and preventing it if the `src` attribute of the old and new element differ:
556
543
 
557
- up.compiler('audio', function($element) {
558
- $element.on('up:fragment:keep', function(event) {
559
- if $element.attr('src') !== event.$newElement.attr('src') {
560
- event.preventDefault();
544
+ up.compiler('audio', function(element) {
545
+ element.addEventListener('up:fragment:keep', function(event) {
546
+ if element.getAttribute('src') !== event.newElement.getAttribute('src') {
547
+ event.preventDefault()
561
548
  }
562
- });
563
- });
549
+ })
550
+ })
564
551
 
565
552
  If we don't want to solve this on the client, we can achieve the same effect
566
553
  on the server. By setting the value of the `up-keep` attribute we can
@@ -586,9 +573,9 @@ up.dom = (($) ->
586
573
  @event up:fragment:keep
587
574
  @param event.preventDefault()
588
575
  Event listeners may call this method to prevent the element from being preserved.
589
- @param {jQuery} event.$element
576
+ @param {Element} event.target
590
577
  The fragment that will be kept.
591
- @param {jQuery} event.$newElement
578
+ @param {Element} event.newFragment
592
579
  The discarded element.
593
580
  @param {Object} event.newData
594
581
  The value of the [`up-data`](/up-data) attribute of the discarded element,
@@ -600,16 +587,16 @@ up.dom = (($) ->
600
587
  This event is [emitted](/up.emit) when an existing element has been [kept](/up-keep)
601
588
  during a page update.
602
589
 
603
- Event listeners can inspect the discarded update through `event.$newElement`
590
+ Event listeners can inspect the discarded update through `event.newElement`
604
591
  and `event.newData` and then modify the preserved element when necessary.
605
592
 
606
593
  @event up:fragment:kept
607
- @param {jQuery} event.$element
594
+ @param {Element} event.target
608
595
  The fragment that has been kept.
609
- @param {jQuery} event.$newElement
610
- The discarded element.
596
+ @param {Element} event.newFragment
597
+ The discarded fragment.
611
598
  @param {Object} event.newData
612
- The value of the [`up-data`](/up-data) attribute of the discarded element,
599
+ The value of the [`up-data`](/up-data) attribute of the discarded fragment,
613
600
  parsed as a JSON object.
614
601
  @stable
615
602
  ###
@@ -624,9 +611,9 @@ up.dom = (($) ->
624
611
  the `innerHTML` property or calling jQuery methods like
625
612
  `html`, `insertAfter` or `appendTo`:
626
613
 
627
- $element = $('.element');
628
- $element.html('<div>...</div>');
629
- up.hello($element);
614
+ element = document.createElement('div')
615
+ element.innerHTML = '... HTML that needs to be activated ...'
616
+ up.hello(element)
630
617
 
631
618
  This function emits the [`up:fragment:inserted`](/up:fragment:inserted)
632
619
  event.
@@ -635,82 +622,98 @@ up.dom = (($) ->
635
622
  @param {string|Element|jQuery} selectorOrElement
636
623
  @param {string|Element|jQuery} [options.origin]
637
624
  @param {string|Element|jQuery} [options.kept]
638
- @return {jQuery}
625
+ @return {Element}
639
626
  The compiled element
640
627
  @stable
641
628
  ###
642
629
  hello = (selectorOrElement, options) ->
643
- $element = $(selectorOrElement)
630
+ element = e.get(selectorOrElement)
644
631
  options = u.options(options, keepPlans: [])
645
632
  keptElements = []
646
633
  for plan in options.keepPlans
647
634
  emitFragmentKept(plan)
648
- keptElements.push(plan.$element[0])
649
- up.syntax.compile($element, skip: keptElements)
650
- emitFragmentInserted($element, options)
651
- $element
635
+ keptElements.push(plan.oldElement)
636
+ up.syntax.compile(element, skip: keptElements)
637
+ emitFragmentInserted(element, options)
638
+ element
652
639
 
653
640
  ###**
654
- When a page fragment has been [inserted or updated](/up.replace),
641
+ When any page fragment has been [inserted or updated](/up.replace),
655
642
  this event is [emitted](/up.emit) on the fragment.
656
643
 
644
+ If you're looking to run code when a new fragment matches
645
+ a selector, use `up.compiler()` instead.
646
+
657
647
  \#\#\# Example
658
648
 
659
- up.on('up:fragment:inserted', function(event, $fragment) {
660
- console.log("Looks like we have a new %o!", $fragment);
661
- });
649
+ up.on('up:fragment:inserted', function(event, fragment) {
650
+ console.log("Looks like we have a new %o!", fragment)
651
+ })
662
652
 
663
653
  @event up:fragment:inserted
664
- @param {jQuery} event.$element
654
+ @param {Element} event.target
665
655
  The fragment that has been inserted or updated.
666
656
  @stable
667
657
  ###
668
- emitFragmentInserted = ($element, options) ->
669
- up.emit 'up:fragment:inserted',
670
- $element: $element
671
- message: ['Inserted fragment %o', $element.get(0)]
658
+ emitFragmentInserted = (element, options) ->
659
+ up.emit element, 'up:fragment:inserted',
660
+ log: ['Inserted fragment %o', element]
672
661
  origin: options.origin
673
662
 
674
663
  emitFragmentKept = (keepPlan) ->
675
- eventAttrs = u.merge(keepPlan, message: ['Kept fragment %o', keepPlan.$element.get(0)])
676
- up.emit('up:fragment:kept', eventAttrs)
677
-
678
- emitFragmentDestroy = ($element, options) ->
679
- if shouldLogDestruction($element, options)
680
- message = ['Destroying fragment %o', $element.get(0)]
681
- up.emit 'up:fragment:destroy', { $element, message }
664
+ keptElement = keepPlan.oldElement
665
+ eventAttrs =
666
+ target: keptElement,
667
+ newFragment: keepPlan.newElement
668
+ newData: keepPlan.newData
669
+ log: ['Kept fragment %o', keptElement]
682
670
 
683
- emitFragmentDestroyed = ($element, options) ->
684
- if shouldLogDestruction($element, options)
685
- message = ['Destroyed fragment %o', $element.get(0)]
686
-
687
- $parent = options.$parent or up.fail("Missing { $parent } option")
671
+ up.emit('up:fragment:kept', eventAttrs)
688
672
 
689
- up.emit 'up:fragment:destroyed',
690
- $target: $parent,
691
- $parent: $parent,
692
- $element: $element,
693
- message: message
673
+ emitFragmentDestroyed = (fragment, options) ->
674
+ if shouldLogDestruction(fragment, options)
675
+ log = ['Destroyed fragment %o', fragment]
676
+ parent = options.parent or up.fail("Missing { parent } option")
677
+ up.emit(parent, 'up:fragment:destroyed', { fragment, parent, log })
694
678
 
695
- isRealElement = ($element) ->
696
- unreal = '.up-destroying'
697
- $element.closest(unreal).length == 0
679
+ isRealElement = (element) ->
680
+ !e.closest(element, '.up-destroying')
698
681
 
699
682
  ###**
700
683
  Returns the first element matching the given selector, but
701
684
  ignores elements that are being [destroyed](/up.destroy) or that are being
702
685
  removed by a [transition](/up.morph).
703
686
 
704
- If the given argument is already a jQuery collection (or an array
705
- of DOM elements), the first element matching these conditions
706
- is returned.
707
-
708
687
  Returns `undefined` if no element matches these conditions.
709
688
 
710
- Also see the [`.up-destroying`](/up-destroying) class.
689
+ \#\#\# Example
690
+
691
+ To select the first element with the selector `.foo`:
692
+
693
+ var fooInModal = up.fragment.first('.foo')
694
+
695
+ You may also pass a `{ layer }` option to only match elements witin a layer:
696
+
697
+ var fooInModal = up.fragment.first('.foo', { layer: 'modal' })
698
+
699
+ You may also pass a root element as a first argument:
700
+
701
+ var container = up.fragment.first('.container')
702
+ var fooInContainer = up.fragment.first(container, '.foo')
711
703
 
712
- @function up.first
713
- @param {string|Element|jQuery|Array<Element>} selectorOrElement
704
+ \#\#\# Similar features
705
+
706
+ - The [`.up-destroying`](/up-destroying) class is assigned to elements during their removal animation.
707
+ - The [`up.element.first()`](/up.element.first) function simply returns the first element matching a selector
708
+ without further filtering.
709
+
710
+ @function up.fragment.first
711
+ @param {Element|jQuery} [root=document]
712
+ The root element for the search. Only the root's children will be matched.
713
+
714
+ May be omitted to search through all elements in the `document`.
715
+ @param {string} selector
716
+ The selector to match
714
717
  @param {string} [options.layer='auto']
715
718
  The name of the layer in which to find the element.
716
719
 
@@ -718,86 +721,63 @@ up.dom = (($) ->
718
721
  @param {string|Element|jQuery} [options.origin]
719
722
  An second element or selector that can be referenced as `&` in the first selector:
720
723
 
721
- $input = $('input.email');
722
- up.first('.field:has(&)', $input); // returns the .field containing $input
723
- @return {jQuery|undefined}
724
+ var input = document.querySelector('input.email')
725
+ up.fragment.first('fieldset:has(&)', { origin: input }) // returns the <fieldset> containing input
726
+ @return {Element|undefined}
724
727
  The first element that is neither a ghost or being destroyed,
725
728
  or `undefined` if no such element was found.
726
729
  @experimental
727
730
  ###
728
- first = (selectorOrElement, options) ->
729
- options = u.options(options, layer: 'auto')
730
- resolved = resolveSelector(selectorOrElement, options.origin)
731
- if options.layer == 'auto'
732
- firstInPriority(resolved, options.origin)
731
+ first = (args...) ->
732
+ options = u.extractOptions(args)
733
+ selector = args.pop()
734
+ root = args[0] || document
735
+ layer = options.layer ? 'auto'
736
+ origin = options.origin
737
+
738
+ selector = e.resolveSelector(selector, origin)
739
+ if layer == 'auto'
740
+ firstInPriority(root, selector, origin)
733
741
  else
734
- firstInLayer(resolved, options.layer)
742
+ firstInLayer(root, selector, layer)
735
743
 
736
- firstInPriority = (selectorOrElement, origin) ->
744
+ firstInPriority = (parent, selector, origin) ->
737
745
  layers = ['popup', 'modal', 'page']
738
- $match = undefined
739
- if u.isPresent(origin)
746
+ if origin
740
747
  originLayer = layerOf(origin)
741
748
  # Make the origin's layer the top priority
742
749
  u.remove(layers, originLayer)
743
750
  layers.unshift(originLayer)
744
- for layer in layers
745
- if $match = firstInLayer(selectorOrElement, layer)
746
- break
747
- $match
748
-
749
- firstInLayer = (selectorOrElement, layer) ->
750
- $elements = $(selectorOrElement)
751
- $match = undefined
752
- for element in $elements
753
- $element = $(element)
754
- if isRealElement($element) && matchesLayer($element, layer)
755
- $match = $element
756
- break
757
- $match
751
+ u.findResult layers, (layer) ->
752
+ return firstInLayer(parent, selector, layer)
753
+
754
+ firstInLayer = (parent, selector, layer) ->
755
+ elements = e.all(parent, selector)
756
+ return u.findResult elements, (element) ->
757
+ if isRealElement(element) && matchesLayer(element, layer)
758
+ return element
758
759
 
759
760
  ###**
760
- @function up.dom.layerOf
761
+ @function up.fragment.layerOf
761
762
  @internal
762
763
  ###
763
- layerOf = (selectorOrElement) ->
764
- $element = $(selectorOrElement)
765
- if $element.length
766
- if up.popup.contains($element)
767
- 'popup'
768
- else if up.modal.contains($element)
769
- 'modal'
770
- else
771
- 'page'
764
+ layerOf = (element) ->
765
+ if up.popup.contains(element)
766
+ 'popup'
767
+ else if up.modal.contains(element)
768
+ 'modal'
769
+ else
770
+ 'page'
772
771
 
773
- matchesLayer = (selectorOrElement, layer) ->
774
- !layer || layerOf(selectorOrElement) == layer
772
+ matchesLayer = (element, layer) ->
773
+ !layer || layerOf(element) == layer
775
774
 
776
775
  ###**
777
- Returns all elements matching the given selector, but
778
- ignores elements that are being [destroyed](/up.destroy) or [transitioned](/up.morph).
779
-
780
- If the given argument is already a jQuery collection (or an array
781
- of DOM elements), returns the subset of the given list that is matching these conditions.
782
-
783
- @function up.all
784
- @param {string|jQuery|Array<Element>} selectorOrElements
785
- @param {string|Element|jQuery} [options.origin]
786
- An second element or selector that can be referenced as `&` in the first selector.
787
- @param {string} [options.layer]
788
- The name of the layer in which to find the element. Valid values are
789
- `'page'`, `'modal'` and `'popup'`.
790
- @return {jQuery}
791
- A jQuery collection of matching elements.
792
- @experimental
776
+ @function up.fragment.createPlaceHolder
777
+ @internal
793
778
  ###
794
- all = (selectorOrElements, options) ->
795
- options = u.options(options)
796
- resolved = resolveSelector(selectorOrElements, options.origin)
797
- $root = $(u.option(options.root, document))
798
- $root.find(resolved).filter (index, element) ->
799
- $element = $(element)
800
- isRealElement($element) && matchesLayer($element, options.layer)
779
+ createPlaceholder = (selector, container = document.body) ->
780
+ e.affix(container, selector, class: 'up-placeholder')
801
781
 
802
782
  ###**
803
783
  Destroys the given element or selector.
@@ -808,7 +788,7 @@ up.dom = (($) ->
808
788
  Note that if you choose to animate the element removal using `options.animate`,
809
789
  the element won't be removed until after the animation has completed.
810
790
 
811
- Emits events [`up:fragment:destroy`](/up:fragment:destroy) and [`up:fragment:destroyed`](/up:fragment:destroyed).
791
+ Emits events [`up:fragment:destroyed`](/up:fragment:destroyed).
812
792
 
813
793
  @function up.destroy
814
794
  @param {string|Element|jQuery} selectorOrElement
@@ -816,7 +796,7 @@ up.dom = (($) ->
816
796
  A URL that will be pushed as a new history entry when the element begins destruction.
817
797
  @param {string} [options.title]
818
798
  The document title to set when the element begins destruction.
819
- @param {string|Function} [options.animation='none']
799
+ @param {string|Function(element, options): Promise} [options.animation='none']
820
800
  The animation to use before the element is removed from the DOM.
821
801
  @param {number} [options.duration]
822
802
  The duration of the animation. See [`up.animate()`](/up.animate).
@@ -829,59 +809,46 @@ up.dom = (($) ->
829
809
  @stable
830
810
  ###
831
811
  destroy = (selectorOrElement, options) ->
832
- $element = $(selectorOrElement)
812
+ element = e.get(selectorOrElement)
833
813
  options = u.options(options, animation: false)
834
814
 
835
- if $element.length == 0
815
+ unless element
836
816
  return Promise.resolve()
837
817
 
838
- markElementAsDestroying($element)
839
- emitFragmentDestroy($element, options)
818
+ markElementAsDestroying(element)
840
819
 
841
820
  updateHistoryAndTitle(options)
842
821
 
843
822
  animate = ->
844
823
  animateOptions = up.motion.animateOptions(options)
845
- up.motion.animate($element, options.animation, animateOptions)
824
+ up.motion.animate(element, options.animation, animateOptions)
846
825
 
847
826
  wipe = ->
848
- $parent = $element.parent()
849
- up.syntax.clean($element)
850
- $element.remove()
851
- emitFragmentDestroyed($element, { $parent })
827
+ parent = element.parentNode
828
+ up.syntax.clean(element)
829
+ e.remove(element)
830
+ emitFragmentDestroyed(element, { parent: parent, log: options.log })
852
831
 
853
832
  animate().then(wipe)
854
833
 
855
- shouldLogDestruction = ($element, options) ->
834
+ shouldLogDestruction = (element, options) ->
856
835
  # Don't log destruction for elements that are either Unpoly internals or frequently destroyed
857
- options.log != false && !$element.is('.up-placeholder, .up-tooltip, .up-modal, .up-popup')
836
+ options.log != false && !e.matches(element, '.up-placeholder, .up-tooltip, .up-modal, .up-popup')
858
837
 
859
838
  ###**
860
839
  Elements are assigned the `.up-destroying` class before they are [destroyed](/up.destroy)
861
840
  or while they are being removed by a [transition](/up.morph).
862
841
 
863
- If the removal is animated, the class is assigned before the animation.
842
+ If the removal is animated, the class is assigned before the animation starts.
864
843
 
865
- Also see the [`up.first()`](/up.first) function.
844
+ To select an element while ignoring elements that are being destroyed,
845
+ see the [`up.fragment.first()`](/up.fragment.first) function.
866
846
 
867
847
  @selector .up-destroying
868
848
  @stable
869
849
  ###
870
- markElementAsDestroying = ($element) ->
871
- $element.addClass('up-destroying')
872
-
873
- ###**
874
- Before a page fragment is being [destroyed](/up.destroy), this
875
- event is [emitted](/up.emit) on the fragment.
876
-
877
- If the destruction is animated, this event is emitted before the
878
- animation begins.
879
-
880
- @event up:fragment:destroy
881
- @param {jQuery} event.$element
882
- The page fragment that is about to be destroyed.
883
- @stable
884
- ###
850
+ markElementAsDestroying = (element) ->
851
+ element.classList.add('up-destroying')
885
852
 
886
853
  ###**
887
854
  This event is [emitted](/up.emit) after a page fragment was [destroyed](/up.destroy) and removed from the DOM.
@@ -891,10 +858,12 @@ up.dom = (($) ->
891
858
  The event is emitted on the parent element of the fragment that was removed.
892
859
 
893
860
  @event up:fragment:destroyed
894
- @param {jQuery} event.$element
895
- The page fragment that has been removed from the DOM.
896
- @param {jQuery} event.$parent
897
- The parent element of the fragment that has been removed from the DOM.
861
+ @param {Element} event.fragment
862
+ The detached element that has been removed from the DOM.
863
+ @param {Element} event.parent
864
+ The former parent element of the fragment that has now been detached from the DOM.
865
+ @param {Element} event.target
866
+ The former parent element of the fragment that has now been detached from the DOM.
898
867
  @stable
899
868
  ###
900
869
 
@@ -903,9 +872,7 @@ up.dom = (($) ->
903
872
 
904
873
  \#\#\# Example
905
874
 
906
- up.on('new-mail', function() {
907
- up.reload('.inbox');
908
- });
875
+ up.on('new-mail', function() { up.reload('.inbox') })
909
876
 
910
877
  Unpoly remembers the URL from which a fragment was loaded, so you
911
878
  don't usually need to give an URL when reloading.
@@ -925,33 +892,33 @@ up.dom = (($) ->
925
892
  replace(selectorOrElement, sourceUrl, options)
926
893
 
927
894
  up.on 'up:app:boot', ->
928
- $body = $(document.body)
929
- setSource($body, up.browser.url())
930
- hello($body)
895
+ body = document.body
896
+ setSource(body, up.browser.url())
897
+ hello(body)
931
898
 
932
899
  up.on 'up:framework:reset', reset
933
900
 
934
901
  <% if ENV['JS_KNIFE'] %>knife: eval(Knife.point)<% end %>
902
+ createPlaceholder: createPlaceholder
935
903
  replace: replace
936
904
  reload: reload
937
905
  destroy: destroy
938
906
  extract: extract
939
907
  first: first
940
- all: all
941
908
  source: source
942
- resolveSelector: resolveSelector
943
909
  hello: hello
944
910
  config: config
945
911
  layerOf: layerOf
946
912
 
947
- )(jQuery)
913
+ up.replace = up.fragment.replace
914
+ up.extract = up.fragment.extract
915
+ up.reload = up.fragment.reload
916
+ up.destroy = up.fragment.destroy
917
+ up.hello = up.fragment.hello
948
918
 
949
- up.replace = up.dom.replace
950
- up.extract = up.dom.extract
951
- up.reload = up.dom.reload
952
- up.destroy = up.dom.destroy
953
- up.first = up.dom.first
954
- up.all = up.dom.all
955
- up.hello = up.dom.hello
919
+ up.first = (args...) ->
920
+ up.legacy.warn('up.first() has been renamed to up.fragment.first()')
921
+ up.fragment.first(args...)
956
922
 
957
- up.deprecateRenamedModule 'flow', 'dom'
923
+ up.legacy.renamedModule 'flow', 'fragment'
924
+ up.legacy.renamedModule 'dom', 'fragment'