unpoly-rails 0.37.0 → 0.50.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 (88) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +127 -25
  3. data/LICENSE +1 -1
  4. data/README_RAILS.md +4 -2
  5. data/Rakefile +6 -1
  6. data/dist/unpoly.js +3192 -2198
  7. data/dist/unpoly.min.js +4 -3
  8. data/lib/assets/javascripts/unpoly/browser.coffee +51 -63
  9. data/lib/assets/javascripts/unpoly/bus.coffee +58 -33
  10. data/lib/assets/javascripts/unpoly/classes/cache.coffee +117 -0
  11. data/lib/assets/javascripts/unpoly/{dom → classes}/extract_cascade.coffee +3 -3
  12. data/lib/assets/javascripts/unpoly/{dom → classes}/extract_plan.coffee +1 -1
  13. data/lib/assets/javascripts/unpoly/classes/field_observer.coffee +57 -0
  14. data/lib/assets/javascripts/unpoly/classes/follow_variant.coffee +52 -0
  15. data/lib/assets/javascripts/unpoly/classes/motion_tracker.coffee +95 -0
  16. data/lib/assets/javascripts/unpoly/classes/record.coffee +16 -0
  17. data/lib/assets/javascripts/unpoly/classes/request.coffee +228 -0
  18. data/lib/assets/javascripts/unpoly/classes/response.coffee +138 -0
  19. data/lib/assets/javascripts/unpoly/dom.coffee +151 -142
  20. data/lib/assets/javascripts/unpoly/feedback.coffee +67 -38
  21. data/lib/assets/javascripts/unpoly/form.coffee +156 -139
  22. data/lib/assets/javascripts/unpoly/history.coffee +22 -19
  23. data/lib/assets/javascripts/unpoly/layout.coffee +108 -90
  24. data/lib/assets/javascripts/unpoly/link.coffee +159 -158
  25. data/lib/assets/javascripts/unpoly/log.coffee +5 -5
  26. data/lib/assets/javascripts/unpoly/modal.coffee +93 -81
  27. data/lib/assets/javascripts/unpoly/motion.coffee +291 -250
  28. data/lib/assets/javascripts/unpoly/popup.coffee +67 -53
  29. data/lib/assets/javascripts/unpoly/protocol.coffee +67 -16
  30. data/lib/assets/javascripts/unpoly/proxy.coffee +282 -211
  31. data/lib/assets/javascripts/unpoly/rails.coffee +3 -14
  32. data/lib/assets/javascripts/unpoly/syntax.coffee +54 -49
  33. data/lib/assets/javascripts/unpoly/tooltip.coffee +18 -25
  34. data/lib/assets/javascripts/unpoly/util.coffee +236 -477
  35. data/lib/assets/javascripts/unpoly.coffee +1 -1
  36. data/lib/unpoly/rails/inspector.rb +67 -22
  37. data/lib/unpoly/rails/version.rb +1 -1
  38. data/package.json +1 -1
  39. data/spec_app/Gemfile.lock +13 -13
  40. data/spec_app/app/assets/javascripts/integration_test.coffee +1 -0
  41. data/spec_app/app/assets/javascripts/jasmine_specs.coffee +1 -1
  42. data/spec_app/app/assets/stylesheets/jasmine_specs.sass +10 -0
  43. data/spec_app/app/controllers/binding_test_controller.rb +19 -2
  44. data/spec_app/app/controllers/method_test_controller.rb +16 -0
  45. data/spec_app/app/views/layouts/jasmine_rails/spec_runner.html.erb +20 -0
  46. data/spec_app/app/views/method_test/form_target.erb +17 -0
  47. data/spec_app/app/views/method_test/page1.erb +11 -0
  48. data/spec_app/app/views/method_test/page2.erb +6 -0
  49. data/spec_app/app/views/pages/start.erb +33 -19
  50. data/spec_app/config/initializers/assets.rb +5 -0
  51. data/spec_app/config/routes.rb +3 -0
  52. data/spec_app/spec/controllers/binding_test_controller_spec.rb +82 -27
  53. data/spec_app/spec/javascripts/helpers/agent_detector.coffee +17 -0
  54. data/spec_app/spec/javascripts/helpers/async_sequence.js.coffee +102 -0
  55. data/spec_app/spec/javascripts/helpers/last_request.js.coffee +1 -1
  56. data/spec_app/spec/javascripts/helpers/mock_ajax.js.coffee +5 -2
  57. data/spec_app/spec/javascripts/helpers/promise_state.js +18 -0
  58. data/spec_app/spec/javascripts/helpers/protect_jasmine_runner.coffee +9 -0
  59. data/spec_app/spec/javascripts/helpers/reset_history.js.coffee +22 -0
  60. data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +11 -3
  61. data/spec_app/spec/javascripts/helpers/show_lib_versions.coffee +10 -0
  62. data/spec_app/spec/javascripts/helpers/to_be_error.coffee +5 -0
  63. data/spec_app/spec/javascripts/helpers/to_match_url.coffee +13 -0
  64. data/spec_app/spec/javascripts/helpers/trigger.js.coffee +13 -6
  65. data/spec_app/spec/javascripts/up/browser_spec.js.coffee +92 -33
  66. data/spec_app/spec/javascripts/up/bus_spec.js.coffee +64 -15
  67. data/spec_app/spec/javascripts/up/classes/.keep +0 -0
  68. data/spec_app/spec/javascripts/up/classes/cache_spec.js.coffee +1 -0
  69. data/spec_app/spec/javascripts/up/dom_spec.js.coffee +759 -551
  70. data/spec_app/spec/javascripts/up/feedback_spec.js.coffee +155 -82
  71. data/spec_app/spec/javascripts/up/form_spec.js.coffee +490 -349
  72. data/spec_app/spec/javascripts/up/history_spec.js.coffee +226 -179
  73. data/spec_app/spec/javascripts/up/layout_spec.js.coffee +253 -185
  74. data/spec_app/spec/javascripts/up/link_spec.js.coffee +416 -270
  75. data/spec_app/spec/javascripts/up/modal_spec.js.coffee +459 -330
  76. data/spec_app/spec/javascripts/up/motion_spec.js.coffee +198 -153
  77. data/spec_app/spec/javascripts/up/namespace_spec.js.coffee +9 -0
  78. data/spec_app/spec/javascripts/up/popup_spec.js.coffee +240 -175
  79. data/spec_app/spec/javascripts/up/protocol_spec.js.coffee +38 -0
  80. data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +777 -303
  81. data/spec_app/spec/javascripts/up/rails_spec.js.coffee +24 -8
  82. data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +40 -23
  83. data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +80 -66
  84. data/spec_app/spec/javascripts/up/util_spec.js.coffee +227 -201
  85. data/spec_app/vendor/asset-libs/es6-promise-4.1.6/es6-promise.auto.js +1159 -0
  86. metadata +30 -7
  87. data/spec_app/spec/javascripts/helpers/reset_path.js.coffee +0 -7
  88. data/spec_app/spec/javascripts/helpers/to_equal_url.coffee +0 -11
@@ -74,16 +74,16 @@ up.link = (($) ->
74
74
  ###*
75
75
  Visits the given URL without a full page load.
76
76
  This is done by fetching `url` through an AJAX request
77
- and replacing the current `<body>` element with the response's `<body>` element.
77
+ and [replacing](/up.replace) the current `<body>` element with the response's `<body>` element.
78
78
 
79
79
  For example, this would fetch the `/users` URL:
80
80
 
81
81
  up.visit('/users')
82
82
 
83
83
  @function up.visit
84
- @param {String} url
84
+ @param {string} url
85
85
  The URL to visit.
86
- @param {String} [options.target='body']
86
+ @param {string} [options.target='body']
87
87
  The selector to replace.
88
88
  @param {Object} [options]
89
89
  See options for [`up.replace()`](/up.replace)
@@ -95,78 +95,50 @@ up.link = (($) ->
95
95
  up.replace(selector, url, options)
96
96
 
97
97
  ###*
98
- Follows the given link via AJAX and [replaces](/up.replace) a CSS selector in the current page
99
- with corresponding elements from a new page fetched from the server.
98
+ Follows the given link via AJAX and [replaces](/up.replace) the current page
99
+ with HTML from the response.
100
100
 
101
- Any Unpoly UJS attributes on the given link will be honored. E. g. you have this link:
101
+ By default the page's `<body>` element will be replaced.
102
+ If the link has an attribute like [`[up-target]`](/up-target)
103
+ or [`[up-modal]`](/a-up-modal), the corresponding UJS behavior will be activated
104
+ just as if the user had clicked on the link.
105
+
106
+ \#\#\# Examples
107
+
108
+ Let's say you have a link with an [`a[up-target]`](/a-up-target) attribute:
102
109
 
103
110
  <a href="/users" up-target=".main">Users</a>
104
111
 
105
- You can update the page's `.main` selector with the `.main` from `/users` like this:
112
+ Calling `up.follow()` with this link will replace the page's `.main` fragment
113
+ as if the user had clicked on the link:
106
114
 
107
- var $link = $('a:first'); // select link with jQuery
115
+ var $link = $('a:first');
108
116
  up.follow($link);
109
117
 
110
- The unobtrusive variant of this are the [`a[up-target]`](/a-up-target) and [`a[up-follow]`](/a-up-follow) selectors.
111
-
112
118
  @function up.follow
113
- @param {Element|jQuery|String} linkOrSelector
114
- An element or selector which resolves to an `<a>` tag
115
- or any element that is marked up with an `up-href` attribute.
116
- @param {String} [options.target]
119
+ @param {Element|jQuery|string} linkOrSelector
120
+ An element or selector which is either an `<a>` tag or any element with an `up-href` attribute.
121
+ @param {string} [options.target]
117
122
  The selector to replace.
118
- Defaults to the `up-target` attribute on `link`, or to `body` if such an attribute does not exist.
119
- @param {String} [options.failTarget]
120
- The selector to replace if the server responds with a non-200 status code.
121
- Defaults to the `up-fail-target` attribute on `link`, or to `body` if such an attribute does not exist.
122
- @param {String} [options.fallback]
123
- The selector to update when the original target was not found in the page.
124
- @param {String} [options.method='get']
125
- The HTTP method to use for the request.
126
- @param {String} [options.confirm]
127
- A message that will be displayed in a cancelable confirmation dialog
128
- before the link is followed.
129
- @param {Function|String} [options.transition]
130
- A transition function or name.
131
- @param {Function|String} [options.failTransition]
132
- The transition to use if the server responds with a non-200 status code.
133
- @param {Number} [options.duration]
134
- The duration of the transition. See [`up.morph()`](/up.morph).
135
- @param {Number} [options.delay]
136
- The delay before the transition starts. See [`up.morph()`](/up.morph).
137
- @param {String} [options.easing]
138
- The timing function that controls the transition's acceleration. [`up.morph()`](/up.morph).
139
- @param {Element|jQuery|String} [options.reveal]
140
- Whether to reveal the target element within its viewport before updating.
141
- @param {Boolean} [options.restoreScroll]
142
- If set to `true`, this will attempt to [restore scroll positions](/up.restoreScroll)
143
- previously seen on the destination URL.
144
- @param {Boolean} [options.cache]
145
- Whether to force the use of a cached response (`true`)
146
- or never use the cache (`false`)
147
- or make an educated guess (`undefined`).
148
- @param {Object} [options.headers={}]
149
- An object of additional header key/value pairs to send along
150
- with the request.
151
- @param {Object} [options.timeout={}]
152
- A timeout in milliseconds for the request.
153
- @param {String} [options.layer='auto']
154
- The name of the layer that ought to be updated. Valid values are
155
- `auto`, `page`, `modal` and `popup`.
156
-
157
- If set to `auto` (default), Unpoly will try to find a match in the
158
- same layer as the given link. If no match was found in that layer,
159
- Unpoly will search in other layers, starting from the topmost layer.
160
- @param {String} [options.failLayer='auto']
161
- The name of the layer that ought to be updated if the server sends a non-200 status code.
123
+ Defaults to the `[up-target]`, `[up-modal]` or `[up-popup]` attribute on `link`.
124
+ If no target is given, the `<body>` element will be replaced.
162
125
 
163
126
  @return {Promise}
164
- A promise that will be resolved when the link destination
127
+ A promise that will be fulfilled when the link destination
165
128
  has been loaded and rendered.
166
129
  @stable
167
130
  ###
168
131
  follow = (linkOrSelector, options) ->
169
132
  $link = $(linkOrSelector)
133
+ variant = followVariantForLink($link)
134
+ variant.followLink($link, options)
135
+
136
+ ###*
137
+ @function defaultFollow
138
+ @internal
139
+ ###
140
+ defaultFollow = (linkOrSelector, options) ->
141
+ $link = $(linkOrSelector)
170
142
 
171
143
  options = u.options(options)
172
144
 
@@ -190,6 +162,11 @@ up.link = (($) ->
190
162
  up.browser.whenConfirmed(options).then ->
191
163
  up.replace(target, url, options)
192
164
 
165
+ defaultPreload = ($link, options) ->
166
+ options = u.options(options)
167
+ options.preload = true
168
+ defaultFollow($link, options)
169
+
193
170
  ###*
194
171
  Returns the HTTP method that should be used when following the given link.
195
172
 
@@ -198,7 +175,7 @@ up.link = (($) ->
198
175
 
199
176
  @function up.link.followMethod
200
177
  @param linkOrSelector
201
- @param options.method {String}
178
+ @param options.method {string}
202
179
  @internal
203
180
  ###
204
181
  followMethod = (linkOrSelector, options) ->
@@ -206,20 +183,6 @@ up.link = (($) ->
206
183
  options = u.options(options)
207
184
  u.option(options.method, $link.attr('up-method'), $link.attr('data-method'), 'get').toUpperCase()
208
185
 
209
- ###*
210
- @function up.link.childClicked
211
- @internal
212
- ###
213
- childClicked = (event, $link) ->
214
- $target = $(event.target)
215
- $targetLink = $target.closest('a, [up-href]')
216
- $targetLink.length && $link.find($targetLink).length
217
-
218
- shouldProcessLinkEvent = (event, $link) ->
219
- u.isUnmodifiedMouseEvent(event) && !childClicked(event, $link)
220
-
221
- followVariantSelectors = []
222
-
223
186
  ###*
224
187
  No-op that is called when we allow a browser's default action to go through,
225
188
  so we can spy on it in unit tests. See `link_spec.js`.
@@ -229,26 +192,28 @@ up.link = (($) ->
229
192
  ###
230
193
  allowDefault = (event) ->
231
194
 
232
- onAction = (selector, handler) ->
233
- followVariantSelectors.push(selector)
234
- handlerWithActiveMark = ($link) ->
235
- up.feedback.start $link, -> handler($link)
236
- up.on 'click', "a#{selector}, [up-href]#{selector}", (event, $link) ->
237
- if shouldProcessLinkEvent(event, $link)
238
- if $link.is('[up-instant]')
239
- # If the link was already processed on mousedown, we still need
240
- # to prevent this later click event's chain.
241
- up.bus.haltEvent(event)
242
- else
243
- up.bus.consumeAction(event)
244
- handlerWithActiveMark($link)
245
- else
246
- allowDefault(event)
247
-
248
- up.on 'mousedown', "a#{selector}[up-instant], [up-href]#{selector}[up-instant]", (event, $link) ->
249
- if shouldProcessLinkEvent(event, $link)
250
- up.bus.consumeAction(event)
251
- handlerWithActiveMark($link)
195
+ followVariants = []
196
+
197
+ ###*
198
+ Registers the given handler for links with the given selector.
199
+
200
+ This does more than a simple `click` handler:
201
+
202
+ - It also handles `[up-instant]`
203
+ - It also handles `[up-href]`
204
+
205
+ @function up.link.addFollowVariant
206
+ @param {string} simplifiedSelector
207
+ A selector without `a` or `[up-href]`, e.g. `[up-target]`
208
+ @param {Function<jQuery, Object>} options.follow
209
+ @param {Function<jQuery, Object>} options.preload
210
+ @internal
211
+ ###
212
+ addFollowVariant = (simplifiedSelector, options) ->
213
+ variant = new up.FollowVariant(simplifiedSelector, options)
214
+ followVariants.push(variant)
215
+ variant.registerEvents()
216
+ variant
252
217
 
253
218
  ###*
254
219
  Returns whether the given link will be handled by Unpoly instead of making a full page load.
@@ -257,13 +222,28 @@ up.link = (($) ->
257
222
  like `up-target` or `up-modal`.
258
223
 
259
224
  @function up.link.isFollowable
260
- @param {Element|jQuery|String} linkOrSelector
225
+ @param {Element|jQuery|string} linkOrSelector
261
226
  The link to check.
262
227
  @experimental
263
228
  ###
264
229
  isFollowable = (link) ->
265
- $link = $(link)
266
- u.any followVariantSelectors, (selector) -> $link.is(selector)
230
+ !!followVariantForLink(link, default: false)
231
+
232
+ ###*
233
+ Returns the handler function that can be used to follow the given link.
234
+ E.g. it wil return a handler calling `up.modal.follow` if the link is a `[up-modal]`,
235
+ but a handler calling `up.link.follow` if the links is `[up-target]`.
236
+
237
+ @param {Element|jQuery|string}
238
+ @return {Function(jQuery)}
239
+ @internal
240
+ ###
241
+ followVariantForLink = (linkOrSelector, options) ->
242
+ options = u.options(options)
243
+ $link = $(linkOrSelector)
244
+ variant = u.detect followVariants, (variant) -> variant.matchesLink($link)
245
+ variant ||= DEFAULT_FOLLOW_VARIANT unless options.default is false
246
+ variant
267
247
 
268
248
  ###*
269
249
  Makes sure that the given link will be handled by Unpoly instead of making a full page load.
@@ -272,7 +252,7 @@ up.link = (($) ->
272
252
  unless it already have it an attribute like `up-target` or `up-modal`.
273
253
 
274
254
  @function up.link.makeFollowable
275
- @param {Element|jQuery|String} linkOrSelector
255
+ @param {Element|jQuery|string} linkOrSelector
276
256
  The link to process.
277
257
  @experimental
278
258
  ###
@@ -281,6 +261,23 @@ up.link = (($) ->
281
261
  unless isFollowable($link)
282
262
  $link.attr('up-follow', '')
283
263
 
264
+ childClicked = (event, $link) ->
265
+ $target = $(event.target)
266
+ $targetLink = $target.closest('a, [up-href]')
267
+ $targetLink.length && $link.find($targetLink).length
268
+
269
+ ###*
270
+ Returns whether the given link has a [safe](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1)
271
+ HTTP method like `GET`.
272
+
273
+ @function up.link.isSafe
274
+ @experimental
275
+ ###
276
+ isSafe = (selectorOrLink, options) ->
277
+ $link = $(selectorOrLink)
278
+ method = followMethod($link, options)
279
+ up.proxy.isSafeMethod(method)
280
+
284
281
  ###*
285
282
  Follows this link via AJAX and replaces a CSS selector in the current page
286
283
  with corresponding elements from a new page fetched from the server:
@@ -329,42 +326,42 @@ up.link = (($) ->
329
326
  opening the destination in a new tab.
330
327
 
331
328
  @selector a[up-target]
332
- @param {String} up-target
329
+ @param {string} up-target
333
330
  The CSS selector to replace
334
- @param {String} [up-method='get']
331
+ @param {string} [up-method='get']
335
332
  The HTTP method to use for the request.
336
- @param {String} [up-transition='none']
333
+ @param {string} [up-transition='none']
337
334
  The [transition](/up.motion) to use for morphing between the old and new elements.
338
335
  @param [up-fail-target='body']
339
336
  The selector to replace if the server responds with a non-200 status code.
340
- @param {String} [up-fail-transition='none']
337
+ @param {string} [up-fail-transition='none']
341
338
  The [transition](/up.motion) to use for morphing between the old and new elements
342
339
  when the server responds with a non-200 status code.
343
- @param {String} [up-fallback]
340
+ @param {string} [up-fallback]
344
341
  The selector to update when the original target was not found in the page.
345
- @param {String} [up-href]
342
+ @param {string} [up-href]
346
343
  The destination URL to follow.
347
344
  If omitted, the the link's `href` attribute will be used.
348
- @param {String} [up-confirm]
345
+ @param {string} [up-confirm]
349
346
  A message that will be displayed in a cancelable confirmation dialog
350
347
  before the link is followed.
351
- @param {String} [up-reveal='true']
348
+ @param {string} [up-reveal='true']
352
349
  Whether to reveal the target element within its viewport before updating.
353
- @param {String} [up-restore-scroll='false']
350
+ @param {string} [up-restore-scroll='false']
354
351
  Whether to restore previously known scroll position of all viewports
355
352
  within the target selector.
356
- @param {String} [up-cache]
353
+ @param {string} [up-cache]
357
354
  Whether to force the use of a cached response (`true`)
358
355
  or never use the cache (`false`)
359
356
  or make an educated guess (default).
360
- @param {String} [up-layer='auto']
357
+ @param {string} [up-layer='auto']
361
358
  The name of the layer that ought to be updated. Valid values are
362
359
  `auto`, `page`, `modal` and `popup`.
363
360
 
364
361
  If set to `auto` (default), Unpoly will try to find a match in the link's layer.
365
362
  If no match was found in that layer,
366
363
  Unpoly will search in other layers, starting from the topmost layer.
367
- @param {String} [up-fail-layer='auto']
364
+ @param {string} [up-fail-layer='auto']
368
365
  The name of the layer that ought to be updated if the server sends a
369
366
  non-200 status code.
370
367
  @param [up-history]
@@ -374,33 +371,13 @@ up.link = (($) ->
374
371
  Set this to a URL string to update the history with the given URL.
375
372
  @stable
376
373
  ###
377
- onAction '[up-target]', ($link) ->
378
- follow($link)
379
-
380
- ###*
381
- By adding an `up-instant` attribute to a link, the destination will be
382
- fetched on `mousedown` instead of `click` (`mouseup`).
383
-
384
- <a href="/users" up-target=".main" up-instant>User list</a>
385
-
386
- This will save precious milliseconds that otherwise spent
387
- on waiting for the user to release the mouse button. Since an
388
- AJAX request will be triggered right way, the interaction will
389
- appear faster.
390
-
391
- Note that using `[up-instant]` will prevent a user from canceling a link
392
- click by moving the mouse away from the interaction area. However, for
393
- navigation actions this isn't needed. E.g. popular operation
394
- systems switch tabs on `mousedown` instead of `click`.
395
-
396
- `up-instant` will also work for links that open [modals](/up.modal) or [popups](/up.popup).
397
-
398
- @selector [up-instant]
399
- @stable
400
- ###
374
+ DEFAULT_FOLLOW_VARIANT = addFollowVariant '[up-target], [up-follow]',
375
+ # Don't just pass the `defaultFollow` function reference so we can stub it in tests
376
+ follow: ($link, options) -> defaultFollow($link, options)
377
+ preload: ($link, options) -> defaultPreload($link, options)
401
378
 
402
379
  ###*
403
- If applied on a link, Follows this link via AJAX and replaces the
380
+ If applied on a link, follows this link via AJAX and replaces the
404
381
  current `<body>` element with the response's `<body>` element.
405
382
 
406
383
  To only update a fragment instead of the entire page, see
@@ -422,24 +399,24 @@ up.link = (($) ->
422
399
 
423
400
  @selector a[up-follow]
424
401
 
425
- @param {String} [up-method='get']
402
+ @param {string} [up-method='get']
426
403
  The HTTP method to use for the request.
427
404
  @param [up-fail-target='body']
428
405
  The selector to replace if the server responds with a non-200 status code.
429
- @param {String} [up-fallback]
406
+ @param {string} [up-fallback]
430
407
  The selector to update when the original target was not found in the page.
431
- @param {String} [up-transition='none']
408
+ @param {string} [up-transition='none']
432
409
  The [transition](/up.motion) to use for morphing between the old and new elements.
433
- @param {String} [up-fail-transition='none']
410
+ @param {string} [up-fail-transition='none']
434
411
  The [transition](/up.motion) to use for morphing between the old and new elements
435
412
  when the server responds with a non-200 status code.
436
413
  @param [up-href]
437
414
  The destination URL to follow.
438
415
  If omitted, the the link's `href` attribute will be used.
439
- @param {String} [up-confirm]
416
+ @param {string} [up-confirm]
440
417
  A message that will be displayed in a cancelable confirmation dialog
441
418
  before the link is followed.
442
- @param {String} [up-history]
419
+ @param {string} [up-history]
443
420
  Whether to push an entry to the browser history when following the link.
444
421
 
445
422
  Set this to `'false'` to prevent the URL bar from being updated.
@@ -449,8 +426,28 @@ up.link = (($) ->
449
426
  within the response.
450
427
  @stable
451
428
  ###
452
- onAction '[up-follow]', ($link) ->
453
- follow($link)
429
+
430
+ ###*
431
+ By adding an `up-instant` attribute to a link, the destination will be
432
+ fetched on `mousedown` instead of `click` (`mouseup`).
433
+
434
+ <a href="/users" up-target=".main" up-instant>User list</a>
435
+
436
+ This will save precious milliseconds that otherwise spent
437
+ on waiting for the user to release the mouse button. Since an
438
+ AJAX request will be triggered right way, the interaction will
439
+ appear faster.
440
+
441
+ Note that using `[up-instant]` will prevent a user from canceling a link
442
+ click by moving the mouse away from the interaction area. However, for
443
+ navigation actions this isn't needed. E.g. popular operation
444
+ systems switch tabs on `mousedown` instead of `click`.
445
+
446
+ `up-instant` will also work for links that open [modals](/up.modal) or [popups](/up.popup).
447
+
448
+ @selector a[up-instant]
449
+ @stable
450
+ ###
454
451
 
455
452
  ###*
456
453
  Marks up the current link to be followed *as fast as possible*.
@@ -458,8 +455,8 @@ up.link = (($) ->
458
455
  This is done by:
459
456
 
460
457
  - [Following the link through AJAX](/a-up-target) instead of a full page load
461
- - [Preloading the link's destination URL](/up-preload)
462
- - [Triggering the link on `mousedown`](/up-instant) instead of on `click`
458
+ - [Preloading the link's destination URL](/a-up-preload)
459
+ - [Triggering the link on `mousedown`](/a-up-instant) instead of on `click`
463
460
 
464
461
  Use `up-dash` like this:
465
462
 
@@ -469,10 +466,10 @@ up.link = (($) ->
469
466
 
470
467
  <a href="/users" up-target=".main" up-instant up-preload>User list</a>
471
468
 
472
- @selector [up-dash]
469
+ @selector a[up-dash]
473
470
  @stable
474
471
  ###
475
- up.macro '[up-dash]', { priority: 'last' }, ($element) ->
472
+ up.macro '[up-dash]', ($element) ->
476
473
  target = u.castedAttr($element, 'up-dash')
477
474
  $element.removeAttr('up-dash')
478
475
  newAttrs = {
@@ -488,11 +485,11 @@ up.link = (($) ->
488
485
  u.setMissingAttrs($element, newAttrs)
489
486
 
490
487
  ###*
491
- Add an `up-expand` class to any element that contains a link
488
+ Add an `[up-expand]` attribute to any element that contains a link
492
489
  in order to enlarge the link's click area.
493
490
 
494
- `up-expand` honors all the UJS behavior in expanded links
495
- ([`up-target`](/a-up-target), [`up-instant`](/up-instant), [`up-preload`](/up-preload), etc.).
491
+ `[up-expand]` honors all the UJS behavior in expanded links
492
+ ([`a[up-target]`](/a-up-target), [`a[up-instant]`](/a-up-instant), [`a[up-preload]`](/a-up-preload), etc.).
496
493
 
497
494
  \#\#\# Example
498
495
 
@@ -519,20 +516,22 @@ up.link = (($) ->
519
516
 
520
517
  \#\#\# Limitations
521
518
 
522
- Users will not be able to use the expanded area to open a context menu by right clicking,
523
- or to open the link in a new tab.
524
- To enable this, make the entire clickable area an actual `<a>` tag.
525
- [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).
519
+ `[up-expand]` has some limitations for advanced browser users:
520
+
521
+ - Users won't be able to right-click the expanded area to open a context menu
522
+ - Users won't be able to CTRL+click the expanded area to open a new tab
526
523
 
524
+ To overcome these limitations, consider nesting the entire clickable area in an actual `<a>` tag.
525
+ [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).
527
526
 
528
527
  @selector [up-expand]
529
- @param {String} [up-expand]
528
+ @param {string} [up-expand]
530
529
  A CSS selector that defines which containing link should be expanded.
531
530
 
532
531
  If omitted, the first contained link will be expanded.
533
532
  @stable
534
533
  ###
535
- up.macro '[up-expand]', { priority: 'last' }, ($area) ->
534
+ up.macro '[up-expand]', ($area) ->
536
535
  $childLinks = $area.find('a, [up-href]')
537
536
  if selector = $area.attr('up-expand')
538
537
  $childLinks = $childLinks.filter(selector)
@@ -552,11 +551,13 @@ up.link = (($) ->
552
551
  visit: visit
553
552
  follow: follow
554
553
  makeFollowable: makeFollowable
554
+ isSafe: isSafe
555
555
  isFollowable: isFollowable
556
- shouldProcessLinkEvent: shouldProcessLinkEvent
557
556
  childClicked: childClicked
558
557
  followMethod: followMethod
559
- onAction: onAction
558
+ addFollowVariant: addFollowVariant
559
+ followVariantForLink: followVariantForLink
560
+ allowDefault: allowDefault
560
561
 
561
562
  )(jQuery)
562
563
 
@@ -24,18 +24,18 @@ up.log = (($) ->
24
24
  Configures the logging output on the developer console.
25
25
 
26
26
  @property up.log.config
27
- @param {Boolean} [options.enabled=false]
27
+ @param {boolean} [options.enabled=false]
28
28
  Whether Unpoly will print debugging information to the developer console.
29
29
 
30
30
  Debugging information includes which elements are being [compiled](/up.syntax)
31
31
  and which [events](/up.bus) are being emitted.
32
32
  Note that errors will always be printed, regardless of this setting.
33
- @param {Boolean} [options.collapse=false]
33
+ @param {boolean} [options.collapse=false]
34
34
  Whether debugging information is printed as a collapsed tree.
35
35
 
36
36
  Set this to `true` if you are overwhelmed by the debugging information Unpoly
37
37
  prints to the developer console.
38
- @param {String} [options.prefix='[UP] ']
38
+ @param {string} [options.prefix='[UP] ']
39
39
  A string to prepend to Unpoly's logging messages so you can distinguish it from your own messages.
40
40
  @stable
41
41
  ###
@@ -54,7 +54,7 @@ up.log = (($) ->
54
54
  Prints a debugging message to the browser console.
55
55
 
56
56
  @function up.log.debug
57
- @param {String} message
57
+ @param {string} message
58
58
  @param {Array} args...
59
59
  @internal
60
60
  ###
@@ -66,7 +66,7 @@ up.log = (($) ->
66
66
  Prints a logging message to the browser console.
67
67
 
68
68
  @function up.puts
69
- @param {String} message
69
+ @param {string} message
70
70
  @param {Array} args...
71
71
  @internal
72
72
  ###