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
@@ -0,0 +1,67 @@
|
|
1
|
+
###**
|
2
|
+
@module up.framework
|
3
|
+
###
|
4
|
+
|
5
|
+
up.framework = do ->
|
6
|
+
|
7
|
+
u = up.util
|
8
|
+
|
9
|
+
isBooting = true
|
10
|
+
|
11
|
+
###**
|
12
|
+
Resets Unpoly to the state when it was booted.
|
13
|
+
All custom event handlers, animations, etc. that have been registered
|
14
|
+
will be discarded.
|
15
|
+
|
16
|
+
Emits event [`up:framework:reset`](/up:framework:reset).
|
17
|
+
|
18
|
+
@function up.framework.reset
|
19
|
+
@internal
|
20
|
+
###
|
21
|
+
emitReset = ->
|
22
|
+
up.emit('up:framework:reset', log: 'Resetting framework')
|
23
|
+
|
24
|
+
###**
|
25
|
+
This event is [emitted](/up.emit) when Unpoly is [reset](/up.framework.reset) during unit tests.
|
26
|
+
|
27
|
+
@event up:framework:reset
|
28
|
+
@internal
|
29
|
+
###
|
30
|
+
|
31
|
+
###**
|
32
|
+
Boots the Unpoly framework.
|
33
|
+
|
34
|
+
**This is called automatically** by including the Unpoly JavaScript files.
|
35
|
+
|
36
|
+
Unpoly will not boot if the current browser is [not supported](/up.browser.isSupported).
|
37
|
+
This leaves you with a classic server-side application on legacy browsers.
|
38
|
+
|
39
|
+
@function up.boot
|
40
|
+
@internal
|
41
|
+
###
|
42
|
+
boot = ->
|
43
|
+
if up.browser.isSupported()
|
44
|
+
# This is called synchronously after all Unpoly modules have been parsed
|
45
|
+
# and executed. User code hasn't been executed yet. Use this moment to
|
46
|
+
# tell everyone to snapshot
|
47
|
+
up.emit('up:framework:booted', log: 'Framework booted')
|
48
|
+
isBooting = false
|
49
|
+
|
50
|
+
# From here on, all event handlers (both Unpoly's and user code) should be able
|
51
|
+
# to work with the DOM, so wait for the DOM to be ready.
|
52
|
+
up.event.onReady ->
|
53
|
+
# In case the DOM was already ready when up.event.boot() was called, we still
|
54
|
+
# haven't executed user-provided code. So we wait one more frame until
|
55
|
+
# user-provided compilers, event handlers, etc. have been registered.
|
56
|
+
# This also gives async user-code a chance to run in the next microtask.
|
57
|
+
u.task ->
|
58
|
+
# At this point all user-code has been called.
|
59
|
+
# The following event will cause Unpoly to compile the <body>.
|
60
|
+
up.emit('up:app:boot', log: 'Booting user application')
|
61
|
+
up.emit('up:app:booted', log: 'User application booted')
|
62
|
+
else
|
63
|
+
console.log?("Unpoly doesn't support this browser. Framework was not booted.")
|
64
|
+
|
65
|
+
reset: emitReset
|
66
|
+
boot: boot
|
67
|
+
isBooting: -> isBooting
|
@@ -6,11 +6,12 @@ In an Unpoly app, every page has an URL.
|
|
6
6
|
|
7
7
|
[Fragment updates](/up.link) automatically update the URL.
|
8
8
|
|
9
|
-
@
|
9
|
+
@module up.history
|
10
10
|
###
|
11
|
-
up.history =
|
11
|
+
up.history = do ->
|
12
12
|
|
13
13
|
u = up.util
|
14
|
+
e = up.element
|
14
15
|
|
15
16
|
###**
|
16
17
|
Configures behavior when the user goes back or forward in browser history.
|
@@ -24,7 +25,7 @@ up.history = (($) ->
|
|
24
25
|
when the user goes back or forward in history.
|
25
26
|
@stable
|
26
27
|
###
|
27
|
-
config =
|
28
|
+
config = new up.Config
|
28
29
|
enabled: true
|
29
30
|
popTargets: ['body']
|
30
31
|
restoreScroll: true
|
@@ -119,11 +120,11 @@ up.history = (($) ->
|
|
119
120
|
push = (url, options) ->
|
120
121
|
options = u.options(options, force: false)
|
121
122
|
url = normalizeUrl(url)
|
122
|
-
if (options.force || !isCurrentUrl(url)) && up.
|
123
|
+
if (options.force || !isCurrentUrl(url)) && up.event.nobodyPrevents('up:history:push', url: url, log: "Adding history entry for #{url}")
|
123
124
|
if manipulate('pushState', url)
|
124
|
-
up.emit('up:history:pushed', url: url,
|
125
|
+
up.emit('up:history:pushed', url: url, log: "Advanced to location #{url}")
|
125
126
|
else
|
126
|
-
up.emit('up:history:muted', url: url,
|
127
|
+
up.emit('up:history:muted', url: url, log: "Did not advance to #{url} (history is unavailable)")
|
127
128
|
|
128
129
|
###**
|
129
130
|
This event is [emitted](/up.emit) before a new history entry is added.
|
@@ -162,27 +163,26 @@ up.history = (($) ->
|
|
162
163
|
url = currentUrl()
|
163
164
|
|
164
165
|
# We can't let people prevent this event, since `popstate` is also unpreventable.
|
165
|
-
up.emit('up:history:restore', url: url,
|
166
|
+
up.emit('up:history:restore', url: url, log: "Restoring location #{url}")
|
166
167
|
|
167
168
|
popSelector = config.popTargets.join(', ')
|
168
169
|
replaced = up.replace popSelector, url,
|
169
170
|
history: false, # don't push a new state
|
170
171
|
title: true, # do extract the title from the response
|
171
172
|
reveal: false,
|
172
|
-
transition: 'none',
|
173
173
|
saveScroll: false # since the URL was already changed by the browser, don't save scroll state
|
174
174
|
restoreScroll: config.restoreScroll
|
175
175
|
layer: 'page' # Don't replace elements in a modal that might still be open
|
176
176
|
replaced.then ->
|
177
177
|
url = currentUrl()
|
178
|
-
up.emit('up:history:restored', url: url,
|
178
|
+
up.emit('up:history:restored', url: url, log: "Restored location #{url}")
|
179
179
|
else
|
180
180
|
up.puts 'Ignoring a state not pushed by Unpoly (%o)', state
|
181
181
|
|
182
182
|
pop = (event) ->
|
183
183
|
observeNewUrl(currentUrl())
|
184
|
-
up.
|
185
|
-
state = event.
|
184
|
+
up.viewport.saveScroll(url: previousUrl)
|
185
|
+
state = event.state
|
186
186
|
restoreStateOnPop(state)
|
187
187
|
|
188
188
|
###**
|
@@ -207,19 +207,21 @@ up.history = (($) ->
|
|
207
207
|
@experimental
|
208
208
|
###
|
209
209
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
210
|
+
up.on 'up:app:boot', ->
|
211
|
+
if up.browser.canPushState()
|
212
|
+
register = ->
|
213
|
+
window.history.scrollRestoration = 'manual' if up.browser.canControlScrollRestoration()
|
214
|
+
window.addEventListener('popstate', pop)
|
215
|
+
replace(currentUrl(), force: true)
|
214
216
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
217
|
+
if jasmine?
|
218
|
+
# Can't delay this in tests.
|
219
|
+
register()
|
220
|
+
else
|
221
|
+
# Defeat an unnecessary popstate that some browsers trigger
|
222
|
+
# on pageload (Safari, Chrome < 34).
|
223
|
+
# We should check in 2023 if we can remove this.
|
224
|
+
setTimeout(register, 100)
|
223
225
|
|
224
226
|
###**
|
225
227
|
Changes the link's destination so it points to the previous URL.
|
@@ -246,13 +248,13 @@ up.history = (($) ->
|
|
246
248
|
@selector a[up-back]
|
247
249
|
@stable
|
248
250
|
###
|
249
|
-
up.macro 'a[up-back], [up-href][up-back]', (
|
251
|
+
up.macro 'a[up-back], [up-href][up-back]', (link) ->
|
250
252
|
if u.isPresent(previousUrl)
|
251
|
-
|
253
|
+
e.setMissingAttrs link,
|
252
254
|
'up-href': previousUrl,
|
253
255
|
'up-restore-scroll': ''
|
254
|
-
|
255
|
-
up.link.makeFollowable(
|
256
|
+
link.removeAttribute('up-back')
|
257
|
+
up.link.makeFollowable(link)
|
256
258
|
|
257
259
|
up.on 'up:framework:reset', reset
|
258
260
|
|
@@ -264,4 +266,3 @@ up.history = (($) ->
|
|
264
266
|
previousUrl: -> previousUrl
|
265
267
|
normalizeUrl: normalizeUrl
|
266
268
|
|
267
|
-
)(jQuery)
|
@@ -0,0 +1,60 @@
|
|
1
|
+
u = up.util
|
2
|
+
|
3
|
+
up.legacy = do ->
|
4
|
+
|
5
|
+
# renamedProperty = (object, oldKey, newKey) ->
|
6
|
+
# warning = -> warn('Property { %s } has been renamed to { %s } (found in %o)', oldKey, newKey, object)
|
7
|
+
# Object.defineProperty object, oldKey,
|
8
|
+
# get: ->
|
9
|
+
# warning()
|
10
|
+
# @[newKey]
|
11
|
+
# set: (newValue) ->
|
12
|
+
# warning()
|
13
|
+
# @[newKey] = newValue
|
14
|
+
|
15
|
+
# removedProperty = (object, key) ->
|
16
|
+
# failure = -> up.fail('Deprecated: Property { %s } is no longer supported (found in %o)', key, object)
|
17
|
+
# Object.defineProperty object, key,
|
18
|
+
# get: failure
|
19
|
+
# set: failure
|
20
|
+
|
21
|
+
fixKey = (object, oldKey, newKey) ->
|
22
|
+
if oldKey of object
|
23
|
+
warn('Property { %s } has been renamed to { %s } (found in %o)', oldKey, newKey, object)
|
24
|
+
u.renameKey(object, oldKey, newKey)
|
25
|
+
|
26
|
+
# # Maps old event name to new event name
|
27
|
+
# renamedEvents = {}
|
28
|
+
#
|
29
|
+
# renamedEvent = (oldName, newName) ->
|
30
|
+
# renamedEvents[oldName] = newName
|
31
|
+
#
|
32
|
+
# fixEventName = (eventName) ->
|
33
|
+
# if newEventName = renamedEvents[eventName]
|
34
|
+
# warn("Event #{eventName} has been renamed to #{newEventName}")
|
35
|
+
# newEventName
|
36
|
+
# else
|
37
|
+
# eventName
|
38
|
+
|
39
|
+
renamedModule = (oldName, newName) ->
|
40
|
+
Object.defineProperty up, oldName, get: ->
|
41
|
+
warn("up.#{oldName} has been renamed to up.#{newName}")
|
42
|
+
up[newName]
|
43
|
+
|
44
|
+
warnedMessages = {}
|
45
|
+
|
46
|
+
warn = (message, args...) ->
|
47
|
+
message = "[DEPRECATION] #{message}"
|
48
|
+
message = up.log.sprintf(message, args...)
|
49
|
+
unless warnedMessages[message]
|
50
|
+
warnedMessages[message] = true
|
51
|
+
up.warn(message)
|
52
|
+
|
53
|
+
renamedModule: renamedModule
|
54
|
+
# renamedProperty: renamedProperty
|
55
|
+
# removedProperty: removedProperty
|
56
|
+
# renamedEvent: renamedEvent
|
57
|
+
# fixEventName: fixEventName
|
58
|
+
fixKey: fixKey
|
59
|
+
warn: warn
|
60
|
+
|
@@ -2,6 +2,10 @@
|
|
2
2
|
Linking to fragments
|
3
3
|
====================
|
4
4
|
|
5
|
+
The `up.link` module lets you build links that update fragments instead of entire pages.
|
6
|
+
|
7
|
+
\#\#\# Motivation
|
8
|
+
|
5
9
|
In a traditional web application, the entire page is destroyed and re-created when the
|
6
10
|
user follows a link:
|
7
11
|
|
@@ -29,7 +33,7 @@ Pages also load much faster since the DOM, CSS and Javascript environments do no
|
|
29
33
|
destroyed and recreated for every request.
|
30
34
|
|
31
35
|
|
32
|
-
|
36
|
+
\#\#\# Example
|
33
37
|
|
34
38
|
Let's say we are rendering three pages with a tabbed navigation to switch between screens:
|
35
39
|
|
@@ -64,19 +68,21 @@ With these [`up-target`](/a-up-target) annotations Unpoly only updates the targe
|
|
64
68
|
The JavaScript environment will persist and the user will not see a white flash while the
|
65
69
|
new page is loading.
|
66
70
|
|
67
|
-
@
|
71
|
+
@module up.link
|
68
72
|
###
|
69
73
|
|
70
|
-
up.link =
|
74
|
+
up.link = do ->
|
71
75
|
|
72
76
|
u = up.util
|
77
|
+
e = up.element
|
73
78
|
|
74
79
|
###**
|
75
|
-
|
76
|
-
|
77
|
-
and [replacing](/up.replace) the current `<body>` element with the response's `<body>` element.
|
80
|
+
Fetches this given URL with JavaScript and [replaces](/up.replace) the
|
81
|
+
current `<body>` element with the response's `<body>` element.
|
78
82
|
|
79
|
-
|
83
|
+
\#\#\# Example
|
84
|
+
|
85
|
+
This would replace the current page with the response for `/users`:
|
80
86
|
|
81
87
|
up.visit('/users')
|
82
88
|
|
@@ -89,37 +95,34 @@ up.link = (($) ->
|
|
89
95
|
See options for [`up.replace()`](/up.replace)
|
90
96
|
@stable
|
91
97
|
###
|
92
|
-
visit = (url, options) ->
|
93
|
-
|
94
|
-
selector = u.option(options.target, 'body')
|
98
|
+
visit = (url, options = {}) ->
|
99
|
+
selector = options.target ? 'body'
|
95
100
|
up.replace(selector, url, options)
|
96
101
|
|
97
102
|
###**
|
98
|
-
|
99
|
-
with HTML from the response.
|
103
|
+
Fetches the given link's `[href]` with JavaScript and [replaces](/up.replace) the current page with HTML from the response.
|
100
104
|
|
101
105
|
By default the page's `<body>` element will be replaced.
|
102
|
-
If the link has an attribute like
|
103
|
-
or
|
104
|
-
just as if the user had clicked on the link.
|
106
|
+
If the link has an attribute like `a[up-target]`
|
107
|
+
or `a[up-modal]`, the respective Unpoly behavior will be used.
|
105
108
|
|
106
|
-
Emits the event
|
109
|
+
Emits the event `up:link:follow`.
|
107
110
|
|
108
111
|
\#\#\# Examples
|
109
112
|
|
110
|
-
|
113
|
+
Assume we have a link with an `a[up-target]` attribute:
|
111
114
|
|
112
115
|
<a href="/users" up-target=".main">Users</a>
|
113
116
|
|
114
117
|
Calling `up.follow()` with this link will replace the page's `.main` fragment
|
115
118
|
as if the user had clicked on the link:
|
116
119
|
|
117
|
-
var
|
118
|
-
up.follow(
|
120
|
+
var link = document.querSelector('a')
|
121
|
+
up.follow(link)
|
119
122
|
|
120
123
|
@function up.follow
|
121
124
|
@param {Element|jQuery|string} linkOrSelector
|
122
|
-
An element or selector which is either an `<a>` tag or any element with an `up-href` attribute.
|
125
|
+
An element or selector which is either an `<a>` tag or any element with an `[up-href]` attribute.
|
123
126
|
@param {string} [options.target]
|
124
127
|
The selector to replace.
|
125
128
|
|
@@ -143,9 +146,9 @@ up.link = (($) ->
|
|
143
146
|
@stable
|
144
147
|
###
|
145
148
|
follow = (linkOrSelector, options) ->
|
146
|
-
|
147
|
-
variant = followVariantForLink(
|
148
|
-
variant.followLink(
|
149
|
+
link = e.get(linkOrSelector)
|
150
|
+
variant = followVariantForLink(link)
|
151
|
+
variant.followLink(link, options)
|
149
152
|
|
150
153
|
###**
|
151
154
|
This event is [emitted](/up.emit) when a link is [followed](/up.follow) through Unpoly.
|
@@ -153,7 +156,7 @@ up.link = (($) ->
|
|
153
156
|
The event is emitted on the `<a>` element that is being followed.
|
154
157
|
|
155
158
|
@event up:link:follow
|
156
|
-
@param {
|
159
|
+
@param {Element} event.target
|
157
160
|
The link element that will be followed.
|
158
161
|
@param event.preventDefault()
|
159
162
|
Event listeners may call this method to prevent the link from being followed.
|
@@ -164,36 +167,33 @@ up.link = (($) ->
|
|
164
167
|
@function defaultFollow
|
165
168
|
@internal
|
166
169
|
###
|
167
|
-
defaultFollow = (
|
168
|
-
$link = $(linkOrSelector)
|
169
|
-
|
170
|
+
defaultFollow = (link, options) ->
|
170
171
|
options = u.options(options)
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
options.
|
175
|
-
options.
|
176
|
-
options.
|
177
|
-
options.
|
178
|
-
options.
|
179
|
-
options.
|
180
|
-
options.
|
181
|
-
options.
|
182
|
-
options.
|
183
|
-
options.
|
184
|
-
options.
|
185
|
-
options.
|
186
|
-
options.
|
187
|
-
options
|
188
|
-
options = u.merge(options, up.motion.animateOptions(options, $link))
|
172
|
+
url = options.url ? link.getAttribute('up-href') ? link.getAttribute('href')
|
173
|
+
target = options.target ? link.getAttribute('up-target')
|
174
|
+
options.failTarget ?= link.getAttribute('up-fail-target')
|
175
|
+
options.fallback ?= link.getAttribute('up-fallback')
|
176
|
+
options.transition ?= e.booleanOrStringAttr(link, 'up-transition')
|
177
|
+
options.failTransition ?= e.booleanOrStringAttr(link, 'up-fail-transition')
|
178
|
+
options.history ?= e.booleanOrStringAttr(link, 'up-history')
|
179
|
+
options.reveal ?= e.booleanOrStringAttr(link, 'up-reveal') ? true
|
180
|
+
options.failReveal ?= e.booleanOrStringAttr(link, 'up-fail-reveal') ? true
|
181
|
+
options.cache ?= e.booleanAttr(link, 'up-cache')
|
182
|
+
options.restoreScroll ?= e.booleanAttr(link, 'up-restore-scroll') # the option may contain an Object, but not the attr
|
183
|
+
options.method = followMethod(link, options)
|
184
|
+
options.origin ?= link
|
185
|
+
options.layer ?= link.getAttribute('up-layer')
|
186
|
+
options.failLayer ?= link.getAttribute('up-fail-layer')
|
187
|
+
options.confirm ?= link.getAttribute('up-confirm')
|
188
|
+
options = u.merge(options, up.motion.animateOptions(options, link))
|
189
189
|
|
190
190
|
up.browser.whenConfirmed(options).then ->
|
191
191
|
up.replace(target, url, options)
|
192
192
|
|
193
|
-
defaultPreload = (
|
193
|
+
defaultPreload = (link, options) ->
|
194
194
|
options = u.options(options)
|
195
195
|
options.preload = true
|
196
|
-
defaultFollow(
|
196
|
+
defaultFollow(link, options)
|
197
197
|
|
198
198
|
###**
|
199
199
|
Returns the HTTP method that should be used when following the given link.
|
@@ -202,14 +202,13 @@ up.link = (($) ->
|
|
202
202
|
Defaults to `"get"`.
|
203
203
|
|
204
204
|
@function up.link.followMethod
|
205
|
-
@param
|
205
|
+
@param link
|
206
206
|
@param options.method {string}
|
207
207
|
@internal
|
208
208
|
###
|
209
|
-
followMethod = (
|
210
|
-
|
211
|
-
|
212
|
-
u.option(options.method, $link.attr('up-method'), $link.attr('data-method'), 'get').toUpperCase()
|
209
|
+
followMethod = (link, options = {}) ->
|
210
|
+
rawMethod = options.method ? link.getAttribute('up-method') ? link.getAttribute('data-method') ? 'GET'
|
211
|
+
rawMethod.toUpperCase()
|
213
212
|
|
214
213
|
###**
|
215
214
|
No-op that is called when we allow a browser's default action to go through,
|
@@ -233,8 +232,8 @@ up.link = (($) ->
|
|
233
232
|
@function up.link.addFollowVariant
|
234
233
|
@param {string} simplifiedSelector
|
235
234
|
A selector without `a` or `[up-href]`, e.g. `[up-target]`
|
236
|
-
@param {Function(
|
237
|
-
@param {Function(
|
235
|
+
@param {Function(element, options)} options.follow
|
236
|
+
@param {Function(element, options)} options.preload
|
238
237
|
@internal
|
239
238
|
###
|
240
239
|
addFollowVariant = (simplifiedSelector, options) ->
|
@@ -244,40 +243,41 @@ up.link = (($) ->
|
|
244
243
|
variant
|
245
244
|
|
246
245
|
###**
|
247
|
-
Returns whether the given link will be
|
246
|
+
Returns whether the given link will be [followed](/up.follow) by Unpoly
|
247
|
+
instead of making a full page load.
|
248
248
|
|
249
|
-
A link will be
|
250
|
-
like `up-target` or `up-modal`.
|
249
|
+
A link will be followed by Unpoly if it has an attribute
|
250
|
+
like `a[up-target]` or `a[up-modal]`.
|
251
251
|
|
252
252
|
@function up.link.isFollowable
|
253
253
|
@param {Element|jQuery|string} linkOrSelector
|
254
254
|
The link to check.
|
255
255
|
@experimental
|
256
256
|
###
|
257
|
-
isFollowable = (
|
258
|
-
|
257
|
+
isFollowable = (linkOrSelector) ->
|
258
|
+
linkOrSelector = e.get(linkOrSelector)
|
259
|
+
!!followVariantForLink(linkOrSelector, default: false)
|
259
260
|
|
260
261
|
###**
|
261
262
|
Returns the handler function that can be used to follow the given link.
|
262
263
|
E.g. it wil return a handler calling `up.modal.follow` if the link is a `[up-modal]`,
|
263
264
|
but a handler calling `up.link.follow` if the links is `[up-target]`.
|
264
265
|
|
265
|
-
@param {Element
|
266
|
-
@return {
|
266
|
+
@param {Element} link
|
267
|
+
@return {Object}
|
267
268
|
@internal
|
268
269
|
###
|
269
|
-
followVariantForLink = (
|
270
|
-
|
271
|
-
$link = $(linkOrSelector)
|
272
|
-
variant = u.detect followVariants, (variant) -> variant.matchesLink($link)
|
270
|
+
followVariantForLink = (link, options = {}) ->
|
271
|
+
variant = u.find followVariants, (variant) -> variant.matchesLink(link)
|
273
272
|
variant ||= DEFAULT_FOLLOW_VARIANT unless options.default is false
|
274
273
|
variant
|
275
274
|
|
276
275
|
###**
|
277
|
-
Makes sure that the given link will be
|
276
|
+
Makes sure that the given link will be [followed](/up.follow)
|
277
|
+
by Unpoly instead of making a full page load.
|
278
278
|
|
279
|
-
This is done by giving the link an `up-follow` attribute
|
280
|
-
unless it already have it an attribute like `up-target` or `up-modal`.
|
279
|
+
This is done by giving the link an `a[up-follow]` attribute
|
280
|
+
unless it already have it an attribute like `a[up-target]` or `a[up-modal]`.
|
281
281
|
|
282
282
|
@function up.link.makeFollowable
|
283
283
|
@param {Element|jQuery|string} linkOrSelector
|
@@ -285,21 +285,20 @@ up.link = (($) ->
|
|
285
285
|
@experimental
|
286
286
|
###
|
287
287
|
makeFollowable = (link) ->
|
288
|
-
|
289
|
-
|
290
|
-
$link.attr('up-follow', '')
|
288
|
+
unless isFollowable(link)
|
289
|
+
link.setAttribute('up-follow', '')
|
291
290
|
|
292
|
-
shouldProcessEvent = (event,
|
291
|
+
shouldProcessEvent = (event, link) ->
|
293
292
|
target = event.target
|
294
293
|
# We never handle events for the right mouse button, or when Shift/CTRL/Meta is pressed
|
295
294
|
return false unless u.isUnmodifiedMouseEvent(event)
|
296
|
-
# If we actually targeted
|
297
|
-
return true if target ==
|
295
|
+
# If we actually targeted `link`, save ourselves the expensive DOM traversal below
|
296
|
+
return true if target == link
|
298
297
|
# If user clicked on a child link of $link, or in an <input> within an [up-expand][up-href]
|
299
298
|
# we want those other elements handle the click.
|
300
|
-
|
301
|
-
|
302
|
-
return
|
299
|
+
betterTargetSelector = "a, [up-href], #{up.form.fieldSelector()}"
|
300
|
+
betterTarget = e.closest(target, betterTargetSelector)
|
301
|
+
return !betterTarget || betterTarget == link
|
303
302
|
|
304
303
|
###**
|
305
304
|
Returns whether the given link has a [safe](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1)
|
@@ -309,20 +308,26 @@ up.link = (($) ->
|
|
309
308
|
@experimental
|
310
309
|
###
|
311
310
|
isSafe = (selectorOrLink, options) ->
|
312
|
-
|
313
|
-
method = followMethod($link, options)
|
311
|
+
method = followMethod(selectorOrLink, options)
|
314
312
|
up.proxy.isSafeMethod(method)
|
315
313
|
|
316
314
|
###**
|
317
|
-
Follows this link
|
318
|
-
|
315
|
+
[Follows](/up.follow) this link with JavaScript and replaces a CSS selector
|
316
|
+
on the current page with a corresponding element from the response.
|
317
|
+
|
318
|
+
\#\#\# Example
|
319
|
+
|
320
|
+
This will update the fragment `<div class="main">` with the same element
|
321
|
+
fetched from `/posts/5`:
|
319
322
|
|
320
323
|
<a href="/posts/5" up-target=".main">Read post</a>
|
321
324
|
|
322
325
|
\#\#\# Updating multiple fragments
|
323
326
|
|
324
327
|
You can update multiple fragments from a single request by separating
|
325
|
-
separators with a comma (like in CSS).
|
328
|
+
separators with a comma (like in CSS).
|
329
|
+
|
330
|
+
For instance, if opening a post should
|
326
331
|
also update a bubble showing the number of unread posts, you might
|
327
332
|
do this:
|
328
333
|
|
@@ -331,7 +336,7 @@ up.link = (($) ->
|
|
331
336
|
\#\#\# Appending or prepending content
|
332
337
|
|
333
338
|
By default Unpoly will replace the given selector with the same
|
334
|
-
selector from
|
339
|
+
selector from the server response. Instead of replacing you
|
335
340
|
can *append* the loaded content to the existing content by using the
|
336
341
|
`:after` pseudo selector. In the same fashion, you can use `:before`
|
337
342
|
to indicate that you would like the *prepend* the loaded content.
|
@@ -353,7 +358,7 @@ up.link = (($) ->
|
|
353
358
|
\#\#\# Following elements that are no links
|
354
359
|
|
355
360
|
You can also use `[up-target]` to turn an arbitrary element into a link.
|
356
|
-
In this case, put the link's destination into the `up-href` attribute:
|
361
|
+
In this case, put the link's destination into the `[up-href]` attribute:
|
357
362
|
|
358
363
|
<button up-target=".main" up-href="/foo/bar">Go</button>
|
359
364
|
|
@@ -420,15 +425,14 @@ up.link = (($) ->
|
|
420
425
|
###
|
421
426
|
DEFAULT_FOLLOW_VARIANT = addFollowVariant '[up-target], [up-follow]',
|
422
427
|
# Don't just pass the `defaultFollow` function reference so we can stub it in tests
|
423
|
-
follow: (
|
424
|
-
preload: (
|
428
|
+
follow: (link, options) -> defaultFollow(link, options)
|
429
|
+
preload: (link, options) -> defaultPreload(link, options)
|
425
430
|
|
426
431
|
###**
|
427
|
-
|
432
|
+
Fetches this link's `[href]` with JavaScript and [replaces](/up.replace) the
|
428
433
|
current `<body>` element with the response's `<body>` element.
|
429
434
|
|
430
|
-
To only update a fragment instead of the entire
|
431
|
-
[`a[up-target]`](/a-up-target).
|
435
|
+
To only update a fragment instead of the entire `<body>`, see `a[up-target]`.
|
432
436
|
|
433
437
|
\#\#\# Example
|
434
438
|
|
@@ -485,19 +489,19 @@ up.link = (($) ->
|
|
485
489
|
AJAX request will be triggered right way, the interaction will
|
486
490
|
appear faster.
|
487
491
|
|
488
|
-
Note that using `[up-instant]` will prevent a user from canceling a
|
489
|
-
click by moving the mouse away from the
|
492
|
+
Note that using `[up-instant]` will prevent a user from canceling a
|
493
|
+
click by moving the mouse away from the link. However, for
|
490
494
|
navigation actions this isn't needed. E.g. popular operation
|
491
495
|
systems switch tabs on `mousedown` instead of `click`.
|
492
496
|
|
493
|
-
`up-instant` will also work for links that open [modals](/up.modal) or [popups](/up.popup).
|
497
|
+
`[up-instant]` will also work for links that open [modals](/up.modal) or [popups](/up.popup).
|
494
498
|
|
495
499
|
@selector a[up-instant]
|
496
500
|
@stable
|
497
501
|
###
|
498
502
|
|
499
503
|
###**
|
500
|
-
|
504
|
+
[Follows](/up.follow) this link *as fast as possible*.
|
501
505
|
|
502
506
|
This is done by:
|
503
507
|
|
@@ -505,20 +509,26 @@ up.link = (($) ->
|
|
505
509
|
- [Preloading the link's destination URL](/a-up-preload)
|
506
510
|
- [Triggering the link on `mousedown`](/a-up-instant) instead of on `click`
|
507
511
|
|
512
|
+
\#\#\# Example
|
513
|
+
|
508
514
|
Use `up-dash` like this:
|
509
515
|
|
510
516
|
<a href="/users" up-dash=".main">User list</a>
|
511
517
|
|
512
|
-
|
518
|
+
This is shorthand for:
|
513
519
|
|
514
520
|
<a href="/users" up-target=".main" up-instant up-preload>User list</a>
|
515
521
|
|
516
522
|
@selector a[up-dash]
|
523
|
+
@param {string} [up-dash='body']
|
524
|
+
The CSS selector to replace
|
525
|
+
|
526
|
+
Inside the CSS selector you may refer to this link as `&` ([like in Sass](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector)).
|
517
527
|
@stable
|
518
528
|
###
|
519
|
-
up.macro '[up-dash]', (
|
520
|
-
target =
|
521
|
-
|
529
|
+
up.macro '[up-dash]', (element) ->
|
530
|
+
target = e.booleanOrStringAttr(element, 'up-dash')
|
531
|
+
element.removeAttribute('up-dash')
|
522
532
|
newAttrs = {
|
523
533
|
'up-preload': '',
|
524
534
|
'up-instant': ''
|
@@ -526,17 +536,19 @@ up.link = (($) ->
|
|
526
536
|
if target is true
|
527
537
|
# If it's literally `true` then we don't have a target selector.
|
528
538
|
# Just follow the link by replacing `<body>`.
|
529
|
-
makeFollowable(
|
539
|
+
makeFollowable(element)
|
530
540
|
else
|
531
541
|
newAttrs['up-target'] = target
|
532
|
-
|
542
|
+
e.setMissingAttrs(element, newAttrs)
|
533
543
|
|
534
544
|
###**
|
535
|
-
Add an `[up-expand]` attribute to any element
|
536
|
-
|
545
|
+
Add an `[up-expand]` attribute to any element to enlarge the click area of an
|
546
|
+
descendant link.
|
547
|
+
|
548
|
+
`[up-expand]` honors all the Unppoly attributes in expanded links, like
|
549
|
+
`a[up-target]`, `a[up-instant]` or `a[up-preload]`.
|
550
|
+
It also expands links that open [modals](/up.modal) or [popups](/up.popup).
|
537
551
|
|
538
|
-
`[up-expand]` honors all the UJS behavior in expanded links
|
539
|
-
([`a[up-target]`](/a-up-target), [`a[up-instant]`](/a-up-instant), [`a[up-preload]`](/a-up-preload), etc.).
|
540
552
|
|
541
553
|
\#\#\# Example
|
542
554
|
|
@@ -548,8 +560,6 @@ up.link = (($) ->
|
|
548
560
|
In the example above, clicking anywhere within `.notification` element
|
549
561
|
would [follow](/up.follow) the *Close* link.
|
550
562
|
|
551
|
-
`up-expand` also expands links that open [modals](/up.modal) or [popups](/up.popup).
|
552
|
-
|
553
563
|
\#\#\# Elements with multiple contained links
|
554
564
|
|
555
565
|
If a container contains more than one link, you can set the value of the
|
@@ -566,7 +576,7 @@ up.link = (($) ->
|
|
566
576
|
`[up-expand]` has some limitations for advanced browser users:
|
567
577
|
|
568
578
|
- Users won't be able to right-click the expanded area to open a context menu
|
569
|
-
- Users won't be able to CTRL
|
579
|
+
- Users won't be able to `CTRL`+click the expanded area to open a new tab
|
570
580
|
|
571
581
|
To overcome these limitations, consider nesting the entire clickable area in an actual `<a>` tag.
|
572
582
|
[It's OK to put block elements inside an anchor tag](https://makandracards.com/makandra/43549-it-s-ok-to-put-block-elements-inside-an-a-tag).
|
@@ -575,24 +585,24 @@ up.link = (($) ->
|
|
575
585
|
@param {string} [up-expand]
|
576
586
|
A CSS selector that defines which containing link should be expanded.
|
577
587
|
|
578
|
-
If omitted, the first
|
588
|
+
If omitted, the first link in this element will be expanded.
|
579
589
|
@stable
|
580
590
|
###
|
581
|
-
up.macro '[up-expand]', (
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
if
|
591
|
+
up.macro '[up-expand]', (area) ->
|
592
|
+
selector = area.getAttribute('up-expand') || 'a, [up-href]'
|
593
|
+
childLinks = e.all(area, selector)
|
594
|
+
|
595
|
+
if childLink = childLinks[0]
|
586
596
|
upAttributePattern = /^up-/
|
587
597
|
newAttrs = {}
|
588
|
-
newAttrs['up-href'] =
|
589
|
-
for attribute in
|
598
|
+
newAttrs['up-href'] = childLink.getAttribute('href')
|
599
|
+
for attribute in childLink.attributes
|
590
600
|
name = attribute.name
|
591
601
|
if name.match(upAttributePattern)
|
592
602
|
newAttrs[name] = attribute.value
|
593
|
-
|
594
|
-
|
595
|
-
makeFollowable(
|
603
|
+
e.setMissingAttrs(area, newAttrs)
|
604
|
+
area.removeAttribute('up-expand')
|
605
|
+
makeFollowable(area)
|
596
606
|
|
597
607
|
<% if ENV['JS_KNIFE'] %>knife: eval(Knife.point)<% end %>
|
598
608
|
visit: visit
|
@@ -606,7 +616,5 @@ up.link = (($) ->
|
|
606
616
|
followVariantForLink: followVariantForLink
|
607
617
|
allowDefault: allowDefault
|
608
618
|
|
609
|
-
)(jQuery)
|
610
|
-
|
611
619
|
up.visit = up.link.visit
|
612
620
|
up.follow = up.link.follow
|