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 @@ Pop-up overlays
5
5
  Instead of [linking to a page fragment](/up.link), you can choose
6
6
  to show a fragment in a popup overlay that rolls down from an anchoring element.
7
7
 
8
- To open a popup, add an [`up-popup` attribute](/up-popup) to a link:
8
+ To open a popup, add an [`up-popup` attribute](/a-up-popup) to a link:
9
9
 
10
10
  <a href="/options" up-popup=".menu">Show options</a>
11
11
 
@@ -22,7 +22,7 @@ The popup also closes *when a link within the popup changes a fragment behind th
22
22
  This is useful to have the popup interact with the page that
23
23
  opened it, e.g. by updating parts of a larger form.
24
24
 
25
- To disable this behavior, give the opening link an [`up-sticky`](/up-popup#up-sticky) attribute.
25
+ To disable this behavior, give the opening link an [`up-sticky`](/a-up-popup#up-sticky) attribute.
26
26
 
27
27
 
28
28
  \#\#\# Customizing the popup design
@@ -53,25 +53,25 @@ up.popup = (($) ->
53
53
  Sets default options for future popups.
54
54
 
55
55
  @property up.popup.config
56
- @param {String} [config.position='bottom-right']
56
+ @param {string} [config.position='bottom-right']
57
57
  Defines where the popup is attached to the opening element.
58
58
 
59
59
  Valid values are `bottom-right`, `bottom-left`, `top-right` and `top-left`.
60
- @param {String} [config.history=false]
60
+ @param {string} [config.history=false]
61
61
  Whether opening a popup will add a browser history entry.
62
- @param {String} [config.openAnimation='fade-in']
62
+ @param {string} [config.openAnimation='fade-in']
63
63
  The animation used to open a popup.
64
- @param {String} [config.closeAnimation='fade-out']
64
+ @param {string} [config.closeAnimation='fade-out']
65
65
  The animation used to close a popup.
66
- @param {String} [config.openDuration]
66
+ @param {string} [config.openDuration]
67
67
  The duration of the open animation (in milliseconds).
68
- @param {String} [config.closeDuration]
68
+ @param {string} [config.closeDuration]
69
69
  The duration of the close animation (in milliseconds).
70
- @param {String} [config.openEasing]
70
+ @param {string} [config.openEasing]
71
71
  The timing function controlling the acceleration of the opening animation.
72
- @param {String} [config.closeEasing]
72
+ @param {string} [config.closeEasing]
73
73
  The timing function controlling the acceleration of the closing animation.
74
- @param {Boolean} [options.sticky=false]
74
+ @param {boolean} [options.sticky=false]
75
75
  If set to `true`, the popup remains
76
76
  open even it changes the page in the background.
77
77
  @stable
@@ -92,7 +92,7 @@ up.popup = (($) ->
92
92
  Returns `undefined` if no popup is open.
93
93
 
94
94
  @function up.popup.url
95
- @return {String}
95
+ @return {string}
96
96
  the source URL
97
97
  @stable
98
98
  ###
@@ -101,7 +101,7 @@ up.popup = (($) ->
101
101
  Returns the URL of the page or modal behind the popup.
102
102
 
103
103
  @function up.popup.coveredUrl
104
- @return {String}
104
+ @return {string}
105
105
  @experimental
106
106
  ###
107
107
 
@@ -173,7 +173,7 @@ up.popup = (($) ->
173
173
  Returns whether popup modal is currently open.
174
174
 
175
175
  @function up.popup.isOpen
176
- @return {Boolean}
176
+ @return {boolean}
177
177
  @stable
178
178
  ###
179
179
  isOpen = ->
@@ -185,51 +185,46 @@ up.popup = (($) ->
185
185
  Emits events [`up:popup:open`](/up:popup:open) and [`up:popup:opened`](/up:popup:opened).
186
186
 
187
187
  @function up.popup.attach
188
- @param {Element|jQuery|String} anchor
188
+ @param {Element|jQuery|string} anchor
189
189
  The element to which the popup will be attached.
190
- @param {String} [options.url]
190
+ @param {string} [options.url]
191
191
  The URL from which to fetch the popup contents.
192
192
 
193
193
  If omitted, the `href` or `up-href` attribute of the anchor element will be used.
194
194
 
195
195
  Will be ignored if `options.html` is given.
196
- @param {String} [options.target]
196
+ @param {string} [options.target]
197
197
  A CSS selector that will be extracted from the response and placed into the popup.
198
- @param {String} [options.position='bottom-right']
198
+ @param {string} [options.position='bottom-right']
199
199
  Defines where the popup is attached to the opening element.
200
200
 
201
201
  Valid values are `bottom-right`, `bottom-left`, `top-right` and `top-left`.
202
- @param {String} [options.html]
202
+ @param {string} [options.html]
203
203
  A string of HTML from which to extract the popup contents. No network request will be made.
204
- @param {String} [options.confirm]
204
+ @param {string} [options.confirm]
205
205
  A message that will be displayed in a cancelable confirmation dialog
206
206
  before the modal is being opened.
207
- @param {String} [options.animation]
207
+ @param {string} [options.animation]
208
208
  The animation to use when opening the popup.
209
- @param {Number} [options.duration]
209
+ @param {number} [options.duration]
210
210
  The duration of the animation. See [`up.animate()`](/up.animate).
211
- @param {Number} [options.delay]
211
+ @param {number} [options.delay]
212
212
  The delay before the animation starts. See [`up.animate()`](/up.animate).
213
- @param {String} [options.easing]
213
+ @param {string} [options.easing]
214
214
  The timing function that controls the animation's acceleration. [`up.animate()`](/up.animate).
215
- @param {String} [options.method="GET"]
215
+ @param {string} [options.method="GET"]
216
216
  Override the request method.
217
- @param {Boolean} [options.sticky=false]
217
+ @param {boolean} [options.sticky=false]
218
218
  If set to `true`, the popup remains
219
219
  open even if the page changes in the background.
220
- @param {Object} [options.history=false]
220
+ @param {boolean} [options.history=false]
221
221
  @return {Promise}
222
- A promise that will be resolved when the popup has been loaded and
222
+ A promise that will be fulfilled when the popup has been loaded and
223
223
  the opening animation has completed.
224
224
  @stable
225
225
  ###
226
226
  attachAsap = (elementOrSelector, options) ->
227
- curriedAttachNow = -> attachNow(elementOrSelector, options)
228
- if isOpen()
229
- chain.asap(closeNow, curriedAttachNow)
230
- else
231
- chain.asap(curriedAttachNow)
232
- chain.promise()
227
+ chain.asap closeNow, (-> attachNow(elementOrSelector, options))
233
228
 
234
229
  attachNow = (elementOrSelector, options) ->
235
230
  $anchor = $(elementOrSelector)
@@ -238,6 +233,7 @@ up.popup = (($) ->
238
233
  options = u.options(options)
239
234
  url = u.option(u.pluckKey(options, 'url'), $anchor.attr('up-href'), $anchor.attr('href'))
240
235
  html = u.option(u.pluckKey(options, 'html'))
236
+ url or html or up.fail('up.popup.attach() requires either an { url } or { html } option')
241
237
  target = u.option(u.pluckKey(options, 'target'), $anchor.attr('up-popup'), 'body')
242
238
  position = u.option(options.position, $anchor.attr('up-position'), config.position)
243
239
  options.animation = u.option(options.animation, $anchor.attr('up-animation'), config.openAnimation)
@@ -246,8 +242,18 @@ up.popup = (($) ->
246
242
  options.confirm = u.option(options.confirm, $anchor.attr('up-confirm'))
247
243
  options.method = up.link.followMethod($anchor, options)
248
244
  options.layer = 'popup'
245
+ options.failTarget = u.option(options.failTarget, $anchor.attr('up-fail-target'))
249
246
  options.failLayer = u.option(options.failLayer, $anchor.attr('up-fail-layer'), 'auto')
247
+
248
+ # This will prevent up.replace() from looking for fallbacks, since
249
+ # it knows the target will always exist.
250
+ options.provideTarget = -> createHiddenFrame(target)
251
+
250
252
  animateOptions = up.motion.animateOptions(options, $anchor, duration: config.openDuration, easing: config.openEasing)
253
+ extractOptions = u.merge(options, animation: false)
254
+
255
+ if options.preload && url
256
+ return up.replace(target, url, options)
251
257
 
252
258
  up.browser.whenConfirmed(options).then ->
253
259
  up.bus.whenEmitted('up:popup:open', url: url, message: 'Opening popup').then ->
@@ -258,8 +264,6 @@ up.popup = (($) ->
258
264
  state.coveredUrl = up.browser.url()
259
265
  state.coveredTitle = document.title
260
266
  state.sticky = options.sticky
261
- options.provideTarget = -> createHiddenFrame(target)
262
- extractOptions = u.merge(options, animation: false)
263
267
  if html
264
268
  promise = up.extract(target, html, extractOptions)
265
269
  else
@@ -300,18 +304,16 @@ up.popup = (($) ->
300
304
  @param {Object} options
301
305
  See options for [`up.animate()`](/up.animate).
302
306
  @return {Promise}
303
- A promise that will be resolved once the modal's close
307
+ A promise that will be fulfilled once the modal's close
304
308
  animation has finished.
305
309
  @stable
306
310
  ###
307
311
  closeAsap = (options) ->
308
- if isOpen()
309
- chain.asap -> closeNow(options)
310
- chain.promise()
312
+ chain.asap -> closeNow(options)
311
313
 
312
314
  closeNow = (options) ->
313
315
  unless isOpen() # this can happen when a request fails and the chain proceeds to the next task
314
- return u.resolvedPromise()
316
+ return Promise.resolve()
315
317
 
316
318
  options = u.options(options,
317
319
  animation: config.closeAnimation
@@ -334,6 +336,19 @@ up.popup = (($) ->
334
336
  state.sticky = null
335
337
  up.emit('up:popup:closed', message: 'Popup closed')
336
338
 
339
+ preloadNow = ($link, options) ->
340
+ options = u.options(options)
341
+ options.preload = true
342
+ # Use attachNow() and not attachAsap() so (1) we don't close a currently open popup
343
+ # and (2) our pending AJAX request does not prevent other popups from opening
344
+ attachNow($link, options)
345
+
346
+ toggleAsap = ($link, options) ->
347
+ if $link.is('.up-current')
348
+ closeAsap()
349
+ else
350
+ attachAsap($link, options)
351
+
337
352
  ###*
338
353
  This event is [emitted](/up.emit) when a popup dialog
339
354
  is starting to [close](/up.popup.close).
@@ -362,9 +377,9 @@ up.popup = (($) ->
362
377
  within the current popup.
363
378
 
364
379
  @methods up.popup.contains
365
- @param {String} elementOrSelector
380
+ @param {string} elementOrSelector
366
381
  The element to test
367
- @return {Boolean}
382
+ @return {boolean}
368
383
  @stable
369
384
  ###
370
385
  contains = (elementOrSelector) ->
@@ -382,23 +397,23 @@ up.popup = (($) ->
382
397
  <a href="/decks" up-popup=".deck_list">Switch deck</a>
383
398
  <a href="/settings" up-popup=".options" up-sticky>Settings</a>
384
399
 
385
- @selector [up-popup]
386
- @param {String} up-popup
400
+ @selector a[up-popup]
401
+ @param {string} up-popup
387
402
  The CSS selector that will be extracted from the response and
388
403
  displayed in a popup overlay.
389
404
  @param [up-position]
390
405
  Defines where the popup is attached to the opening element.
391
406
 
392
407
  Valid values are `bottom-right`, `bottom-left`, `top-right` and `top-left`.
393
- @param {String} [up-confirm]
408
+ @param {string} [up-confirm]
394
409
  A message that will be displayed in a cancelable confirmation dialog
395
410
  before the popup is opened.
396
- @param {String} [up-method='GET']
411
+ @param {string} [up-method='GET']
397
412
  Override the request method.
398
413
  @param [up-sticky]
399
414
  If set to `true`, the popup remains
400
415
  open even if the page changes in the background.
401
- @param {String} [up-history='false']
416
+ @param {string} [up-history='false']
402
417
  Whether to push an entry to the browser history for the popup's source URL.
403
418
 
404
419
  Set this to `'false'` to prevent the URL bar from being updated.
@@ -406,11 +421,10 @@ up.popup = (($) ->
406
421
 
407
422
  @stable
408
423
  ###
409
- up.link.onAction '[up-popup]', ($link) ->
410
- if $link.is('.up-current')
411
- closeAsap()
412
- else
413
- attachAsap($link)
424
+ up.link.addFollowVariant '[up-popup]',
425
+ # Don't just pass the `toggleAsap` function reference so we can stub it in tests
426
+ follow: ($link, options) -> toggleAsap($link, options)
427
+ preload: ($link, options) -> preloadNow($link, options)
414
428
 
415
429
  # We close the popup when someone clicks on the document.
416
430
  # We also need to listen to up:action:consumed in case an [up-instant] link
@@ -31,7 +31,6 @@ After the form's action performs a redirect, the next response should include th
31
31
  URL in the HTTP headers:
32
32
 
33
33
  ```http
34
- X-Up-Method: GET
35
34
  X-Up-Location: /current-url
36
35
  ```
37
36
 
@@ -40,8 +39,8 @@ The **simplest implementation** is to set these headers for every request.
40
39
 
41
40
  \#\#\# Optimizing responses
42
41
 
43
- When [updating a fragment](/up.link), Unpoly will send
44
- an additional HTTP header containing the CSS selector that is being replaced:
42
+ When [updating a fragment](/up.link), Unpoly will send an
43
+ additional HTTP header containing the CSS selector that is being replaced:
45
44
 
46
45
  ```http
47
46
  X-Up-Target: .user-list
@@ -51,6 +50,13 @@ Server-side code is free to **optimize its response** by only returning HTML
51
50
  that matches the selector. For example, you might prefer to not render an
52
51
  expensive sidebar if the sidebar is not targeted.
53
52
 
53
+ Unpoly will often update a different selector in case the request fails.
54
+ This selector is also included as a HTTP header:
55
+
56
+ ```
57
+ X-Up-Fail-Target: body
58
+ ```
59
+
54
60
 
55
61
  \#\#\# Pushing a document title to the client
56
62
 
@@ -97,7 +103,7 @@ To do so in [Ruby on Rails](http://rubyonrails.org/), pass a [`:status` option t
97
103
 
98
104
  \#\#\# Detecting live form validations
99
105
 
100
- When [validating a form](/up-validate), Unpoly will
106
+ When [validating a form](/input-up-validate), Unpoly will
101
107
  send an additional HTTP header containing a CSS selector for the form that is
102
108
  being updated:
103
109
 
@@ -144,7 +150,8 @@ This fixes two edge cases you might or might not care about:
144
150
  2. Some browsers have a bug where the initial request method is used for all
145
151
  subsequently pushed states. That means if the user reloads the page on a later
146
152
  GET state, the browser will wrongly attempt a POST request.
147
- Modern Firefoxes, Chromes and IE10+ don't seem to be affected by this.
153
+ This issue affects Safari 9 and 10 (last tested in 2017-08).
154
+ Modern Firefoxes, Chromes and IE10+ don't have this behavior.
148
155
 
149
156
  In order to allow Unpoly to detect the HTTP method of the initial page load,
150
157
  the server must set a cookie:
@@ -205,38 +212,82 @@ up.protocol = (($) ->
205
212
  Configures strings used in the optional [server protocol](/up.protocol).
206
213
 
207
214
  @property up.protocol.config
208
- @param [config.targetHeader='X-Up-Target']
209
- @param [config.locationHeader='X-Up-Location']
210
- @param [config.titleHeader='X-Up-Title']
211
- @param [config.validateHeader='X-Up-Validate']
212
- @param [config.methodHeader='X-Up-Method']
213
- @param [config.methodCookie='_up_method']
214
- @param [config.methodParam='_method']
215
+ @param {String} [config.targetHeader='X-Up-Target']
216
+ @param {String} [config.failTargetHeader='X-Up-Fail-Target']
217
+ @param {String} [config.locationHeader='X-Up-Location']
218
+ @param {String} [config.titleHeader='X-Up-Title']
219
+ @param {String} [config.validateHeader='X-Up-Validate']
220
+ @param {String} [config.methodHeader='X-Up-Method']
221
+ @param {String} [config.methodCookie='_up_method']
222
+ The name of the optional cookie the server can send to
223
+ [signal the initial request method](/up.protocol#signaling-the-initial-request-method).
224
+ @param {String} [config.methodParam='_method']
215
225
  The name of the POST parameter when [wrapping HTTP methods](/up.form.config#config.wrapMethods)
216
226
  in a `POST` request.
227
+ @param {String} [config.csrfHeader='X-CSRF-Token']
228
+ The name of the HTTP header that will include the
229
+ [CSRF token](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Synchronizer_token_pattern)
230
+ for AJAX requests.
231
+ @param {String|Function} [config.csrfParam]
232
+ The `name` of the hidden `<input>` used for sending a
233
+ [CSRF token](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Synchronizer_token_pattern) when
234
+ submitting a default, non-AJAX form. For AJAX request the token is sent as an HTTP header instead.
235
+
236
+ The parameter name can be configured as a string or as function that returns the parameter name.
237
+ If no name is set, no token will be sent.
238
+
239
+ Defaults to the `content` attribute of a `<meta>` tag named `csrf-token`:
240
+
241
+ <meta name="csrf-param" content="authenticity_token" />
242
+
243
+ @param {String|Function} [config.csrfToken]
244
+ The [CSRF token](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Synchronizer_token_pattern)
245
+ to send for unsafe requests. The token will be sent as either a HTTP header (for AJAX requests)
246
+ or hidden form `<input>` (for default, non-AJAX form submissions).
247
+
248
+ The token can either be configured as a string or as function that returns the token.
249
+ If no token is set, no token will be sent.
250
+
251
+ Defaults to the `content` attribute of a `<meta>` tag named `csrf-token`:
252
+
253
+ <meta name='csrf-token' content='secret12345'>
254
+
217
255
  @experimental
218
256
  ###
219
257
  config = u.config
220
258
  targetHeader: 'X-Up-Target'
259
+ failTargetHeader: 'X-Up-Fail-Target'
221
260
  locationHeader: 'X-Up-Location'
222
261
  validateHeader: 'X-Up-Validate'
223
262
  titleHeader: 'X-Up-Title'
224
263
  methodHeader: 'X-Up-Method'
225
264
  methodCookie: '_up_method'
226
265
  methodParam: '_method'
266
+ csrfParam: -> $('meta[name="csrf-param"]').attr('content')
267
+ csrfToken: -> $('meta[name="csrf-token"]').attr('content')
268
+ csrfHeader: 'X-CSRF-Token'
227
269
 
228
- ## Unfortunately we cannot offer reset without introducing cycles
270
+ csrfParam = ->
271
+ u.evalOption(config.csrfParam)
272
+
273
+ csrfToken = ->
274
+ u.evalOption(config.csrfToken)
275
+
276
+ ## Unfortunately we cannot offer reset via event without introducing cycles
229
277
  ## in the asset load order
230
278
  #
231
- # reset = ->
232
- # config.reset()
233
- #
234
279
  # up.on 'up:framework:reset', reset
235
280
 
281
+ reset = ->
282
+ config.reset()
283
+
236
284
  config: config
285
+ reset: reset
237
286
  locationFromXhr: locationFromXhr
238
287
  titleFromXhr: titleFromXhr
239
288
  methodFromXhr: methodFromXhr
289
+ csrfParam :csrfParam
290
+ csrfToken: csrfToken
240
291
  initialRequestMethod: initialRequestMethod
241
292
 
242
293
  )(jQuery)