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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +393 -1
- data/Gemfile.lock +5 -2
- data/README.md +1 -1
- data/README_RAILS.md +1 -1
- data/Rakefile +10 -1
- data/design/es6.js +32 -0
- data/design/ie11.txt +9 -0
- data/design/measure_jquery/element_list.js +41 -0
- data/design/measure_jquery/up.on_vs_addEventListener.js +56 -0
- data/design/todo_jquery.txt +13 -0
- data/dist/unpoly-bootstrap3.js +8 -8
- data/dist/unpoly-bootstrap3.min.js +1 -1
- data/dist/unpoly.css +22 -20
- data/dist/unpoly.js +6990 -5336
- data/dist/unpoly.min.css +1 -1
- data/dist/unpoly.min.js +4 -4
- data/lib/assets/javascripts/unpoly-bootstrap3/viewport-ext.coffee +5 -0
- data/lib/assets/javascripts/unpoly.coffee +8 -6
- data/lib/assets/javascripts/unpoly/browser.coffee.erb +23 -118
- data/lib/assets/javascripts/unpoly/classes/body_shifter.coffee +36 -0
- data/lib/assets/javascripts/unpoly/classes/cache.coffee +4 -4
- data/lib/assets/javascripts/unpoly/classes/compile_pass.coffee +45 -39
- data/lib/assets/javascripts/unpoly/classes/config.coffee +9 -0
- data/lib/assets/javascripts/unpoly/classes/css_transition.coffee +18 -27
- data/lib/assets/javascripts/unpoly/classes/divertible_chain.coffee +39 -0
- data/lib/assets/javascripts/unpoly/classes/event_listener.coffee +116 -0
- data/lib/assets/javascripts/unpoly/classes/extract_cascade.coffee +8 -8
- data/lib/assets/javascripts/unpoly/classes/extract_plan.coffee +19 -19
- data/lib/assets/javascripts/unpoly/classes/field_observer.coffee +54 -31
- data/lib/assets/javascripts/unpoly/classes/{focus_tracker.coffee → focus_follower.coffee} +2 -2
- data/lib/assets/javascripts/unpoly/classes/follow_variant.coffee +25 -25
- data/lib/assets/javascripts/unpoly/classes/html_parser.coffee +4 -11
- data/lib/assets/javascripts/unpoly/classes/motion_controller.coffee +157 -0
- data/lib/assets/javascripts/unpoly/classes/params.coffee.erb +525 -0
- data/lib/assets/javascripts/unpoly/classes/record.coffee +8 -2
- data/lib/assets/javascripts/unpoly/classes/rect.js +21 -0
- data/lib/assets/javascripts/unpoly/classes/request.coffee +41 -35
- data/lib/assets/javascripts/unpoly/classes/response.coffee +7 -3
- data/lib/assets/javascripts/unpoly/classes/reveal_motion.coffee +102 -0
- data/lib/assets/javascripts/unpoly/classes/scroll_motion.coffee +67 -0
- data/lib/assets/javascripts/unpoly/classes/selector.coffee +60 -0
- data/lib/assets/javascripts/unpoly/classes/tether.coffee +105 -0
- data/lib/assets/javascripts/unpoly/classes/url_set.coffee +12 -7
- data/lib/assets/javascripts/unpoly/element.coffee.erb +1126 -0
- data/lib/assets/javascripts/unpoly/event.coffee.erb +437 -0
- data/lib/assets/javascripts/unpoly/feedback.coffee +73 -94
- data/lib/assets/javascripts/unpoly/form.coffee.erb +188 -181
- data/lib/assets/javascripts/unpoly/{dom.coffee.erb → fragment.coffee.erb} +250 -283
- data/lib/assets/javascripts/unpoly/framework.coffee +67 -0
- data/lib/assets/javascripts/unpoly/history.coffee +29 -28
- data/lib/assets/javascripts/unpoly/legacy.coffee +60 -0
- data/lib/assets/javascripts/unpoly/link.coffee.erb +127 -119
- data/lib/assets/javascripts/unpoly/log.coffee +99 -19
- data/lib/assets/javascripts/unpoly/modal.coffee.erb +95 -118
- data/lib/assets/javascripts/unpoly/motion.coffee.erb +158 -138
- data/lib/assets/javascripts/unpoly/namespace.coffee.erb +0 -5
- data/lib/assets/javascripts/unpoly/popup.coffee.erb +119 -102
- data/lib/assets/javascripts/unpoly/protocol.coffee +11 -15
- data/lib/assets/javascripts/unpoly/proxy.coffee +62 -65
- data/lib/assets/javascripts/unpoly/radio.coffee +3 -5
- data/lib/assets/javascripts/unpoly/rails.coffee +8 -9
- data/lib/assets/javascripts/unpoly/syntax.coffee.erb +173 -125
- data/lib/assets/javascripts/unpoly/toast.coffee +25 -24
- data/lib/assets/javascripts/unpoly/tooltip.coffee +89 -79
- data/lib/assets/javascripts/unpoly/util.coffee.erb +579 -1074
- data/lib/assets/javascripts/unpoly/{layout.coffee.erb → viewport.coffee.erb} +334 -264
- data/lib/assets/stylesheets/unpoly/dom.sass +1 -1
- data/lib/assets/stylesheets/unpoly/layout.sass +2 -0
- data/lib/assets/stylesheets/unpoly/popup.sass +0 -1
- data/lib/assets/stylesheets/unpoly/tooltip.sass +17 -12
- data/lib/unpoly/rails/version.rb +1 -1
- data/package.json +1 -2
- data/spec_app/Gemfile +2 -1
- data/spec_app/Gemfile.lock +38 -27
- data/spec_app/app/assets/javascripts/integration_test.coffee +1 -0
- data/spec_app/app/assets/javascripts/jasmine_specs.coffee +1 -2
- data/spec_app/app/assets/stylesheets/integration_test.sass +14 -1
- data/spec_app/app/controllers/scroll_test_controller.rb +5 -0
- data/spec_app/app/views/css_test/modal.erb +6 -6
- data/spec_app/app/views/css_test/popup.erb +44 -18
- data/spec_app/app/views/css_test/tooltip.erb +23 -4
- data/spec_app/app/views/error_test/trigger.erb +1 -1
- data/spec_app/app/views/form_test/basics/new.erb +1 -3
- data/spec_app/app/views/pages/start.erb +9 -2
- data/spec_app/app/views/reveal_test/long1.erb +1 -1
- data/spec_app/app/views/reveal_test/long2.erb +1 -1
- data/spec_app/app/views/reveal_test/within_document_viewport.erb +24 -0
- data/spec_app/app/views/reveal_test/within_overflowing_div_viewport.erb +28 -0
- data/spec_app/app/views/scroll_test/long1.erb +30 -0
- data/spec_app/config/routes.rb +1 -0
- data/spec_app/spec/javascripts/helpers/agent_detector.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/async_sequence.js.coffee +1 -0
- data/spec_app/spec/javascripts/helpers/browser_switches.js.coffee +17 -5
- data/spec_app/spec/javascripts/helpers/enable_logging.js.coffee +1 -1
- data/spec_app/spec/javascripts/helpers/fixture.js.coffee +25 -0
- data/spec_app/spec/javascripts/helpers/jquery_no_conflict.js +1 -0
- data/spec_app/spec/javascripts/helpers/last_request.js.coffee +1 -0
- data/spec_app/spec/javascripts/helpers/mock_ajax.js.coffee +1 -1
- data/spec_app/spec/javascripts/helpers/parse_form_data.js.coffee +2 -2
- data/spec_app/spec/javascripts/helpers/protect_jasmine_runner.coffee +4 -1
- data/spec_app/spec/javascripts/helpers/remove_body_margin.js.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/reset_history.js.coffee +2 -1
- data/spec_app/spec/javascripts/helpers/reset_knife.js.coffee +2 -2
- data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +18 -11
- data/spec_app/spec/javascripts/helpers/restore_body_scroll.js.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/show_lib_versions.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/spec_util.coffee +47 -0
- data/spec_app/spec/javascripts/helpers/to_be_around.js.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_be_array.coffee +5 -0
- data/spec_app/spec/javascripts/helpers/to_be_attached.coffee +6 -2
- data/spec_app/spec/javascripts/helpers/to_be_blank.js.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_be_detached.coffee +6 -2
- data/spec_app/spec/javascripts/helpers/to_be_element.js.coffee +8 -0
- data/spec_app/spec/javascripts/helpers/to_be_error.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_be_given.js.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_be_hidden.js.coffee +8 -0
- data/spec_app/spec/javascripts/helpers/to_be_missing.js.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_be_present.js.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_be_scrolled_to.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_be_visible.js.coffee +9 -0
- data/spec_app/spec/javascripts/helpers/to_contain.js.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_end_with.js.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_equal_jquery.js.coffee +1 -2
- data/spec_app/spec/javascripts/helpers/to_equal_node_list.coffee +7 -0
- data/spec_app/spec/javascripts/helpers/to_equal_via_is_equal.js.coffee +7 -0
- data/spec_app/spec/javascripts/helpers/to_have_class.js.coffee +10 -0
- data/spec_app/spec/javascripts/helpers/to_have_descendant.js.coffee +10 -0
- data/spec_app/spec/javascripts/helpers/to_have_length.js.coffee +8 -0
- data/spec_app/spec/javascripts/helpers/to_have_opacity.coffee +7 -3
- data/spec_app/spec/javascripts/helpers/to_have_own_property.js.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_have_request_method.js.coffee +1 -0
- data/spec_app/spec/javascripts/helpers/to_have_text.js.coffee +9 -0
- data/spec_app/spec/javascripts/helpers/to_have_unhandled_rejections.coffee +0 -21
- data/spec_app/spec/javascripts/helpers/to_match_list.coffee +14 -0
- data/spec_app/spec/javascripts/helpers/to_match_selector.coffee +3 -0
- data/spec_app/spec/javascripts/helpers/to_match_text.js.coffee +4 -1
- data/spec_app/spec/javascripts/helpers/to_match_url.coffee +1 -0
- data/spec_app/spec/javascripts/helpers/trigger.js.coffee +91 -7
- data/spec_app/spec/javascripts/helpers/wait_until_dom_ready.js.coffee +3 -0
- data/spec_app/spec/javascripts/up/browser_spec.js.coffee +23 -90
- data/spec_app/spec/javascripts/up/classes/cache_spec.js.coffee +3 -0
- data/spec_app/spec/javascripts/up/classes/config_spec.coffee +24 -0
- data/spec_app/spec/javascripts/up/classes/divertible_chain_spec.coffee +45 -0
- data/spec_app/spec/javascripts/up/classes/focus_tracker_spec.coffee +5 -2
- data/spec_app/spec/javascripts/up/classes/params_spec.coffee +557 -0
- data/spec_app/spec/javascripts/up/classes/request_spec.coffee +7 -4
- data/spec_app/spec/javascripts/up/classes/scroll_motion_spec.js.coffee +51 -0
- data/spec_app/spec/javascripts/up/classes/store/memory_spec.js.coffee +3 -0
- data/spec_app/spec/javascripts/up/classes/store/session_spec.js.coffee +3 -2
- data/spec_app/spec/javascripts/up/element_spec.coffee +897 -0
- data/spec_app/spec/javascripts/up/event_spec.js.coffee +496 -0
- data/spec_app/spec/javascripts/up/feedback_spec.js.coffee +69 -48
- data/spec_app/spec/javascripts/up/form_spec.js.coffee +252 -194
- data/spec_app/spec/javascripts/up/{dom_spec.js.coffee → fragment_spec.js.coffee} +381 -388
- data/spec_app/spec/javascripts/up/history_spec.js.coffee +21 -19
- data/spec_app/spec/javascripts/up/jquery_spec.js.coffee +4 -0
- data/spec_app/spec/javascripts/up/legacy_spec.js.coffee +27 -0
- data/spec_app/spec/javascripts/up/link_spec.js.coffee +163 -160
- data/spec_app/spec/javascripts/up/log_spec.js.coffee +85 -12
- data/spec_app/spec/javascripts/up/modal_spec.js.coffee +141 -123
- data/spec_app/spec/javascripts/up/motion_spec.js.coffee +117 -113
- data/spec_app/spec/javascripts/up/popup_spec.js.coffee +60 -77
- data/spec_app/spec/javascripts/up/protocol_spec.js.coffee +1 -0
- data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +85 -78
- data/spec_app/spec/javascripts/up/radio_spec.js.coffee +29 -22
- data/spec_app/spec/javascripts/up/rails_spec.js.coffee +14 -13
- data/spec_app/spec/javascripts/up/spec_spec.js.coffee +9 -0
- data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +96 -66
- data/spec_app/spec/javascripts/up/toast_spec.js.coffee +37 -0
- data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +31 -47
- data/spec_app/spec/javascripts/up/util_spec.js.coffee +725 -562
- data/spec_app/spec/javascripts/up/{layout_spec.js.coffee → viewport_spec.js.coffee} +175 -149
- metadata +57 -19
- data/lib/assets/javascripts/unpoly-bootstrap3/layout-ext.coffee +0 -5
- data/lib/assets/javascripts/unpoly/bus.coffee.erb +0 -518
- data/lib/assets/javascripts/unpoly/classes/extract_step.coffee +0 -4
- data/lib/assets/javascripts/unpoly/classes/motion_tracker.coffee +0 -125
- data/lib/assets/javascripts/unpoly/params.coffee.erb +0 -522
- data/spec_app/spec/javascripts/helpers/append_fixture.js.coffee +0 -8
- data/spec_app/spec/javascripts/up/bus_spec.js.coffee +0 -210
- data/spec_app/spec/javascripts/up/namespace_spec.js.coffee +0 -9
- data/spec_app/spec/javascripts/up/params_spec.coffee +0 -768
- data/spec_app/vendor/asset-libs/jasmine-fixture-1.3.4/jasmine-fixture.js +0 -433
- data/spec_app/vendor/asset-libs/jasmine-jquery-2.1.1/.bower.json +0 -26
- 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
|
-
|
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
|
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
|
-
@
|
15
|
+
@module up.fragment
|
13
16
|
###
|
14
|
-
up.
|
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.
|
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 =
|
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
|
-
|
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.
|
56
|
+
@method up.fragment.source
|
54
57
|
@param {string|Element|jQuery} selectorOrElement
|
55
58
|
@experimental
|
56
59
|
###
|
57
60
|
source = (selectorOrElement) ->
|
58
|
-
|
59
|
-
|
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
|
-
|
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.
|
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
|
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(
|
261
|
-
|
262
|
-
|
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
|
-
|
270
|
-
|
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.
|
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
|
-
|
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 = (
|
404
|
-
cascade = new up.ExtractCascade(
|
383
|
+
bestPreflightSelector = (selectorOrElement, options) ->
|
384
|
+
cascade = new up.ExtractCascade(selectorOrElement, options)
|
405
385
|
cascade.bestPreflightSelector()
|
406
386
|
|
407
|
-
bestMatchingSteps = (
|
387
|
+
bestMatchingSteps = (selectorOrElement, response, options) ->
|
408
388
|
options = u.merge(options, { response })
|
409
|
-
cascade = new up.ExtractCascade(
|
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 = (
|
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(
|
403
|
+
options = u.merge(options, source: source(oldElement))
|
424
404
|
|
425
|
-
# Remember where the element came from in case someone needs to up.reload(
|
426
|
-
setSource(
|
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
|
-
|
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
|
-
#
|
417
|
+
# newElement will not actually be inserted into the DOM, only its children.
|
436
418
|
if pseudoClass == 'before'
|
437
|
-
|
419
|
+
oldElement.insertAdjacentElement('afterbegin', wrapper)
|
438
420
|
else
|
439
|
-
|
421
|
+
oldElement.insertAdjacentElement('beforeend', wrapper)
|
440
422
|
|
441
|
-
|
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
|
446
|
-
promise = up.
|
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
|
450
|
-
promise = promise
|
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 ->
|
436
|
+
promise = promise.then -> e.unwrap(wrapper)
|
454
437
|
|
455
438
|
return promise
|
456
439
|
|
457
|
-
else if keepPlan = findKeepPlan(
|
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(
|
449
|
+
options.keepPlans = transferKeepableElements(oldElement, newElement, options)
|
467
450
|
|
468
|
-
|
451
|
+
parent = oldElement.parentNode
|
469
452
|
|
470
453
|
morphOptions = u.merge options,
|
471
454
|
beforeStart: ->
|
472
|
-
markElementAsDestroying(
|
473
|
-
emitFragmentDestroy($old, log: false)
|
455
|
+
markElementAsDestroying(oldElement)
|
474
456
|
afterInsert: ->
|
475
|
-
up.hello(
|
457
|
+
up.hello(newElement, options)
|
476
458
|
beforeDetach: ->
|
477
|
-
up.syntax.clean(
|
459
|
+
up.syntax.clean(oldElement)
|
478
460
|
afterDetach: ->
|
479
|
-
|
480
|
-
emitFragmentDestroyed(
|
461
|
+
e.remove(oldElement) # clean up jQuery data
|
462
|
+
emitFragmentDestroyed(oldElement, parent: parent, log: false)
|
481
463
|
|
482
|
-
return up.morph(
|
464
|
+
return up.morph(oldElement, newElement, transition, morphOptions)
|
483
465
|
|
484
466
|
|
485
|
-
# This will find all [up-keep] descendants in
|
486
|
-
# element in
|
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 = (
|
470
|
+
transferKeepableElements = (oldElement, newElement, options) ->
|
489
471
|
keepPlans = []
|
490
472
|
if options.keep
|
491
|
-
for keepable in
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
#
|
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
|
-
|
498
|
-
|
480
|
+
keepableClone = keepable.cloneNode(true)
|
481
|
+
e.replace(keepable, keepableClone)
|
499
482
|
|
500
|
-
#
|
501
|
-
#
|
502
|
-
|
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 = (
|
490
|
+
findKeepPlan = (element, newElement, options) ->
|
509
491
|
if options.keep
|
510
|
-
|
511
|
-
if partnerSelector =
|
492
|
+
keepable = element
|
493
|
+
if partnerSelector = e.booleanOrStringAttr(keepable, 'up-keep')
|
512
494
|
u.isString(partnerSelector) or partnerSelector = '&'
|
513
|
-
partnerSelector = resolveSelector(partnerSelector,
|
495
|
+
partnerSelector = e.resolveSelector(partnerSelector, keepable)
|
514
496
|
if options.descendantsOnly
|
515
|
-
|
497
|
+
partner = e.first(newElement, partnerSelector)
|
516
498
|
else
|
517
|
-
|
518
|
-
|
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
|
-
|
522
|
-
|
523
|
-
newData: up.syntax.data(
|
524
|
-
|
525
|
-
|
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(
|
558
|
-
|
559
|
-
if
|
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 {
|
576
|
+
@param {Element} event.target
|
590
577
|
The fragment that will be kept.
|
591
|
-
@param {
|
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
|
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 {
|
594
|
+
@param {Element} event.target
|
608
595
|
The fragment that has been kept.
|
609
|
-
@param {
|
610
|
-
The discarded
|
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
|
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
|
-
|
628
|
-
|
629
|
-
up.hello(
|
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 {
|
625
|
+
@return {Element}
|
639
626
|
The compiled element
|
640
627
|
@stable
|
641
628
|
###
|
642
629
|
hello = (selectorOrElement, options) ->
|
643
|
-
|
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
|
649
|
-
up.syntax.compile(
|
650
|
-
emitFragmentInserted(
|
651
|
-
|
635
|
+
keptElements.push(plan.oldElement)
|
636
|
+
up.syntax.compile(element, skip: keptElements)
|
637
|
+
emitFragmentInserted(element, options)
|
638
|
+
element
|
652
639
|
|
653
640
|
###**
|
654
|
-
When
|
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,
|
660
|
-
console.log("Looks like we have a new %o!",
|
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 {
|
654
|
+
@param {Element} event.target
|
665
655
|
The fragment that has been inserted or updated.
|
666
656
|
@stable
|
667
657
|
###
|
668
|
-
emitFragmentInserted = (
|
669
|
-
up.emit 'up:fragment:inserted',
|
670
|
-
|
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
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
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
|
-
|
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
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
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 = (
|
696
|
-
|
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
|
-
|
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
|
-
|
713
|
-
|
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
|
-
|
722
|
-
up.first('
|
723
|
-
@return {
|
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 = (
|
729
|
-
options = u.
|
730
|
-
|
731
|
-
|
732
|
-
|
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(
|
742
|
+
firstInLayer(root, selector, layer)
|
735
743
|
|
736
|
-
firstInPriority = (
|
744
|
+
firstInPriority = (parent, selector, origin) ->
|
737
745
|
layers = ['popup', 'modal', 'page']
|
738
|
-
|
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
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
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.
|
761
|
+
@function up.fragment.layerOf
|
761
762
|
@internal
|
762
763
|
###
|
763
|
-
layerOf = (
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
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 = (
|
774
|
-
!layer || layerOf(
|
772
|
+
matchesLayer = (element, layer) ->
|
773
|
+
!layer || layerOf(element) == layer
|
775
774
|
|
776
775
|
###**
|
777
|
-
|
778
|
-
|
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
|
-
|
795
|
-
|
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:
|
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
|
-
|
812
|
+
element = e.get(selectorOrElement)
|
833
813
|
options = u.options(options, animation: false)
|
834
814
|
|
835
|
-
|
815
|
+
unless element
|
836
816
|
return Promise.resolve()
|
837
817
|
|
838
|
-
markElementAsDestroying(
|
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(
|
824
|
+
up.motion.animate(element, options.animation, animateOptions)
|
846
825
|
|
847
826
|
wipe = ->
|
848
|
-
|
849
|
-
up.syntax.clean(
|
850
|
-
|
851
|
-
emitFragmentDestroyed(
|
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 = (
|
834
|
+
shouldLogDestruction = (element, options) ->
|
856
835
|
# Don't log destruction for elements that are either Unpoly internals or frequently destroyed
|
857
|
-
options.log != false &&
|
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
|
-
|
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 = (
|
871
|
-
|
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 {
|
895
|
-
The
|
896
|
-
@param {
|
897
|
-
The parent element of the fragment that has been
|
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
|
-
|
929
|
-
setSource(
|
930
|
-
hello(
|
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
|
-
|
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.
|
950
|
-
up.
|
951
|
-
up.
|
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.
|
923
|
+
up.legacy.renamedModule 'flow', 'fragment'
|
924
|
+
up.legacy.renamedModule 'dom', 'fragment'
|