unpoly-rails 0.52.0 → 0.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of unpoly-rails might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 24e1c3554a4c11b5fea24fea4397140f394ff0a9
4
- data.tar.gz: 7ade92982a0beb9ddb8cac452aa13ba4dfbada61
3
+ metadata.gz: 6df6e7fea86df29cccc4752d549cd7083be2341f
4
+ data.tar.gz: a7375db94c1351ed6d5f46ef9ee856898fe1b5b7
5
5
  SHA512:
6
- metadata.gz: 2b470bc42358455541f1ec11e3d08b1655be173a911aeb9acd0babe9a8cd47c76fab5128c899b79c8ba4f47baa5a4e6d464a35f0402d6577f866f92699d4f5cf
7
- data.tar.gz: fb755591fd57695660aacde41c4b09f8c3de8fc24bfaa07b24e9d3ab82920c5e76ed96a0cfd8b1a35e46c0740970d776c9f91f3820a4cb230bb8dda20c07d053
6
+ metadata.gz: 5ee1ee46c9d12ad6c40252fa31b8d877f5f32f85d3df461da82c02f7479d81f2a58d104bd3998aa478ace1215762d9be1c7e8d12e341be26aaeeb69ca399a239
7
+ data.tar.gz: 4e835e9180d7b051bb9ec126b760fc7766711ae2bca4993cc0f9fe04785e8c53a039c3ae4aed850a44bf2165b1d4adbe64b19c2ee383b8c897fccd8607114602
data/CHANGELOG.md CHANGED
@@ -6,6 +6,56 @@ Changes to this project will be documented in this file.
6
6
  This project mostly adheres to [Semantic Versioning](http://semver.org/).
7
7
 
8
8
 
9
+
10
+ Unreleased
11
+ ----------
12
+
13
+ ### New module: Passive updates
14
+
15
+ Thi work-in-progress package [`up.radio`](/up.radio) will contain functionality to
16
+ passively receive updates from the server. Currently the following functionality is implemented:
17
+
18
+ - Elements with an [`[up-hungry]`](/up-hungry) attribute are [updated](/up.replace) whenever there is a matching element found in a successful response. The element is replaced even when it isn't [targeted](/a-up-target) directly.
19
+
20
+ Use cases for this are unread message counters or notification flashes. Such elements often live in the layout, outside of the content area that is being replaced.
21
+ - When a reserver response contains a `<meta name="csrf-param">` or `<meta name="csrf-token">` element, it is automatically updated in the current page.
22
+
23
+
24
+ ### General
25
+
26
+ - Changes when generating CSS selectors for elements:
27
+ - `[aria-label]` attributes are used if no better attributes exist (like `[id]` or `[up-id]` attributes).
28
+ - Attribute values with quotes are now escaped if they appear in an attribute selector.
29
+ - Attribute selectors now use double quotes instead of single quotes.
30
+ - When a `[name]` attribute is used, the tag name is also used. E.g. `meta[name="csrf-token"]`.
31
+ - Element IDs that contain non-word characters (e.g. slashes, spaces, dots), will now generate an attribute selector like `[id="foo/bar"]`.
32
+
33
+ ### Forms
34
+
35
+ - You can give forms an `[up-fail-reveal]` attribute to indicate which element should be [revealed](/up.reveal) when the server responds with an error. You may use this, for example, to reveal the first validation error message:
36
+ ```
37
+ <form up-target=".content" up-fail-reveal=".error">
38
+ ...
39
+ </form>
40
+ ```
41
+ - Forms with an `[up-reveal]` attribute will now only honor the attribute when the form submission was successful.
42
+ - Forms with an `[up-restore-scroll]` attribute will now only honor the attribute when the form submission was successful.
43
+ - Forms with an `[up-reveal="css-selector"]` attribute will no longer crash when the selector could not be found.
44
+ - Fix a bug where you couldn't submit a form if it's ID contains a slash character ([#46](https://github.com/unpoly/unpoly/issues/46)).
45
+
46
+ ### Links
47
+
48
+ - You can give links an `[up-fail-reveal]` attribute to indicate which element should be [revealed](/up.reveal) when the server responds with an error
49
+ - Links with an `[up-reveal]` attribute will now only honor the attribute when the link could be followed successfully.
50
+ - Links with an `[up-restore-scroll]` attribute will now only honor the attribute when the link could be followed successfully.
51
+ - Links with an `[up-reveal="css-selector"]` attribute will no longer crash when the selector could not be found.
52
+
53
+ ### Animations
54
+
55
+ - When [replacing](/up.replace) multiple elements, it is no longer possible to use different [transitions](/up.morph) for each element. The same transition is always applied to all elements.
56
+
57
+
58
+
9
59
  0.52.0
10
60
  ------
11
61
 
@@ -832,9 +882,9 @@ This is a major update with some breaking changes. Expect a few more updates lik
832
882
  - Loading modals and popups will now open if there is a fragment update between the modal/popup's
833
883
  request and response.
834
884
  - [`up.follow()`](/up.follow) and [`up.replace()`](/up.replace) now have an option `{ failTarget }`.
835
- Use it to define the selector to replace if the server responds with a non-200 status code.
885
+ Use it to define the selector to replace if the server responds with an error.
836
886
  - [`[up-target]`](/a-up-target) and [`up-follow`](/a-up-follow) now have a modifying attribute `up-fail-target`.
837
- Use it to define the selector to replace if the server responds with a non-200 status code.
887
+ Use it to define the selector to replace if the server responds with an error.
838
888
  - New utility method [`up.util.reject()`](/up.util.reject)
839
889
  - New utility method [`up.util.only()`](/up.util.only)
840
890
  - New utility method [`up.util.except()`](/up.util.except)
data/dist/unpoly.js CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  (function() {
7
7
  window.up = {
8
- version: "0.52.0",
8
+ version: "0.53.0",
9
9
  renamedModule: function(oldName, newName) {
10
10
  return typeof Object.defineProperty === "function" ? Object.defineProperty(up, oldName, {
11
11
  get: function() {
@@ -41,7 +41,7 @@ that might save you from loading something like [Lodash](https://lodash.com/).
41
41
  @function up.util.noop
42
42
  @experimental
43
43
  */
44
- var $createElementFromSelector, $createPlaceholder, $submittingButton, DivertibleChain, ESCAPE_HTML_ENTITY_MAP, all, always, any, appendRequestData, assign, assignPolyfill, castedAttr, clientSize, compact, config, contains, copy, copyAttributes, createElementFromHtml, cssAnimate, detachWith, detect, documentHasVerticalScrollbar, each, escapeHtml, escapePressed, evalOption, except, extractOptions, fail, fixedToAbsolute, flatten, forceCompositing, forceRepaint, horizontalScreenHalf, identity, intersect, isArray, isBlank, isBodyDescendant, isCrossDomain, isDefined, isDetached, isElement, isFixed, isFormData, isFunction, isGiven, isJQuery, isMissing, isNull, isNumber, isObject, isOptions, isPresent, isPromise, isStandardPort, isString, isTruthy, isUndefined, isUnmodifiedKeyEvent, isUnmodifiedMouseEvent, last, map, margins, measure, memoize, merge, mergeRequestData, methodAllowsPayload, microtask, multiSelector, newDeferred, nextFrame, nonUpClasses, noop, normalizeMethod, normalizeUrl, nullJQuery, offsetParent, once, only, opacity, openConfig, option, options, parseUrl, pluckData, pluckKey, presence, presentAttr, previewable, promiseTimer, reject, rejectOnError, remove, renameKey, requestDataAsArray, requestDataAsQuery, requestDataFromForm, scrollbarWidth, select, selectInDynasty, selectInSubtree, selectorForElement, sequence, setMissingAttrs, setTimer, submittedValue, temporaryCss, times, toArray, trim, unJQuery, uniq, unresolvablePromise, unwrapElement, whenReady;
44
+ var $createElementFromSelector, $createPlaceholder, $submittingButton, DivertibleChain, ESCAPE_HTML_ENTITY_MAP, all, always, any, appendRequestData, assign, assignPolyfill, attributeSelector, castedAttr, clientSize, compact, config, contains, copy, copyAttributes, createElementFromHtml, cssAnimate, detachWith, detect, documentHasVerticalScrollbar, each, escapeHtml, escapePressed, evalOption, except, extractOptions, fail, fixedToAbsolute, flatten, forceCompositing, forceRepaint, horizontalScreenHalf, identity, intersect, isArray, isBlank, isBodyDescendant, isCrossDomain, isDefined, isDetached, isElement, isFixed, isFormData, isFunction, isGiven, isJQuery, isMissing, isNull, isNumber, isObject, isOptions, isPresent, isPromise, isStandardPort, isString, isTruthy, isUndefined, isUnmodifiedKeyEvent, isUnmodifiedMouseEvent, last, map, margins, measure, memoize, merge, mergeRequestData, methodAllowsPayload, microtask, multiSelector, newDeferred, nextFrame, nonUpClasses, noop, normalizeMethod, normalizeUrl, nullJQuery, offsetParent, once, only, opacity, openConfig, option, options, parseUrl, pluckData, pluckKey, presence, presentAttr, previewable, promiseTimer, reject, rejectOnError, remove, renameKey, requestDataAsArray, requestDataAsQuery, requestDataFromForm, scrollbarWidth, select, selectInDynasty, selectInSubtree, selectorForElement, sequence, setMissingAttrs, setTimer, submittedValue, temporaryCss, times, toArray, trim, unJQuery, uniq, unresolvablePromise, unwrapElement, whenReady;
45
45
  noop = $.noop;
46
46
 
47
47
  /**
@@ -252,26 +252,37 @@ that might save you from loading something like [Lodash](https://lodash.com/).
252
252
  @experimental
253
253
  */
254
254
  selectorForElement = function(element) {
255
- var $element, classes, i, id, klass, len, name, selector, upId;
255
+ var $element, ariaLabel, classes, i, id, klass, len, name, selector, tagName, upId;
256
256
  $element = $(element);
257
257
  selector = void 0;
258
+ tagName = $element.prop('tagName').toLowerCase();
258
259
  if (upId = presence($element.attr("up-id"))) {
259
- selector = "[up-id='" + upId + "']";
260
+ selector = attributeSelector('up-id', upId);
260
261
  } else if (id = presence($element.attr("id"))) {
261
- selector = "#" + id;
262
+ if (id.match(/^[a-z0-9\-_]+$/i)) {
263
+ selector = "#" + id;
264
+ } else {
265
+ selector = attributeSelector('id', id);
266
+ }
262
267
  } else if (name = presence($element.attr("name"))) {
263
- selector = "[name='" + name + "']";
268
+ selector = tagName + attributeSelector('name', name);
264
269
  } else if (classes = presence(nonUpClasses($element))) {
265
270
  selector = '';
266
271
  for (i = 0, len = classes.length; i < len; i++) {
267
272
  klass = classes[i];
268
273
  selector += "." + klass;
269
274
  }
275
+ } else if (ariaLabel = presence($element.attr("aria-label"))) {
276
+ selector = attributeSelector('aria-label', ariaLabel);
270
277
  } else {
271
- selector = $element.prop('tagName').toLowerCase();
278
+ selector = tagName;
272
279
  }
273
280
  return selector;
274
281
  };
282
+ attributeSelector = function(attribute, value) {
283
+ value = value.replace(/"/g, '\\"');
284
+ return "[" + attribute + "=\"" + value + "\"]";
285
+ };
275
286
  nonUpClasses = function($element) {
276
287
  var classString, classes;
277
288
  classString = $element.attr('class') || '';
@@ -2436,6 +2447,7 @@ that might save you from loading something like [Lodash](https://lodash.com/).
2436
2447
  function ExtractCascade(selector, options) {
2437
2448
  this.oldPlanNotFound = bind(this.oldPlanNotFound, this);
2438
2449
  this.matchingPlanNotFound = bind(this.matchingPlanNotFound, this);
2450
+ this.hungrySteps = bind(this.hungrySteps, this);
2439
2451
  this.bestMatchingSteps = bind(this.bestMatchingSteps, this);
2440
2452
  this.bestPreflightSelector = bind(this.bestPreflightSelector, this);
2441
2453
  this.detectPlan = bind(this.detectPlan, this);
@@ -2446,13 +2458,15 @@ that might save you from loading something like [Lodash](https://lodash.com/).
2446
2458
  humanizedTarget: 'selector',
2447
2459
  layer: 'auto'
2448
2460
  });
2461
+ this.options.transition = u.option(this.options.transition, this.options.animation);
2462
+ this.options.hungry = u.option(this.options.hungry, true);
2449
2463
  this.candidates = this.buildCandidates(selector);
2450
2464
  this.plans = u.map(this.candidates, (function(_this) {
2451
2465
  return function(candidate, i) {
2452
2466
  var planOptions;
2453
2467
  planOptions = u.copy(_this.options);
2454
2468
  if (i > 0) {
2455
- planOptions.transition = up.dom.config.fallbackTransition;
2469
+ planOptions.transition = u.option(up.dom.config.fallbackTransition, _this.options.transition);
2456
2470
  }
2457
2471
  return new up.ExtractPlan(candidate, planOptions);
2458
2472
  };
@@ -2503,12 +2517,34 @@ that might save you from loading something like [Lodash](https://lodash.com/).
2503
2517
  ExtractCascade.prototype.bestMatchingSteps = function() {
2504
2518
  var plan;
2505
2519
  if (plan = this.matchingPlan()) {
2506
- return plan.steps;
2520
+ return plan.steps.concat(this.hungrySteps());
2507
2521
  } else {
2508
2522
  return this.matchingPlanNotFound();
2509
2523
  }
2510
2524
  };
2511
2525
 
2526
+ ExtractCascade.prototype.hungrySteps = function() {
2527
+ var $hungries, $hungry, $newHungry, hungry, j, len, selector, steps, transition;
2528
+ steps = [];
2529
+ if (this.options.hungry) {
2530
+ $hungries = up.radio.hungrySelector().select();
2531
+ for (j = 0, len = $hungries.length; j < len; j++) {
2532
+ hungry = $hungries[j];
2533
+ $hungry = $(hungry);
2534
+ selector = u.selectorForElement($hungry);
2535
+ if ($newHungry = this.options.response.first(selector)) {
2536
+ transition = u.option(up.radio.config.hungryTransition, this.options.transition);
2537
+ steps.push({
2538
+ $old: $hungry,
2539
+ $new: $newHungry,
2540
+ transition: transition
2541
+ });
2542
+ }
2543
+ }
2544
+ }
2545
+ return steps;
2546
+ };
2547
+
2512
2548
  ExtractCascade.prototype.matchingPlanNotFound = function() {
2513
2549
  var inspectAction, message;
2514
2550
  if (this.newPlan()) {
@@ -2561,7 +2597,7 @@ that might save you from loading something like [Lodash](https://lodash.com/).
2561
2597
  this.findOld = bind(this.findOld, this);
2562
2598
  this.origin = options.origin;
2563
2599
  this.selector = up.dom.resolveSelector(selector, options.origin);
2564
- this.transition = options.transition || options.animation || 'none';
2600
+ this.transition = options.transition;
2565
2601
  this.response = options.response;
2566
2602
  this.oldLayer = options.layer;
2567
2603
  this.steps = this.parseSteps();
@@ -2616,30 +2652,26 @@ that might save you from loading something like [Lodash](https://lodash.com/).
2616
2652
  */
2617
2653
 
2618
2654
  ExtractPlan.prototype.parseSteps = function() {
2619
- var comma, disjunction, transitions;
2620
- if (u.isString(this.transition)) {
2621
- transitions = this.transition.split(comma);
2622
- } else {
2623
- transitions = [this.transition];
2624
- }
2655
+ var comma, disjunction;
2625
2656
  comma = /\ *,\ */;
2626
2657
  disjunction = this.selector.split(comma);
2627
- return u.map(disjunction, function(literal, i) {
2628
- var literalParts, pseudoClass, selector, transition;
2629
- literalParts = literal.match(/^(.+?)(?:\:(before|after))?$/);
2630
- literalParts || up.fail('Could not parse selector literal "%s"', literal);
2631
- selector = literalParts[1];
2632
- if (selector === 'html') {
2633
- selector = 'body';
2634
- }
2635
- pseudoClass = literalParts[2];
2636
- transition = transitions[i] || u.last(transitions);
2637
- return {
2638
- selector: selector,
2639
- pseudoClass: pseudoClass,
2640
- transition: transition
2658
+ return u.map(disjunction, (function(_this) {
2659
+ return function(literal, i) {
2660
+ var literalParts, pseudoClass, selector;
2661
+ literalParts = literal.match(/^(.+?)(?:\:(before|after))?$/);
2662
+ literalParts || up.fail('Could not parse selector literal "%s"', literal);
2663
+ selector = literalParts[1];
2664
+ if (selector === 'html') {
2665
+ selector = 'body';
2666
+ }
2667
+ pseudoClass = literalParts[2];
2668
+ return {
2669
+ selector: selector,
2670
+ pseudoClass: pseudoClass,
2671
+ transition: _this.transition
2672
+ };
2641
2673
  };
2642
- });
2674
+ })(this));
2643
2675
  };
2644
2676
 
2645
2677
  return ExtractPlan;
@@ -3495,17 +3527,23 @@ That said, there is an **optional** protocol your server can use to
3495
3527
  exchange additional information when Unpoly is [updating fragments](/up.link).
3496
3528
 
3497
3529
  While the protocol can help you optimize performance and handle some
3498
- edge cases, implementing it is entirely optional. For instance,
3530
+ edge cases, implementing it is **entirely optional**. For instance,
3499
3531
  `unpoly.com` itself is a static site that uses Unpoly on the frontend
3500
3532
  and doesn't even have a server component.
3501
3533
 
3502
- If you have [installed Unpoly as a Rails gem](/install/rails), the protocol
3503
- is already implemented and you will get some
3504
- [Ruby bindings](https://github.com/unpoly/unpoly/blob/master/README_RAILS.md)
3505
- in your controllers and views. If your server-side app uses another language
3506
- or framework, you should be able to implement the protocol in a very short time.
3534
+ ## Existing implementations
3535
+
3536
+ You should be able to implement the protocol in a very short time.
3537
+ There are existing implementations for various web frameworks:
3538
+
3539
+ - [Ruby on Rails](/install/rails)
3540
+ - [Roda](https://github.com/adam12/roda-unpoly)
3541
+ - [Rack](https://github.com/adam12/rack-unpoly) (Sinatra, Padrino, Hanami, Cuba, ...)
3542
+ - [Phoenix](https://elixirforum.com/t/unpoly-a-framework-like-turbolinks/3614/15) (Elixir)
3507
3543
 
3508
3544
 
3545
+ ## Protocol details
3546
+
3509
3547
  \#\#\# Redirect detection for IE11
3510
3548
 
3511
3549
  On Internet Explorer 11, Unpoly cannot detect the final URL after a redirect.
@@ -6112,7 +6150,7 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
6112
6150
  */
6113
6151
  reveal = function(elementOrSelector, options) {
6114
6152
  var $element;
6115
- $element = $(elementOrSelector);
6153
+ $element = $(elementOrSelector).first();
6116
6154
  up.puts('Revealing fragment %o', $element.get(0));
6117
6155
  options = u.options(options);
6118
6156
  return u.rejectOnError(function() {
@@ -6390,7 +6428,9 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
6390
6428
  $element = up.first(selector) || $element;
6391
6429
  revealOptions.top = true;
6392
6430
  }
6393
- return reveal($element, revealOptions);
6431
+ if ($element.length) {
6432
+ return reveal($element, revealOptions);
6433
+ }
6394
6434
  }
6395
6435
  return Promise.resolve();
6396
6436
  };
@@ -6604,13 +6644,15 @@ is built from these functions. You can use them to extend Unpoly from your
6604
6644
  It is recommend to always keep `'body'` as the last selector in the last in the case
6605
6645
  your server or load balancer renders an error message that does not contain your
6606
6646
  application layout.
6607
- @param {string} [options.fallbackTransition='none']
6608
- The transition to use when using a fallback target.
6647
+ @param {string} [options.fallbackTransition=null]
6648
+ The transition to use when using a [fallback target](/#options.fallbacks).
6649
+
6650
+ By default this is not set and the original replacement's transition is used.
6609
6651
  @stable
6610
6652
  */
6611
6653
  config = u.config({
6612
6654
  fallbacks: ['body'],
6613
- fallbackTransition: 'none'
6655
+ fallbackTransition: null
6614
6656
  });
6615
6657
  reset = function() {
6616
6658
  return config.reset();
@@ -6774,8 +6816,11 @@ is built from these functions. You can use them to extend Unpoly from your
6774
6816
  If set to `false`, the history will remain unchanged.
6775
6817
  @param {boolean|string} [options.source=true]
6776
6818
  @param {boolean|string} [options.reveal=false]
6777
- Whether to [reveal](/up.reveal) the element being updated, by
6778
- scrolling its containing viewport.
6819
+ Whether to [reveal](/up.reveal) the new fragment.
6820
+
6821
+ You can also pass a CSS selector for the element to reveal.
6822
+ @param {boolean|string} [options.failReveal=false]
6823
+ Whether to [reveal](/up.reveal) the new fragment when the server responds with an error.
6779
6824
 
6780
6825
  You can also pass a CSS selector for the element to reveal.
6781
6826
  @param {boolean} [options.restoreScroll=false]
@@ -6828,10 +6873,13 @@ is built from these functions. You can use them to extend Unpoly from your
6828
6873
  });
6829
6874
  failureOptions = u.merge(options, {
6830
6875
  humanizedTarget: 'failure target',
6831
- provideTarget: void 0
6876
+ provideTarget: void 0,
6877
+ restoreScroll: false,
6878
+ hungry: false
6832
6879
  });
6833
6880
  u.renameKey(failureOptions, 'failTransition', 'transition');
6834
6881
  u.renameKey(failureOptions, 'failLayer', 'layer');
6882
+ u.renameKey(failureOptions, 'failReveal', 'reveal');
6835
6883
  try {
6836
6884
  improvedTarget = bestPreflightSelector(selectorOrElement, successOptions);
6837
6885
  improvedFailTarget = bestPreflightSelector(options.failTarget, failureOptions);
@@ -9181,7 +9229,14 @@ new page is loading.
9181
9229
  The selector to replace.
9182
9230
  Defaults to the `[up-target]`, `[up-modal]` or `[up-popup]` attribute on `link`.
9183
9231
  If no target is given, the `<body>` element will be replaced.
9232
+ @param {boolean|string} [options.reveal=true]
9233
+ Whether to [reveal](/up.reveal) the target fragment after it was replaced.
9234
+
9235
+ You can also pass a CSS selector for the element to reveal.
9236
+ @param {boolean|string} [options.failReveal=true]
9237
+ Whether to [reveal](/up.reveal) the target fragment when the server responds with an error.
9184
9238
 
9239
+ You can also pass a CSS selector for the element to reveal.
9185
9240
  @return {Promise}
9186
9241
  A promise that will be fulfilled when the link destination
9187
9242
  has been loaded and rendered.
@@ -9221,6 +9276,7 @@ new page is loading.
9221
9276
  options.failTransition = u.option(options.failTransition, u.castedAttr($link, 'up-fail-transition'), 'none');
9222
9277
  options.history = u.option(options.history, u.castedAttr($link, 'up-history'));
9223
9278
  options.reveal = u.option(options.reveal, u.castedAttr($link, 'up-reveal'), true);
9279
+ options.failReveal = u.option(options.failReveal, u.castedAttr($link, 'up-fail-reveal'), true);
9224
9280
  options.cache = u.option(options.cache, u.castedAttr($link, 'up-cache'));
9225
9281
  options.restoreScroll = u.option(options.restoreScroll, u.castedAttr($link, 'up-restore-scroll'));
9226
9282
  options.method = followMethod($link, options);
@@ -9424,10 +9480,10 @@ new page is loading.
9424
9480
  @param {string} [up-transition='none']
9425
9481
  The [transition](/up.motion) to use for morphing between the old and new elements.
9426
9482
  @param [up-fail-target='body']
9427
- The selector to replace if the server responds with a non-200 status code.
9483
+ The selector to replace if the server responds with an error.
9428
9484
  @param {string} [up-fail-transition='none']
9429
9485
  The [transition](/up.motion) to use for morphing between the old and new elements
9430
- when the server responds with a non-200 status code.
9486
+ when the server responds with an error.
9431
9487
  @param {string} [up-fallback]
9432
9488
  The selector to update when the original target was not found in the page.
9433
9489
  @param {string} [up-href]
@@ -9437,7 +9493,13 @@ new page is loading.
9437
9493
  A message that will be displayed in a cancelable confirmation dialog
9438
9494
  before the link is followed.
9439
9495
  @param {string} [up-reveal='true']
9440
- Whether to reveal the target element within its viewport before updating.
9496
+ Whether to reveal the target element after it was replaced.
9497
+
9498
+ You can also pass a CSS selector for the element to reveal.
9499
+ @param {string} [up-fail-reveal='true']
9500
+ Whether to reveal the target element when the server responds with an error.
9501
+
9502
+ You can also pass a CSS selector for the element to reveal.
9441
9503
  @param {string} [up-restore-scroll='false']
9442
9504
  Whether to restore previously known scroll position of all viewports
9443
9505
  within the target selector.
@@ -9497,14 +9559,14 @@ new page is loading.
9497
9559
  @param {string} [up-method='get']
9498
9560
  The HTTP method to use for the request.
9499
9561
  @param [up-fail-target='body']
9500
- The selector to replace if the server responds with a non-200 status code.
9562
+ The selector to replace if the server responds with an error.
9501
9563
  @param {string} [up-fallback]
9502
9564
  The selector to update when the original target was not found in the page.
9503
9565
  @param {string} [up-transition='none']
9504
9566
  The [transition](/up.motion) to use for morphing between the old and new elements.
9505
9567
  @param {string} [up-fail-transition='none']
9506
9568
  The [transition](/up.motion) to use for morphing between the old and new elements
9507
- when the server responds with a non-200 status code.
9569
+ when the server responds with an error.
9508
9570
  @param [up-href]
9509
9571
  The destination URL to follow.
9510
9572
  If omitted, the the link's `href` attribute will be used.
@@ -9781,8 +9843,14 @@ open dialogs with sub-forms, etc. all without losing form state.
9781
9843
  The delay before the transition starts. See [`up.morph()`](/up.morph).
9782
9844
  @param {string} [options.easing]
9783
9845
  The timing function that controls the transition's acceleration. [`up.morph()`](/up.morph).
9784
- @param {Element|jQuery|string} [options.reveal=true]
9785
- Whether to reveal the target element within its viewport.
9846
+ @param {Element|string} [options.reveal=true]
9847
+ Whether to reveal the target fragment after it was replaced.
9848
+
9849
+ You can also pass a CSS selector for the element to reveal.
9850
+ @param {boolean|string} [options.failReveal=true]
9851
+ Whether to [reveal](/up.reveal) the target fragment when the server responds with an error.
9852
+
9853
+ You can also pass a CSS selector for the element to reveal.
9786
9854
  @param {boolean} [options.restoreScroll]
9787
9855
  If set to `true`, this will attempt to [`restore scroll positions`](/up.restoreScroll)
9788
9856
  previously seen on the destination URL.
@@ -9814,13 +9882,14 @@ open dialogs with sub-forms, etc. all without losing form state.
9814
9882
  target = u.option(options.target, $form.attr('up-target'), 'body');
9815
9883
  url = u.option(options.url, $form.attr('action'), up.browser.url());
9816
9884
  options.failTarget = u.option(options.failTarget, $form.attr('up-fail-target')) || u.selectorForElement($form);
9885
+ options.reveal = u.option(options.reveal, u.castedAttr($form, 'up-reveal'), true);
9886
+ options.failReveal = u.option(options.failReveal, u.castedAttr($form, 'up-fail-reveal'), true);
9817
9887
  options.fallback = u.option(options.fallback, $form.attr('up-fallback'));
9818
9888
  options.history = u.option(options.history, u.castedAttr($form, 'up-history'), true);
9819
9889
  options.transition = u.option(options.transition, u.castedAttr($form, 'up-transition'), 'none');
9820
9890
  options.failTransition = u.option(options.failTransition, u.castedAttr($form, 'up-fail-transition'), 'none');
9821
9891
  options.method = u.option(options.method, $form.attr('up-method'), $form.attr('data-method'), $form.attr('method'), 'post').toUpperCase();
9822
9892
  options.headers = u.option(options.headers, {});
9823
- options.reveal = u.option(options.reveal, u.castedAttr($form, 'up-reveal'), true);
9824
9893
  options.cache = u.option(options.cache, u.castedAttr($form, 'up-cache'));
9825
9894
  options.restoreScroll = u.option(options.restoreScroll, u.castedAttr($form, 'up-restore-scroll'));
9826
9895
  options.origin = u.option(options.origin, $form);
@@ -10232,7 +10301,7 @@ open dialogs with sub-forms, etc. all without losing form state.
10232
10301
  If omitted, Unpoly will replace the `<form>` tag itself, assuming that the
10233
10302
  server has echoed the form with validation errors.
10234
10303
  @param [up-fallback]
10235
- The selector to replace if the server responds with a non-200 status code.
10304
+ The selector to replace if the server responds with an error.
10236
10305
  @param {string} [up-transition]
10237
10306
  The animation to use when the form is replaced after a successful submission.
10238
10307
  @param {string} [up-fail-transition]
@@ -10261,7 +10330,18 @@ open dialogs with sub-forms, etc. all without losing form state.
10261
10330
  The name of the layer that ought to be updated if the server sends a
10262
10331
  non-200 status code.
10263
10332
  @param {string} [up-reveal='true']
10264
- Whether to reveal the target element within its viewport before updating.
10333
+ Whether to reveal the target element after it was replaced.
10334
+
10335
+ You can also pass a CSS selector for the element to reveal.
10336
+ @param {string} [up-fail-reveal='true']
10337
+ Whether to reveal the target element when the server responds with an error.
10338
+
10339
+ You can also pass a CSS selector for the element to reveal. You may use this, for example,
10340
+ to reveal the first validation error message:
10341
+
10342
+ <form up-target=".content" up-fail-reveal=".error">
10343
+ ...
10344
+ </form>
10265
10345
  @param {string} [up-restore-scroll='false']
10266
10346
  Whether to restore previously known scroll position of all viewports
10267
10347
  within the target selector.
@@ -12747,6 +12827,75 @@ Once the response is received the URL will change to `/bar` and the `up-active`
12747
12827
 
12748
12828
  }).call(this);
12749
12829
 
12830
+ /**
12831
+ Passive updates
12832
+ ===============
12833
+
12834
+ This work-in-progress package will contain functionality to
12835
+ passively receive updates from the server.
12836
+
12837
+ @class up.radio
12838
+ */
12839
+
12840
+ (function() {
12841
+ up.radio = (function($) {
12842
+ var config, hungrySelector, reset, u;
12843
+ u = up.util;
12844
+
12845
+ /**
12846
+ Configures defaults for passive updates.
12847
+
12848
+ @property up.radio.config
12849
+ @param {Array<string>} [options.hungry]
12850
+ An array of CSS selectors that is replaced whenever a matching element is found in a response.
12851
+ These elements are replaced even when they were not targeted directly.
12852
+
12853
+ By default this contains the [`[up-hungry]`](/up-hungry) attribute as well as
12854
+ `<meta name="csrf-param">` and `<meta name="csrf-token">` tags.
12855
+ @param {string} [options.hungryTransition=null]
12856
+ The transition to use when a [hungry element](/up-hungry) is replacing itself
12857
+ while another target is replaced.
12858
+
12859
+ By default this is not set and the original replacement's transition is used.
12860
+ @stable
12861
+ */
12862
+ config = u.config({
12863
+ hungry: ['[up-hungry]', 'meta[name="csrf-param"]', 'meta[name="csrf-token"]'],
12864
+ hungryTransition: null
12865
+ });
12866
+ reset = function() {
12867
+ return config.reset();
12868
+ };
12869
+
12870
+ /**
12871
+ @function up.radio.hungrySelector
12872
+ @internal
12873
+ */
12874
+ hungrySelector = function() {
12875
+ return u.multiSelector(config.hungry);
12876
+ };
12877
+
12878
+ /**
12879
+ Elements with this attribute are [updated](/up.replace) whenever there is a
12880
+ matching element found in a successful response. The element is replaced even
12881
+ when it isn't [targeted](/a-up-target) directly.
12882
+
12883
+ Use cases for this are unread message counters or notification flashes.
12884
+ Such elements often live in the layout, outside of the content area that is
12885
+ being replaced.
12886
+
12887
+ @selector [up-hungry]
12888
+ @stable
12889
+ */
12890
+ up.on('up:framework:reset', reset);
12891
+ return {
12892
+ config: config,
12893
+ hungrySelector: hungrySelector
12894
+ };
12895
+ })(jQuery);
12896
+
12897
+ }).call(this);
12898
+
12750
12899
  /**
12751
12900
  Play nice with Rails UJS
12752
12901
  ========================