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
@@ -5,7 +5,7 @@ Modal dialogs
5
5
  Instead of [linking to a page fragment](/up.link), you can choose to show a fragment
6
6
  in a modal dialog. The existing page will remain open in the background.
7
7
 
8
- To open a modal, add an [`up-modal`](/up-modal) attribute to a link:
8
+ To open a modal, add an [`up-modal`](/a-up-modal) attribute to a link:
9
9
 
10
10
  <a href="/blogs" up-modal=".blog-list">Switch blog</a>
11
11
 
@@ -21,7 +21,7 @@ By default the dialog automatically closes
21
21
  This is useful to have the dialog interact with the page that
22
22
  opened it, e.g. by updating parts of a larger form.
23
23
 
24
- To disable this behavior, give the opening link an [`up-sticky`](/up-modal#up-sticky) attribute:
24
+ To disable this behavior, give the opening link an [`up-sticky`](/a-up-modal#up-sticky) attribute:
25
25
 
26
26
 
27
27
  \#\#\# Customizing the dialog design
@@ -64,24 +64,24 @@ up.modal = (($) ->
64
64
  Sets default options for future modals.
65
65
 
66
66
  @property up.modal.config
67
- @param {String} [config.history=true]
67
+ @param {string} [config.history=true]
68
68
  Whether opening a modal will add a browser history entry.
69
- @param {Number} [config.width]
69
+ @param {number} [config.width]
70
70
  The width of the dialog as a CSS value like `'400px'` or `'50%'`.
71
71
 
72
72
  Defaults to `undefined`, meaning that the dialog will grow to fit its contents
73
73
  until it reaches `config.maxWidth`. Leaving this as `undefined` will
74
74
  also allow you to control the width using CSS on `.up-modal-dialog´.
75
- @param {Number} [config.maxWidth]
75
+ @param {number} [config.maxWidth]
76
76
  The width of the dialog as a CSS value like `'400px'` or `50%`.
77
77
  You can set this to `undefined` to make the dialog fit its contents.
78
78
  Be aware however, that e.g. Bootstrap stretches input elements
79
79
  to `width: 100%`, meaning the dialog will also stretch to the full
80
80
  width of the screen.
81
- @param {Number} [config.height='auto']
81
+ @param {number} [config.height='auto']
82
82
  The height of the dialog in pixels.
83
83
  Defaults to `undefined`, meaning that the dialog will grow to fit its contents.
84
- @param {String|Function(config)} [config.template]
84
+ @param {string|Function(config)} [config.template]
85
85
  A string containing the HTML structure of the modal.
86
86
  You can supply an alternative template string, but make sure that it
87
87
  defines tag with the classes `up-modal`, `up-modal-dialog` and `up-modal-content`.
@@ -89,34 +89,34 @@ up.modal = (($) ->
89
89
  You can also supply a function that returns a HTML string.
90
90
  The function will be called with the modal options (merged from these defaults
91
91
  and any per-open overrides) whenever a modal opens.
92
- @param {String} [config.closeLabel='×']
92
+ @param {string} [config.closeLabel='×']
93
93
  The label of the button that closes the dialog.
94
- @param {Boolean} [config.closable=true]
94
+ @param {boolean} [config.closable=true]
95
95
  When `true`, the modal will render a close icon and close when the user
96
96
  clicks on the backdrop or presses Escape.
97
97
 
98
98
  When `false`, you need to either supply an element with `[up-close]` or
99
99
  close the modal manually with `up.modal.close()`.
100
- @param {String} [config.openAnimation='fade-in']
100
+ @param {string} [config.openAnimation='fade-in']
101
101
  The animation used to open the viewport around the dialog.
102
- @param {String} [config.closeAnimation='fade-out']
102
+ @param {string} [config.closeAnimation='fade-out']
103
103
  The animation used to close the viewport the dialog.
104
- @param {String} [config.backdropOpenAnimation='fade-in']
104
+ @param {string} [config.backdropOpenAnimation='fade-in']
105
105
  The animation used to open the backdrop that dims the page below the dialog.
106
- @param {String} [config.backdropCloseAnimation='fade-out']
106
+ @param {string} [config.backdropCloseAnimation='fade-out']
107
107
  The animation used to close the backdrop that dims the page below the dialog.
108
- @param {Number} [config.openDuration]
108
+ @param {number} [config.openDuration]
109
109
  The duration of the open animation (in milliseconds).
110
- @param {Number} [config.closeDuration]
110
+ @param {number} [config.closeDuration]
111
111
  The duration of the close animation (in milliseconds).
112
- @param {String} [config.openEasing]
112
+ @param {string} [config.openEasing]
113
113
  The timing function controlling the acceleration of the opening animation.
114
- @param {String} [config.closeEasing]
114
+ @param {string} [config.closeEasing]
115
115
  The timing function controlling the acceleration of the closing animation.
116
- @param {Boolean} [options.sticky=false]
116
+ @param {boolean} [options.sticky=false]
117
117
  If set to `true`, the modal remains
118
118
  open even it changes the page in the background.
119
- @param {String} [options.flavor='default']
119
+ @param {string} [options.flavor='default']
120
120
  The default [flavor](/up.modal.flavors).
121
121
  @stable
122
122
  ###
@@ -156,7 +156,7 @@ up.modal = (($) ->
156
156
 
157
157
  \#\#\# Example
158
158
 
159
- Unpoly's [`[up-drawer]`](/up-drawer) is implemented as a modal flavor:
159
+ Unpoly's [`[up-drawer]`](/a-up-drawer) is implemented as a modal flavor:
160
160
 
161
161
  up.modal.flavors.drawer = {
162
162
  openAnimation: 'move-from-right',
@@ -197,7 +197,7 @@ up.modal = (($) ->
197
197
  or `undefined` if no modal is currently open.
198
198
 
199
199
  @function up.modal.url
200
- @return {String}
200
+ @return {string}
201
201
  the source URL
202
202
  @stable
203
203
  ###
@@ -206,7 +206,7 @@ up.modal = (($) ->
206
206
  Returns the URL of the page behind the modal overlay.
207
207
 
208
208
  @function up.modal.coveredUrl
209
- @return {String}
209
+ @return {string}
210
210
  @experimental
211
211
  ###
212
212
 
@@ -297,7 +297,7 @@ up.modal = (($) ->
297
297
  This also returns `true` if the modal is in an opening or closing animation.
298
298
 
299
299
  @function up.modal.isOpen
300
- @return {Boolean}
300
+ @return {boolean}
301
301
  @stable
302
302
  ###
303
303
  isOpen = ->
@@ -314,42 +314,42 @@ up.modal = (($) ->
314
314
  Emits events [`up:modal:open`](/up:modal:open) and [`up:modal:opened`](/up:modal:opened).
315
315
 
316
316
  @function up.modal.follow
317
- @param {Element|jQuery|String} linkOrSelector
317
+ @param {Element|jQuery|string} linkOrSelector
318
318
  The link to follow.
319
- @param {String} [options.target]
319
+ @param {string} [options.target]
320
320
  The selector to extract from the response and open in a modal dialog.
321
- @param {Number} [options.width]
321
+ @param {number} [options.width]
322
322
  The width of the dialog in pixels.
323
323
  By [default](/up.modal.config) the dialog will grow to fit its contents.
324
- @param {Number} [options.height]
324
+ @param {number} [options.height]
325
325
  The width of the dialog in pixels.
326
326
  By [default](/up.modal.config) the dialog will grow to fit its contents.
327
- @param {Boolean} [options.sticky=false]
327
+ @param {boolean} [options.sticky=false]
328
328
  If set to `true`, the modal remains
329
329
  open even it changes the page in the background.
330
- @param {Boolean} [config.closable=true]
330
+ @param {boolean} [config.closable=true]
331
331
  When `true`, the modal will render a close icon and close when the user
332
332
  clicks on the backdrop or presses Escape.
333
333
 
334
334
  When `false`, you need to either supply an element with `[up-close]` or
335
335
  close the modal manually with `up.modal.close()`.
336
- @param {String} [options.confirm]
336
+ @param {string} [options.confirm]
337
337
  A message that will be displayed in a cancelable confirmation dialog
338
338
  before the modal is being opened.
339
- @param {String} [options.method="GET"]
339
+ @param {string} [options.method="GET"]
340
340
  Override the request method.
341
- @param {Object} [options.history=true]
341
+ @param {boolean} [options.history=true]
342
342
  Whether to add a browser history entry for the modal's source URL.
343
- @param {String} [options.animation]
343
+ @param {string} [options.animation]
344
344
  The animation to use when opening the modal.
345
- @param {Number} [options.duration]
345
+ @param {number} [options.duration]
346
346
  The duration of the animation. See [`up.animate()`](/up.animate).
347
- @param {Number} [options.delay]
347
+ @param {number} [options.delay]
348
348
  The delay before the animation starts. See [`up.animate()`](/up.animate).
349
- @param {String} [options.easing]
349
+ @param {string} [options.easing]
350
350
  The timing function that controls the animation's acceleration. [`up.animate()`](/up.animate).
351
351
  @return {Promise}
352
- A promise that will be resolved when the modal has been loaded and
352
+ A promise that will be fulfilled when the modal has been loaded and
353
353
  the opening animation has completed.
354
354
  @stable
355
355
  ###
@@ -358,6 +358,14 @@ up.modal = (($) ->
358
358
  options.$link = $(linkOrSelector)
359
359
  openAsap(options)
360
360
 
361
+ preloadNow = ($link, options) ->
362
+ options = u.options(options)
363
+ options.$link = $link
364
+ options.preload = true
365
+ # Use openNow() and not openAsap() so (1) we don't close a currently open modal
366
+ # and (2) our pending AJAX request does not prevent other modals from opening
367
+ openNow(options)
368
+
361
369
  ###*
362
370
  Opens a modal for the given URL.
363
371
 
@@ -371,15 +379,15 @@ up.modal = (($) ->
371
379
  Emits events [`up:modal:open`](/up:modal:open) and [`up:modal:opened`](/up:modal:opened).
372
380
 
373
381
  @function up.modal.visit
374
- @param {String} url
382
+ @param {string} url
375
383
  The URL to load.
376
- @param {String} options.target
384
+ @param {string} options.target
377
385
  The CSS selector to extract from the response.
378
386
  The extracted content will be placed into the dialog window.
379
387
  @param {Object} options
380
388
  See options for [`up.modal.follow()`](/up.modal.follow).
381
389
  @return {Promise}
382
- A promise that will be resolved when the modal has been loaded and the opening
390
+ A promise that will be fulfilled when the modal has been loaded and the opening
383
391
  animation has completed.
384
392
  @stable
385
393
  ###
@@ -404,14 +412,14 @@ up.modal = (($) ->
404
412
  Emits events [`up:modal:open`](/up:modal:open) and [`up:modal:opened`](/up:modal:opened).
405
413
 
406
414
  @function up.modal.extract
407
- @param {String} selector
415
+ @param {string} selector
408
416
  The CSS selector to extract from the HTML.
409
- @param {String} html
417
+ @param {string} html
410
418
  The HTML containing the modal content.
411
419
  @param {Object} options
412
420
  See options for [`up.modal.follow()`](/up.modal.follow).
413
421
  @return {Promise}
414
- A promise that will be resolved when the modal has been opened and the opening
422
+ A promise that will be fulfilled when the modal has been opened and the opening
415
423
  animation has completed.
416
424
  @stable
417
425
  ###
@@ -423,12 +431,7 @@ up.modal = (($) ->
423
431
  openAsap(options)
424
432
 
425
433
  openAsap = (options) ->
426
- curriedOpenNow = -> openNow(options)
427
- if isOpen()
428
- chain.asap(closeNow, curriedOpenNow)
429
- else
430
- chain.asap(curriedOpenNow)
431
- chain.promise()
434
+ chain.asap closeNow, (-> openNow(options))
432
435
 
433
436
  openNow = (options) ->
434
437
  options = u.options(options)
@@ -451,6 +454,7 @@ up.modal = (($) ->
451
454
  options.confirm = u.option(options.confirm, $link.attr('up-confirm'))
452
455
  options.method = up.link.followMethod($link, options)
453
456
  options.layer = 'modal'
457
+ options.failTarget = u.option(options.failTarget, $link.attr('up-fail-target'))
454
458
  options.failLayer = u.option(options.failLayer, $link.attr('up-fail-layer'), 'auto')
455
459
  animateOptions = up.motion.animateOptions(options, $link, duration: flavorDefault('openDuration', options.flavor), easing: flavorDefault('openEasing', options.flavor))
456
460
 
@@ -460,6 +464,13 @@ up.modal = (($) ->
460
464
  options.history = u.option(options.history, u.castedAttr($link, 'up-history'), flavorDefault('history', options.flavor))
461
465
  options.history = false unless up.browser.canPushState()
462
466
 
467
+ # This will prevent up.replace() from looking for fallbacks, since
468
+ # it knows the target will always exist.
469
+ options.provideTarget = -> createHiddenFrame(target, options)
470
+
471
+ if options.preload
472
+ return up.replace(target, url, options)
473
+
463
474
  up.browser.whenConfirmed(options).then ->
464
475
  up.bus.whenEmitted('up:modal:open', url: url, message: 'Opening modal').then ->
465
476
  state.phase = 'opening'
@@ -470,7 +481,6 @@ up.modal = (($) ->
470
481
  if options.history
471
482
  state.coveredUrl = up.browser.url()
472
483
  state.coveredTitle = document.title
473
- options.provideTarget = -> createHiddenFrame(target, options)
474
484
  extractOptions = u.merge(options, animation: false)
475
485
  if html
476
486
  promise = up.extract(target, html, extractOptions)
@@ -512,20 +522,19 @@ up.modal = (($) ->
512
522
  @param {Object} options
513
523
  See options for [`up.animate()`](/up.animate)
514
524
  @return {Promise}
515
- A promise that will be resolved once the modal's close
525
+ A promise that will be fulfilled once the modal's close
516
526
  animation has finished.
517
527
  @stable
518
528
  ###
519
529
  closeAsap = (options) ->
520
- if isOpen()
521
- chain.asap -> closeNow(options)
522
- chain.promise()
530
+ chain.asap -> closeNow(options)
523
531
 
524
532
  closeNow = (options) ->
525
- unless isOpen() # this can happen when a request fails and the chain proceeds to the next task
526
- return u.resolvedPromise()
527
-
528
533
  options = u.options(options)
534
+
535
+ unless isOpen()
536
+ return Promise.resolve()
537
+
529
538
  viewportCloseAnimation = u.option(options.animation, flavorDefault('closeAnimation'))
530
539
  viewportCloseAnimation = u.evalOption(viewportCloseAnimation, position: state.position)
531
540
  backdropCloseAnimation = u.option(options.backdropAnimation, flavorDefault('backdropCloseAnimation'))
@@ -546,6 +555,7 @@ up.modal = (($) ->
546
555
  state.url = null
547
556
  state.coveredUrl = null
548
557
  state.coveredTitle = null
558
+
549
559
  promise = animate(viewportCloseAnimation, backdropCloseAnimation, animateOptions)
550
560
 
551
561
  promise = promise.then ->
@@ -569,13 +579,13 @@ up.modal = (($) ->
569
579
  animate = (viewportAnimation, backdropAnimation, animateOptions) ->
570
580
  # If we're not animating the dialog, don't animate the backdrop either
571
581
  if up.motion.isNone(viewportAnimation)
572
- u.resolvedPromise()
582
+ Promise.resolve()
573
583
  else
574
584
  markAsAnimating()
575
- promise = $.when(
585
+ promise = Promise.all([
576
586
  up.animate(state.$modal.find('.up-modal-viewport'), viewportAnimation, animateOptions),
577
587
  up.animate(state.$modal.find('.up-modal-backdrop'), backdropAnimation, animateOptions)
578
- )
588
+ ])
579
589
  promise = promise.then -> markAsAnimating(false)
580
590
  promise
581
591
 
@@ -607,9 +617,9 @@ up.modal = (($) ->
607
617
  within the current modal.
608
618
 
609
619
  @function up.modal.contains
610
- @param {String} elementOrSelector
620
+ @param {string} elementOrSelector
611
621
  The element to test
612
- @return {Boolean}
622
+ @return {boolean}
613
623
  @stable
614
624
  ###
615
625
  contains = (elementOrSelector) ->
@@ -617,7 +627,7 @@ up.modal = (($) ->
617
627
  $element.closest('.up-modal').length > 0
618
628
 
619
629
  flavor = (name, overrideConfig = {}) ->
620
- up.log.warn 'The up.modal.flavor function is deprecated. Use the up.modal.flavors property instead.'
630
+ up.log.warn 'up.modal.flavor() is deprecated. Use the up.modal.flavors property instead.'
621
631
  u.assign(flavorOverrides(name), overrideConfig)
622
632
 
623
633
  ###*
@@ -655,34 +665,34 @@ up.modal = (($) ->
655
665
  and place the matching `.blog-list` tag will be placed in
656
666
  a modal dialog.
657
667
 
658
- @selector [up-modal]
659
- @param {String} up-modal
668
+ @selector a[up-modal]
669
+ @param {string} up-modal
660
670
  The CSS selector that will be extracted from the response and displayed in a modal dialog.
661
- @param {String} [up-confirm]
671
+ @param {string} [up-confirm]
662
672
  A message that will be displayed in a cancelable confirmation dialog
663
673
  before the modal is opened.
664
- @param {String} [up-method='GET']
674
+ @param {string} [up-method='GET']
665
675
  Override the request method.
666
- @param {String} [up-sticky]
676
+ @param {string} [up-sticky]
667
677
  If set to `"true"`, the modal remains
668
678
  open even if the page changes in the background.
669
- @param {Boolean} [up-closable]
679
+ @param {boolean} [up-closable]
670
680
  When `true`, the modal will render a close icon and close when the user
671
681
  clicks on the backdrop or presses Escape.
672
682
 
673
683
  When `false`, you need to either supply an element with `[up-close]` or
674
684
  close the modal manually with `up.modal.close()`.
675
- @param {String} [up-animation]
685
+ @param {string} [up-animation]
676
686
  The animation to use when opening the viewport containing the dialog.
677
- @param {String} [up-backdrop-animation]
687
+ @param {string} [up-backdrop-animation]
678
688
  The animation to use when opening the backdrop that dims the page below the dialog.
679
- @param {String} [up-height]
689
+ @param {string} [up-height]
680
690
  The width of the dialog in pixels.
681
691
  By [default](/up.modal.config) the dialog will grow to fit its contents.
682
- @param {String} [up-width]
692
+ @param {string} [up-width]
683
693
  The width of the dialog in pixels.
684
694
  By [default](/up.modal.config) the dialog will grow to fit its contents.
685
- @param {String} [up-history]
695
+ @param {string} [up-history]
686
696
  Whether to push an entry to the browser history for the modal's source URL.
687
697
 
688
698
  Set this to `'false'` to prevent the URL bar from being updated.
@@ -690,8 +700,10 @@ up.modal = (($) ->
690
700
 
691
701
  @stable
692
702
  ###
693
- up.link.onAction '[up-modal]', ($link) ->
694
- followAsap($link)
703
+ up.link.addFollowVariant '[up-modal]',
704
+ # Don't just pass the `follow` function reference so we can stub it in tests
705
+ follow: ($link, options) -> followAsap($link, options)
706
+ preload: ($link, options) -> preloadNow($link, options)
695
707
 
696
708
  # Close the modal when someone clicks outside the dialog (but not on a modal opener).
697
709
  # Note that we cannot listen to clicks on .up-modal-backdrop, which is a sister element
@@ -755,10 +767,10 @@ up.modal = (($) ->
755
767
  and place the matching `.blog-list` tag will be placed in
756
768
  a modal drawer.
757
769
 
758
- @selector [up-drawer]
759
- @param {String} up-drawer
770
+ @selector a[up-drawer]
771
+ @param {string} up-drawer
760
772
  The CSS selector to extract from the response and open in the drawer.
761
- @param {String} [up-position='auto']
773
+ @param {string} [up-position='auto']
762
774
  The side from which the drawer slides in.
763
775
 
764
776
  Valid values are `'left'`, `'right'` and `'auto'`. If set to `'auto'`, the
@@ -766,7 +778,7 @@ up.modal = (($) ->
766
778
  Otherwise it will slide in from the right.
767
779
  @stable
768
780
  ###
769
- up.macro '[up-drawer]', ($link) ->
781
+ up.macro 'a[up-drawer], [up-href][up-drawer]', ($link) ->
770
782
  target = $link.attr('up-drawer')
771
783
  $link.attr
772
784
  'up-modal': target
@@ -779,7 +791,7 @@ up.modal = (($) ->
779
791
  @param {Object} config
780
792
  Default options for future drawers.
781
793
 
782
- See [`up.modal.config`] for available options.
794
+ See [`up.modal.config`](/up.modal.config) for available options.
783
795
  @experimental
784
796
  ###
785
797
  flavors.drawer =