unpoly-rails 2.5.1 → 2.6.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.

@@ -8,7 +8,7 @@
8
8
  @module up
9
9
  */
10
10
  window.up = {
11
- version: '2.5.1'
11
+ version: '2.6.0'
12
12
  };
13
13
 
14
14
 
@@ -2101,7 +2101,32 @@ up.error = (function () {
2101
2101
  const { message } = error;
2102
2102
  up.emit(window, 'error', { message, error, log: false });
2103
2103
  }
2104
+ /*-
2105
+ Throws a [JavaScript error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)
2106
+ with the given message.
2107
+
2108
+ The message may contain [substitution marks](https://developer.mozilla.org/en-US/docs/Web/API/console#Using_string_substitutions).
2109
+
2110
+ ### Examples
2111
+
2112
+ up.fail('Division by zero')
2113
+ up.fail('Unexpected result %o', result)
2114
+
2115
+ @function up.fail
2116
+ @param {string} message
2117
+ A message with details about the error.
2118
+
2119
+ The message can contain [substitution marks](https://developer.mozilla.org/en-US/docs/Web/API/console#Using_string_substitutions)
2120
+ like `%s` or `%o`.
2121
+ @param {Array<string>} vars...
2122
+ A list of variables to replace any substitution marks in the error message.
2123
+ @internal
2124
+ */
2125
+ function fail(...args) {
2126
+ throw up.error.failed(args);
2127
+ }
2104
2128
  return {
2129
+ fail,
2105
2130
  failed,
2106
2131
  aborted,
2107
2132
  invalidSelector,
@@ -2110,6 +2135,7 @@ up.error = (function () {
2110
2135
  emitGlobal
2111
2136
  };
2112
2137
  })();
2138
+ up.fail = up.error.fail;
2113
2139
 
2114
2140
 
2115
2141
  /***/ }),
@@ -2742,11 +2768,11 @@ up.element = (function () {
2742
2768
  The [text content](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent) of the created element.
2743
2769
  @param {Object} [attrs.content]
2744
2770
  The [inner HTML](https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML) of the created element.
2745
- @param {Object} [attrs.style]
2771
+ @param {Object|string} [attrs.style]
2746
2772
  An object of CSS properties that will be set as the inline style
2747
- of the created element.
2773
+ of the created element. The given object may use kebab-case or camelCase keys.
2748
2774
 
2749
- The given object may use kebab-case or camelCase keys.
2775
+ You may also pass a string with semicolon-separated styles.
2750
2776
  @return {Element}
2751
2777
  The created element.
2752
2778
  @stable
@@ -2849,7 +2875,7 @@ up.element = (function () {
2849
2875
  An object of attributes to set on the created element.
2850
2876
  @param {Object} attrs.text
2851
2877
  The [text content](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent) of the created element.
2852
- @param {Object} attrs.style
2878
+ @param {Object|string} attrs.style
2853
2879
  An object of CSS properties that will be set as the inline style
2854
2880
  of the created element.
2855
2881
 
@@ -3352,11 +3378,16 @@ up.element = (function () {
3352
3378
  @stable
3353
3379
  */
3354
3380
  function setInlineStyle(element, props) {
3355
- const { style } = element;
3356
- for (let key in props) {
3357
- let value = props[key];
3358
- value = normalizeStyleValueForWrite(key, value);
3359
- style[key] = value;
3381
+ if (u.isString(props)) {
3382
+ element.setAttribute('style', props);
3383
+ }
3384
+ else {
3385
+ const { style } = element;
3386
+ for (let key in props) {
3387
+ let value = props[key];
3388
+ value = normalizeStyleValueForWrite(key, value);
3389
+ style[key] = value;
3390
+ }
3360
3391
  }
3361
3392
  }
3362
3393
  function normalizeStyleValueForWrite(key, value) {
@@ -4252,9 +4283,17 @@ up.Change.UpdateLayer = class UpdateLayer extends up.Change.Addition {
4252
4283
  },
4253
4284
  afterInsert: () => {
4254
4285
  this.responseDoc.finalizeElement(step.newElement);
4286
+ step.keepPlans.forEach(this.reviveKeepable);
4287
+ // In the case of [up-keep] descendants, keepable elements are now transferred
4288
+ // to step.newElement, leaving a clone in their old DOM Position.
4289
+ // up.hello() is aware of step.keepPlans and will not compile kept elements a second time.
4255
4290
  up.hello(step.newElement, step);
4256
4291
  },
4257
4292
  beforeDetach: () => {
4293
+ // In the case of [up-keep] descendants, keepable elements have been replaced
4294
+ // with a clone in step.oldElement. However, since that clone was never compiled,
4295
+ // it does not have destructors registered. Hence we will not clean the clone
4296
+ // unnecessarily.
4258
4297
  up.syntax.clean(step.oldElement, { layer: this.layer });
4259
4298
  },
4260
4299
  afterDetach() {
@@ -4372,9 +4411,10 @@ up.Change.UpdateLayer = class UpdateLayer extends up.Change.Addition {
4372
4411
  const keepPlans = [];
4373
4412
  if (step.keep) {
4374
4413
  for (let keepable of step.oldElement.querySelectorAll('[up-keep]')) {
4375
- let plan = this.findKeepPlan({ ...step, oldElement: keepable, descendantsOnly: true });
4376
- if (plan) {
4414
+ let keepPlan = this.findKeepPlan({ ...step, oldElement: keepable, descendantsOnly: true });
4415
+ if (keepPlan) {
4377
4416
  // plan.oldElement is now keepable
4417
+ this.hibernateKeepable(keepPlan);
4378
4418
  // Replace keepable with its clone so it looks good in a transition between
4379
4419
  // oldElement and newElement. Note that keepable will still point to the same element
4380
4420
  // after the replacement, which is now detached.
@@ -4382,8 +4422,8 @@ up.Change.UpdateLayer = class UpdateLayer extends up.Change.Addition {
4382
4422
  e.replace(keepable, keepableClone);
4383
4423
  // Since we're going to swap the entire oldElement and newElement containers afterwards,
4384
4424
  // replace the matching element with keepable so it will eventually return to the DOM.
4385
- e.replace(plan.newElement, keepable);
4386
- keepPlans.push(plan);
4425
+ e.replace(keepPlan.newElement, keepable);
4426
+ keepPlans.push(keepPlan);
4387
4427
  }
4388
4428
  }
4389
4429
  }
@@ -4408,6 +4448,18 @@ up.Change.UpdateLayer = class UpdateLayer extends up.Change.Addition {
4408
4448
  }
4409
4449
  }
4410
4450
  }
4451
+ hibernateKeepable(keepPlan) {
4452
+ let viewports = up.viewport.subtree(keepPlan.oldElement);
4453
+ keepPlan.revivers = viewports.map(function (viewport) {
4454
+ let { scrollTop, scrollLeft } = viewport;
4455
+ return () => u.assign(viewport, { scrollTop, scrollLeft });
4456
+ });
4457
+ }
4458
+ reviveKeepable(keepPlan) {
4459
+ for (let reviver of keepPlan.revivers) {
4460
+ reviver();
4461
+ }
4462
+ }
4411
4463
  matchPreflight() {
4412
4464
  if (this.matchedPreflight) {
4413
4465
  return;
@@ -4565,7 +4617,7 @@ up.Change.CloseLayer = class CloseLayer extends up.Change.Removal {
4565
4617
  // The close event is emitted on the layer that is about to close.
4566
4618
  return this.layer.emit(this.buildEvent(`up:layer:${this.verb}`), {
4567
4619
  callback: this.layer.callback(`on${u.upperCaseFirst(this.verb)}`),
4568
- log: `Will ${this.verb} ${this.layer}`
4620
+ log: [`Will ${this.verb} ${this.layer} with value %o`, this.value]
4569
4621
  });
4570
4622
  }
4571
4623
  emitClosedEvent(formerParent) {
@@ -4583,7 +4635,7 @@ up.Change.CloseLayer = class CloseLayer extends up.Change.Removal {
4583
4635
  baseLayer: formerParent,
4584
4636
  callback: this.layer.callback(`on${verbPastUpperCaseFirst}`),
4585
4637
  ensureBubbles: true,
4586
- log: `${verbPastUpperCaseFirst} ${this.layer}`
4638
+ log: [`${verbPastUpperCaseFirst} ${this.layer} with value %o`, this.value]
4587
4639
  });
4588
4640
  }
4589
4641
  buildEvent(name) {
@@ -5882,6 +5934,110 @@ up.FragmentFocus = class FragmentFocus extends up.FragmentProcessor {
5882
5934
  /* 33 */
5883
5935
  /***/ (() => {
5884
5936
 
5937
+ const e = up.element;
5938
+ const u = up.util;
5939
+ up.FragmentPolling = class FragmentPolling {
5940
+ constructor(fragment) {
5941
+ this.options = {};
5942
+ this.state = 'initialized';
5943
+ this.setFragment(fragment);
5944
+ }
5945
+ static forFragment(fragment) {
5946
+ return fragment.upPolling || (fragment.upPolling = new this(fragment));
5947
+ }
5948
+ onPollAttributeObserved() {
5949
+ this.start();
5950
+ }
5951
+ onFragmentDestroyed() {
5952
+ // The element may come back (when it is swapped) or or may not come back (when it is destroyed).
5953
+ // If it does come back, `onPollAttributeObserved()` will restart the polling.
5954
+ this.stop();
5955
+ }
5956
+ start() {
5957
+ if (this.state !== 'started') {
5958
+ this.state = 'started';
5959
+ this.scheduleReload();
5960
+ }
5961
+ }
5962
+ stop() {
5963
+ if (this.state === 'started') {
5964
+ clearTimeout(this.reloadTimer);
5965
+ this.state = 'stopped';
5966
+ }
5967
+ }
5968
+ forceStart(options) {
5969
+ u.assign(this.options, options);
5970
+ this.forceStarted = true;
5971
+ this.start();
5972
+ }
5973
+ forceStop() {
5974
+ this.stop();
5975
+ this.forceStarted = false;
5976
+ }
5977
+ scheduleReload(delay = this.getInterval()) {
5978
+ this.reloadTimer = setTimeout(() => this.reload(), delay);
5979
+ }
5980
+ reload() {
5981
+ // The setTimeout(doReload) callback might already be scheduled
5982
+ // before the polling stopped.
5983
+ if (this.state !== 'started') {
5984
+ return;
5985
+ }
5986
+ if (up.radio.shouldPoll(this.fragment)) {
5987
+ let reloadOptions = {
5988
+ url: this.options.url,
5989
+ guardEvent: up.event.build('up:fragment:poll', { log: 'Polling fragment' })
5990
+ };
5991
+ u.always(up.reload(this.fragment, reloadOptions), (result) => this.onReloaded(result));
5992
+ }
5993
+ else {
5994
+ up.puts('[up-poll]', 'Polling is disabled');
5995
+ // Reconsider after 10 seconds at most
5996
+ let reconsiderDisabledDelay = Math.min(10 * 1000, this.getInterval());
5997
+ this.scheduleReload(reconsiderDisabledDelay);
5998
+ }
5999
+ }
6000
+ onReloaded(result) {
6001
+ // Transfer this instance to the new fragment.
6002
+ // We can remove this in case we don't implement forced start/stop.
6003
+ let newFragment = result?.fragments?.[0];
6004
+ if (newFragment) {
6005
+ // No need to scheduleReload() in this branch:
6006
+ // (1) Either the new fragment also has an [up-poll] and we have already
6007
+ // started in #onPollAttributeObserved().
6008
+ // (2) Or we are force-started and we will start in #onFragmentSwapped().
6009
+ this.onFragmentSwapped(newFragment);
6010
+ }
6011
+ else {
6012
+ this.scheduleReload();
6013
+ }
6014
+ }
6015
+ onFragmentSwapped(newFragment) {
6016
+ // Transfer this polling to the new instance
6017
+ newFragment.upPolling = this;
6018
+ delete this.fragment.upPolling;
6019
+ this.setFragment(newFragment);
6020
+ if (this.state === 'stopped' && this.forceStarted) {
6021
+ // When polling was started programmatically through up.fragment.startPolling()
6022
+ // we don't require the updated fragment to have an [up-poll] attribute to
6023
+ // continue polling.
6024
+ this.start();
6025
+ }
6026
+ }
6027
+ setFragment(newFragment) {
6028
+ this.fragment = newFragment;
6029
+ up.destructor(newFragment, () => this.onFragmentDestroyed());
6030
+ }
6031
+ getInterval() {
6032
+ return this.options.interval ?? e.numberAttr(this.fragment, 'up-interval') ?? up.radio.config.pollInterval;
6033
+ }
6034
+ };
6035
+
6036
+
6037
+ /***/ }),
6038
+ /* 34 */
6039
+ /***/ (() => {
6040
+
5885
6041
  const u = up.util;
5886
6042
  up.FragmentScrolling = class FragmentScrolling extends up.FragmentProcessor {
5887
6043
  keys() {
@@ -5957,7 +6113,7 @@ up.FragmentScrolling = class FragmentScrolling extends up.FragmentProcessor {
5957
6113
 
5958
6114
 
5959
6115
  /***/ }),
5960
- /* 34 */
6116
+ /* 35 */
5961
6117
  /***/ (() => {
5962
6118
 
5963
6119
  const u = up.util;
@@ -5998,7 +6154,7 @@ up.HTMLWrapper = class HTMLWrapper {
5998
6154
 
5999
6155
 
6000
6156
  /***/ }),
6001
- /* 35 */
6157
+ /* 36 */
6002
6158
  /***/ (() => {
6003
6159
 
6004
6160
  const e = up.element;
@@ -6687,7 +6843,7 @@ up.Layer = class Layer extends up.Record {
6687
6843
 
6688
6844
 
6689
6845
  /***/ }),
6690
- /* 36 */
6846
+ /* 37 */
6691
6847
  /***/ (() => {
6692
6848
 
6693
6849
  const e = up.element;
@@ -6844,12 +7000,6 @@ up.Layer.Overlay = class Overlay extends up.Layer {
6844
7000
  this.createDismissElement(this.getBoxElement());
6845
7001
  }
6846
7002
  if (this.supportsDismissMethod('outside')) {
6847
- this.unbindParentClicked = this.parent.on('up:click', (event, element) => {
6848
- // When our origin is clicked again, halt the click event
6849
- // We achieve this by halting the click event.
6850
- const originClicked = this.origin && this.origin.contains(element);
6851
- this.onOutsideClicked(event, originClicked);
6852
- });
6853
7003
  // If this overlay has its own viewport, a click outside the frame will hit
6854
7004
  // the viewport and not the parent element.
6855
7005
  if (this.viewportElement) {
@@ -6860,6 +7010,18 @@ up.Layer.Overlay = class Overlay extends up.Layer {
6860
7010
  }
6861
7011
  });
6862
7012
  }
7013
+ else {
7014
+ // Only bind to the parent if there's not already a viewport.
7015
+ // This prevents issues with other overlay libs appending elements to document.body,
7016
+ // but overlaying this overlay with a huge z-index. Clicking such a foreign overlay
7017
+ // would close this layer, as Unpoly considers it to be on the root layer (our parent).2
7018
+ this.unbindParentClicked = this.parent.on('up:click', (event, element) => {
7019
+ // When our origin is clicked again, halt the click event
7020
+ // We achieve this by halting the click event.
7021
+ const originClicked = this.origin && this.origin.contains(element);
7022
+ this.onOutsideClicked(event, originClicked);
7023
+ });
7024
+ }
6863
7025
  }
6864
7026
  if (this.supportsDismissMethod('key')) {
6865
7027
  this.unbindEscapePressed = up.event.onEscape(event => this.onEscapePressed(event));
@@ -6882,7 +7044,7 @@ up.Layer.Overlay = class Overlay extends up.Layer {
6882
7044
  if (halt) {
6883
7045
  up.event.halt(event);
6884
7046
  }
6885
- this.dismiss(':outside');
7047
+ this.dismiss(':outside', { origin: event.target });
6886
7048
  }
6887
7049
  onEscapePressed(event) {
6888
7050
  // All overlays listen to the Escape key being pressed, but only the front layer
@@ -6909,7 +7071,7 @@ up.Layer.Overlay = class Overlay extends up.Layer {
6909
7071
  // Since we're defining this handler on up.Overlay, we will not prevent
6910
7072
  // a link from being followed on the root layer.
6911
7073
  up.event.halt(event);
6912
- const origin = event.target.closest(selector);
7074
+ const origin = e.closest(event.target, selector);
6913
7075
  const value = e.jsonAttr(origin, attribute);
6914
7076
  const closeOptions = { origin };
6915
7077
  const parser = new up.OptionsParser(closeOptions, origin);
@@ -7031,7 +7193,7 @@ up.Layer.Overlay = class Overlay extends up.Layer {
7031
7193
 
7032
7194
 
7033
7195
  /***/ }),
7034
- /* 37 */
7196
+ /* 38 */
7035
7197
  /***/ (() => {
7036
7198
 
7037
7199
  up.Layer.OverlayWithTether = class OverlayWithTether extends up.Layer.Overlay {
@@ -7076,7 +7238,7 @@ up.Layer.OverlayWithTether = class OverlayWithTether extends up.Layer.Overlay {
7076
7238
 
7077
7239
 
7078
7240
  /***/ }),
7079
- /* 38 */
7241
+ /* 39 */
7080
7242
  /***/ (() => {
7081
7243
 
7082
7244
  var _a;
@@ -7128,7 +7290,7 @@ up.Layer.OverlayWithViewport = (_a = class OverlayWithViewport extends up.Layer.
7128
7290
 
7129
7291
 
7130
7292
  /***/ }),
7131
- /* 39 */
7293
+ /* 40 */
7132
7294
  /***/ (() => {
7133
7295
 
7134
7296
  var _a;
@@ -7200,7 +7362,7 @@ up.Layer.Root = (_a = class Root extends up.Layer {
7200
7362
 
7201
7363
 
7202
7364
  /***/ }),
7203
- /* 40 */
7365
+ /* 41 */
7204
7366
  /***/ (() => {
7205
7367
 
7206
7368
  var _a;
@@ -7211,7 +7373,7 @@ up.Layer.Modal = (_a = class Modal extends up.Layer.OverlayWithViewport {
7211
7373
 
7212
7374
 
7213
7375
  /***/ }),
7214
- /* 41 */
7376
+ /* 42 */
7215
7377
  /***/ (() => {
7216
7378
 
7217
7379
  var _a;
@@ -7222,7 +7384,7 @@ up.Layer.Popup = (_a = class Popup extends up.Layer.OverlayWithTether {
7222
7384
 
7223
7385
 
7224
7386
  /***/ }),
7225
- /* 42 */
7387
+ /* 43 */
7226
7388
  /***/ (() => {
7227
7389
 
7228
7390
  var _a;
@@ -7233,7 +7395,7 @@ up.Layer.Drawer = (_a = class Drawer extends up.Layer.OverlayWithViewport {
7233
7395
 
7234
7396
 
7235
7397
  /***/ }),
7236
- /* 43 */
7398
+ /* 44 */
7237
7399
  /***/ (() => {
7238
7400
 
7239
7401
  var _a;
@@ -7244,7 +7406,7 @@ up.Layer.Cover = (_a = class Cover extends up.Layer.OverlayWithViewport {
7244
7406
 
7245
7407
 
7246
7408
  /***/ }),
7247
- /* 44 */
7409
+ /* 45 */
7248
7410
  /***/ (() => {
7249
7411
 
7250
7412
  const u = up.util;
@@ -7343,7 +7505,7 @@ up.LayerLookup = class LayerLookup {
7343
7505
 
7344
7506
 
7345
7507
  /***/ }),
7346
- /* 45 */
7508
+ /* 46 */
7347
7509
  /***/ (() => {
7348
7510
 
7349
7511
  const u = up.util;
@@ -7476,7 +7638,7 @@ up.LayerStack = class LayerStack extends Array {
7476
7638
 
7477
7639
 
7478
7640
  /***/ }),
7479
- /* 46 */
7641
+ /* 47 */
7480
7642
  /***/ (() => {
7481
7643
 
7482
7644
  up.LinkFeedbackURLs = class LinkFeedbackURLs {
@@ -7510,7 +7672,7 @@ up.LinkFeedbackURLs = class LinkFeedbackURLs {
7510
7672
 
7511
7673
 
7512
7674
  /***/ }),
7513
- /* 47 */
7675
+ /* 48 */
7514
7676
  /***/ (() => {
7515
7677
 
7516
7678
  const u = up.util;
@@ -7585,7 +7747,7 @@ up.LinkPreloader = class LinkPreloader {
7585
7747
 
7586
7748
 
7587
7749
  /***/ }),
7588
- /* 48 */
7750
+ /* 49 */
7589
7751
  /***/ (() => {
7590
7752
 
7591
7753
  const u = up.util;
@@ -7758,7 +7920,7 @@ up.MotionController = class MotionController {
7758
7920
 
7759
7921
 
7760
7922
  /***/ }),
7761
- /* 49 */
7923
+ /* 50 */
7762
7924
  /***/ (() => {
7763
7925
 
7764
7926
  const u = up.util;
@@ -7871,7 +8033,7 @@ up.NonceableCallback = class NonceableCallback {
7871
8033
 
7872
8034
 
7873
8035
  /***/ }),
7874
- /* 50 */
8036
+ /* 51 */
7875
8037
  /***/ (() => {
7876
8038
 
7877
8039
  const u = up.util;
@@ -7938,7 +8100,7 @@ up.OptionsParser = class OptionsParser {
7938
8100
 
7939
8101
 
7940
8102
  /***/ }),
7941
- /* 51 */
8103
+ /* 52 */
7942
8104
  /***/ (() => {
7943
8105
 
7944
8106
  const e = up.element;
@@ -8029,7 +8191,7 @@ up.OverlayFocus = class OverlayFocus {
8029
8191
 
8030
8192
 
8031
8193
  /***/ }),
8032
- /* 52 */
8194
+ /* 53 */
8033
8195
  /***/ (() => {
8034
8196
 
8035
8197
  const u = up.util;
@@ -8616,7 +8778,7 @@ up.Params = class Params {
8616
8778
 
8617
8779
 
8618
8780
  /***/ }),
8619
- /* 53 */
8781
+ /* 54 */
8620
8782
  /***/ (() => {
8621
8783
 
8622
8784
  const e = up.element;
@@ -8673,7 +8835,7 @@ up.ProgressBar = class ProgressBar {
8673
8835
 
8674
8836
 
8675
8837
  /***/ }),
8676
- /* 54 */
8838
+ /* 55 */
8677
8839
  /***/ (() => {
8678
8840
 
8679
8841
  const u = up.util;
@@ -8811,7 +8973,7 @@ up.RenderOptions = (function () {
8811
8973
 
8812
8974
 
8813
8975
  /***/ }),
8814
- /* 55 */
8976
+ /* 56 */
8815
8977
  /***/ (() => {
8816
8978
 
8817
8979
  /*-
@@ -8852,7 +9014,7 @@ up.RenderResult = class RenderResult extends up.Record {
8852
9014
 
8853
9015
 
8854
9016
  /***/ }),
8855
- /* 56 */
9017
+ /* 57 */
8856
9018
  /***/ (() => {
8857
9019
 
8858
9020
  const u = up.util;
@@ -9114,8 +9276,18 @@ up.Request = class Request extends up.Record {
9114
9276
  // Normalize a first time to get a normalized cache key.
9115
9277
  this.normalizeForCaching();
9116
9278
  if (!options.basic) {
9117
- this.layer = up.layer.get(this.layer); // If @layer and @origin is undefined, this will choose the current layer.
9118
- this.failLayer = up.layer.get(this.failLayer || this.layer);
9279
+ const layerLookupOptions = { origin: this.origin };
9280
+ // Calling up.layer.get() will give us:
9281
+ //
9282
+ // (1) Resolution of strings like 'current' to an up.Layer instance
9283
+ // (2) Default of origin's layer
9284
+ // (3) Default of up.layer.current
9285
+ //
9286
+ // up.layer.get('new') will return 'new' unchanged, but I'm not sure
9287
+ // if any code actually calls up.request({ ..., layer: 'new' }).
9288
+ // In up.Change.OpenLayer we connect requests to the base layer we're stacking upon.
9289
+ this.layer = up.layer.get(this.layer, layerLookupOptions);
9290
+ this.failLayer = up.layer.get(this.failLayer || this.layer, layerLookupOptions);
9119
9291
  this.context || (this.context = this.layer.context || {}); // @layer might be "new", so we default to {}
9120
9292
  this.failContext || (this.failContext = this.failLayer.context || {}); // @failLayer might be "new", so we default to {}
9121
9293
  this.mode || (this.mode = this.layer.mode);
@@ -9437,7 +9609,7 @@ up.Request.tester = function (condition) {
9437
9609
 
9438
9610
 
9439
9611
  /***/ }),
9440
- /* 57 */
9612
+ /* 58 */
9441
9613
  /***/ (() => {
9442
9614
 
9443
9615
  let u = up.util;
@@ -9482,7 +9654,7 @@ up.Request.Cache = class Cache extends up.Cache {
9482
9654
 
9483
9655
 
9484
9656
  /***/ }),
9485
- /* 58 */
9657
+ /* 59 */
9486
9658
  /***/ (() => {
9487
9659
 
9488
9660
  const u = up.util;
@@ -9620,7 +9792,7 @@ up.Request.Queue = class Queue {
9620
9792
 
9621
9793
 
9622
9794
  /***/ }),
9623
- /* 59 */
9795
+ /* 60 */
9624
9796
  /***/ (() => {
9625
9797
 
9626
9798
  const u = up.util;
@@ -9672,7 +9844,7 @@ up.Request.FormRenderer = class FormRenderer {
9672
9844
 
9673
9845
 
9674
9846
  /***/ }),
9675
- /* 60 */
9847
+ /* 61 */
9676
9848
  /***/ (() => {
9677
9849
 
9678
9850
  const CONTENT_TYPE_URL_ENCODED = 'application/x-www-form-urlencoded';
@@ -9779,7 +9951,7 @@ up.Request.XHRRenderer = class XHRRenderer {
9779
9951
 
9780
9952
 
9781
9953
  /***/ }),
9782
- /* 61 */
9954
+ /* 62 */
9783
9955
  /***/ (() => {
9784
9956
 
9785
9957
  /*-
@@ -9960,7 +10132,7 @@ up.Response = class Response extends up.Record {
9960
10132
 
9961
10133
 
9962
10134
  /***/ }),
9963
- /* 62 */
10135
+ /* 63 */
9964
10136
  /***/ (() => {
9965
10137
 
9966
10138
  const u = up.util;
@@ -10066,7 +10238,7 @@ up.ResponseDoc = class ResponseDoc {
10066
10238
 
10067
10239
 
10068
10240
  /***/ }),
10069
- /* 63 */
10241
+ /* 64 */
10070
10242
  /***/ (() => {
10071
10243
 
10072
10244
  const e = up.element;
@@ -10182,7 +10354,7 @@ up.RevealMotion = class RevealMotion {
10182
10354
 
10183
10355
 
10184
10356
  /***/ }),
10185
- /* 64 */
10357
+ /* 65 */
10186
10358
  /***/ (() => {
10187
10359
 
10188
10360
  const u = up.util;
@@ -10226,11 +10398,6 @@ up.ScrollMotion = class ScrollMotion {
10226
10398
  if (this.settled) {
10227
10399
  return;
10228
10400
  }
10229
- // When the scroll position is not the one we previously set, we assume
10230
- // that the user has tried scrolling on her own. We then cancel the scrolling animation.
10231
- if (this.frameTop && (Math.abs(this.frameTop - this.scrollable.scrollTop) > 1.5)) {
10232
- this.abort('Animation aborted due to user intervention');
10233
- }
10234
10401
  const currentTime = Date.now();
10235
10402
  const timeElapsed = currentTime - this.startTime;
10236
10403
  const timeFraction = Math.min(timeElapsed / this.duration, 1);
@@ -10261,7 +10428,7 @@ up.ScrollMotion = class ScrollMotion {
10261
10428
 
10262
10429
 
10263
10430
  /***/ }),
10264
- /* 65 */
10431
+ /* 66 */
10265
10432
  /***/ (() => {
10266
10433
 
10267
10434
  const e = up.element;
@@ -10312,7 +10479,7 @@ up.Selector = class Selector {
10312
10479
 
10313
10480
 
10314
10481
  /***/ }),
10315
- /* 66 */
10482
+ /* 67 */
10316
10483
  /***/ (() => {
10317
10484
 
10318
10485
  const u = up.util;
@@ -10346,7 +10513,7 @@ up.store.Memory = class Memory {
10346
10513
 
10347
10514
 
10348
10515
  /***/ }),
10349
- /* 67 */
10516
+ /* 68 */
10350
10517
  /***/ (() => {
10351
10518
 
10352
10519
  //#
@@ -10416,7 +10583,7 @@ up.store.Session = class Session extends up.store.Memory {
10416
10583
 
10417
10584
 
10418
10585
  /***/ }),
10419
- /* 68 */
10586
+ /* 69 */
10420
10587
  /***/ (() => {
10421
10588
 
10422
10589
  const u = up.util;
@@ -10576,7 +10743,7 @@ up.Tether = class Tether {
10576
10743
 
10577
10744
 
10578
10745
  /***/ }),
10579
- /* 69 */
10746
+ /* 70 */
10580
10747
  /***/ (() => {
10581
10748
 
10582
10749
  const u = up.util;
@@ -10663,7 +10830,7 @@ up.URLPattern = class URLPattern {
10663
10830
 
10664
10831
 
10665
10832
  /***/ }),
10666
- /* 70 */
10833
+ /* 71 */
10667
10834
  /***/ (() => {
10668
10835
 
10669
10836
  /*-
@@ -10874,7 +11041,7 @@ up.boot = up.framework.boot;
10874
11041
 
10875
11042
 
10876
11043
  /***/ }),
10877
- /* 71 */
11044
+ /* 72 */
10878
11045
  /***/ (() => {
10879
11046
 
10880
11047
  /*-
@@ -11440,7 +11607,7 @@ up.emit = up.event.emit;
11440
11607
 
11441
11608
 
11442
11609
  /***/ }),
11443
- /* 72 */
11610
+ /* 73 */
11444
11611
  /***/ (() => {
11445
11612
 
11446
11613
  /*-
@@ -12237,7 +12404,7 @@ up.protocol = (function () {
12237
12404
 
12238
12405
 
12239
12406
  /***/ }),
12240
- /* 73 */
12407
+ /* 74 */
12241
12408
  /***/ (() => {
12242
12409
 
12243
12410
  /*-
@@ -12387,33 +12554,6 @@ up.log = (function () {
12387
12554
  setEnabled(false);
12388
12555
  }
12389
12556
  /*-
12390
- Throws a [JavaScript error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)
12391
- with the given message.
12392
-
12393
- The message will also be printed to the error log. Also a notification will be shown at the bottom of the screen.
12394
-
12395
- The message may contain [substitution marks](https://developer.mozilla.org/en-US/docs/Web/API/console#Using_string_substitutions).
12396
-
12397
- ### Examples
12398
-
12399
- up.fail('Division by zero')
12400
- up.fail('Unexpected result %o', result)
12401
-
12402
- @function up.fail
12403
- @param {string} message
12404
- A message with details about the error.
12405
-
12406
- The message can contain [substitution marks](https://developer.mozilla.org/en-US/docs/Web/API/console#Using_string_substitutions)
12407
- like `%s` or `%o`.
12408
- @param {Array<string>} vars...
12409
- A list of variables to replace any substitution marks in the error message.
12410
- @experimental
12411
- */
12412
- function fail(...args) {
12413
- printToError('error', ...args);
12414
- throw up.error.failed(args);
12415
- }
12416
- /*-
12417
12557
  Registers an empty rejection handler in case the given promise
12418
12558
  rejects with an AbortError or a failed up.Response.
12419
12559
 
@@ -12449,18 +12589,16 @@ up.log = (function () {
12449
12589
  config,
12450
12590
  enable,
12451
12591
  disable,
12452
- fail,
12453
12592
  muteUncriticalRejection,
12454
12593
  isEnabled() { return config.enabled; },
12455
12594
  };
12456
12595
  })();
12457
12596
  up.puts = up.log.puts;
12458
12597
  up.warn = up.log.warn;
12459
- up.fail = up.log.fail;
12460
12598
 
12461
12599
 
12462
12600
  /***/ }),
12463
- /* 74 */
12601
+ /* 75 */
12464
12602
  /***/ (() => {
12465
12603
 
12466
12604
  /*-
@@ -12770,7 +12908,6 @@ up.syntax = (function () {
12770
12908
  isDefault: up.framework.evaling,
12771
12909
  priority: 0,
12772
12910
  batch: false,
12773
- keep: false,
12774
12911
  jQuery: false
12775
12912
  });
12776
12913
  return u.assign(callback, options);
@@ -12965,7 +13102,7 @@ up.data = up.syntax.data;
12965
13102
 
12966
13103
 
12967
13104
  /***/ }),
12968
- /* 75 */
13105
+ /* 76 */
12969
13106
  /***/ (() => {
12970
13107
 
12971
13108
  /*-
@@ -13231,9 +13368,6 @@ up.history = (function () {
13231
13368
  return historyLayer.emit(...args);
13232
13369
  }
13233
13370
  function register() {
13234
- // Supported by all browser except IE:
13235
- // https://developer.mozilla.org/en-US/docs/Web/API/History/scrollRestoration
13236
- window.history.scrollRestoration = 'manual';
13237
13371
  window.addEventListener('popstate', onPop);
13238
13372
  // Unpoly replaces the initial page state so it can later restore it when the user
13239
13373
  // goes back to that initial URL. However, if the initial request was a POST,
@@ -13308,10 +13442,10 @@ up.history = (function () {
13308
13442
 
13309
13443
 
13310
13444
  /***/ }),
13311
- /* 76 */
13445
+ /* 77 */
13312
13446
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
13313
13447
 
13314
- __webpack_require__(77);
13448
+ __webpack_require__(78);
13315
13449
  const u = up.util;
13316
13450
  const e = up.element;
13317
13451
  /*-
@@ -14159,7 +14293,7 @@ up.fragment = (function () {
14159
14293
  const keepPlans = options.keepPlans || [];
14160
14294
  const skip = keepPlans.map(function (plan) {
14161
14295
  emitFragmentKept(plan);
14162
- return plan.oldElement;
14296
+ return plan.oldElement; // the kept element
14163
14297
  });
14164
14298
  up.syntax.compile(element, { skip, layer: options.layer });
14165
14299
  emitFragmentInserted(element, options);
@@ -15112,16 +15246,16 @@ u.delegate(up, 'context', () => up.layer.current);
15112
15246
 
15113
15247
 
15114
15248
  /***/ }),
15115
- /* 77 */
15249
+ /* 78 */
15116
15250
  /***/ (() => {
15117
15251
 
15118
15252
  // extracted by mini-css-extract-plugin
15119
15253
 
15120
15254
  /***/ }),
15121
- /* 78 */
15255
+ /* 79 */
15122
15256
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
15123
15257
 
15124
- __webpack_require__(79);
15258
+ __webpack_require__(80);
15125
15259
  /*-
15126
15260
  Scrolling viewports
15127
15261
  ===================
@@ -15235,8 +15369,8 @@ up.viewport = (function () {
15235
15369
  The container element to scroll.
15236
15370
  @param {number} scrollPos
15237
15371
  The absolute number of pixels to set the scroll position to.
15238
- @param {string}[options.behavior='auto']
15239
- When set to `'auto'`, this will immediately scroll to the new position.
15372
+ @param {string}[options.behavior='instant']
15373
+ When set to `'instant'`, this will immediately scroll to the new position.
15240
15374
 
15241
15375
  When set to `'smooth'`, this will scroll smoothly to the new position.
15242
15376
  @param {number}[options.speed]
@@ -15308,8 +15442,8 @@ up.viewport = (function () {
15308
15442
 
15309
15443
  Defaults to `up.viewport.config.revealTop`.
15310
15444
 
15311
- @param {string}[options.behavior='auto']
15312
- When set to `'auto'`, this will immediately scroll to the new position.
15445
+ @param {string}[options.behavior='instant']
15446
+ When set to `'instant'`, this will immediately scroll to the new position.
15313
15447
 
15314
15448
  When set to `'smooth'`, this will scroll smoothly to the new position.
15315
15449
 
@@ -15414,7 +15548,7 @@ up.viewport = (function () {
15414
15548
  /*-
15415
15549
  [Reveals](/up.reveal) an element matching the given `#hash` anchor.
15416
15550
 
15417
- Other than the default behavior found in browsers, `up.revealHash` works with
15551
+ Other than the default behavior found in browsers, `up.revealHash()` works with
15418
15552
  [multiple viewports](/up-viewport) and honors [fixed elements](/up-fixed-top) obstructing the user's
15419
15553
  view of the viewport.
15420
15554
 
@@ -15976,13 +16110,13 @@ up.reveal = up.viewport.reveal;
15976
16110
 
15977
16111
 
15978
16112
  /***/ }),
15979
- /* 79 */
16113
+ /* 80 */
15980
16114
  /***/ (() => {
15981
16115
 
15982
16116
  // extracted by mini-css-extract-plugin
15983
16117
 
15984
16118
  /***/ }),
15985
- /* 80 */
16119
+ /* 81 */
15986
16120
  /***/ (() => {
15987
16121
 
15988
16122
  /*-
@@ -16672,10 +16806,10 @@ up.animate = up.motion.animate;
16672
16806
 
16673
16807
 
16674
16808
  /***/ }),
16675
- /* 81 */
16809
+ /* 82 */
16676
16810
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
16677
16811
 
16678
- __webpack_require__(82);
16812
+ __webpack_require__(83);
16679
16813
  const u = up.util;
16680
16814
  /*-
16681
16815
  Network requests
@@ -17558,16 +17692,16 @@ up.cache = up.network.cache;
17558
17692
 
17559
17693
 
17560
17694
  /***/ }),
17561
- /* 82 */
17695
+ /* 83 */
17562
17696
  /***/ (() => {
17563
17697
 
17564
17698
  // extracted by mini-css-extract-plugin
17565
17699
 
17566
17700
  /***/ }),
17567
- /* 83 */
17701
+ /* 84 */
17568
17702
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
17569
17703
 
17570
- __webpack_require__(84);
17704
+ __webpack_require__(85);
17571
17705
  const u = up.util;
17572
17706
  const e = up.element;
17573
17707
  /*-
@@ -17709,6 +17843,11 @@ up.layer = (function () {
17709
17843
  If set to `true`, the overlay will always render history.
17710
17844
  If set to `false`, the overlay will never render history.
17711
17845
 
17846
+ @param {string} [config.overlay.class]
17847
+ An HTML class for the overlay's container element.
17848
+
17849
+ See [overlay classes](/customizing-overlays#overlay-classes).
17850
+
17712
17851
  @param {object} config.modal
17713
17852
  Defaults for [modal overlays](/layer-terminology).
17714
17853
 
@@ -18570,6 +18709,8 @@ up.layer = (function () {
18570
18709
  @event up:layer:accept
18571
18710
  @param {up.Layer} event.layer
18572
18711
  The layer that is about to close.
18712
+ @param {Element} [event.value]
18713
+ The overlay's [acceptance value](/closing-overlays#overlay-result-values).
18573
18714
  @param {Element} [event.origin]
18574
18715
  The element that is causing the layer to close.
18575
18716
  @param event.preventDefault()
@@ -18586,6 +18727,8 @@ up.layer = (function () {
18586
18727
  @event up:layer:accepted
18587
18728
  @param {up.Layer} event.layer
18588
18729
  The layer that was closed.
18730
+ @param {Element} [event.value]
18731
+ The overlay's [acceptance value](/closing-overlays#overlay-result-values).
18589
18732
  @param {Element} [event.origin]
18590
18733
  The element that has caused the layer to close.
18591
18734
  @stable
@@ -18609,6 +18752,8 @@ up.layer = (function () {
18609
18752
  @event up:layer:dismiss
18610
18753
  @param {up.Layer} event.layer
18611
18754
  The layer that is about to close.
18755
+ @param {Element} [event.value]
18756
+ The overlay's [dismissal value](/closing-overlays#overlay-result-values).
18612
18757
  @param {Element} [event.origin]
18613
18758
  The element that is causing the layer to close.
18614
18759
  @param event.preventDefault()
@@ -18625,6 +18770,8 @@ up.layer = (function () {
18625
18770
  @event up:layer:dismissed
18626
18771
  @param {up.Layer} event.layer
18627
18772
  The layer that was closed.
18773
+ @param {Element} [event.value]
18774
+ The overlay's [dismissal value](/closing-overlays#overlay-result-values).
18628
18775
  @param {Element} [event.origin]
18629
18776
  The element that has caused the layer to close.
18630
18777
  @stable
@@ -18830,16 +18977,16 @@ up.layer = (function () {
18830
18977
 
18831
18978
 
18832
18979
  /***/ }),
18833
- /* 84 */
18980
+ /* 85 */
18834
18981
  /***/ (() => {
18835
18982
 
18836
18983
  // extracted by mini-css-extract-plugin
18837
18984
 
18838
18985
  /***/ }),
18839
- /* 85 */
18986
+ /* 86 */
18840
18987
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
18841
18988
 
18842
- __webpack_require__(86);
18989
+ __webpack_require__(87);
18843
18990
  /*-
18844
18991
  Linking to fragments
18845
18992
  ====================
@@ -19815,12 +19962,6 @@ up.link = (function () {
19815
19962
  A JSON object that will be merged into the [context](/context)
19816
19963
  of the current layer once the fragment is rendered.
19817
19964
 
19818
- @param [up-keep='true']
19819
- Whether [`[up-keep]`](/up-keep) elements will be preserved in the updated fragment.
19820
-
19821
- @param [up-hungry='true']
19822
- Whether [`[up-hungry]`](/up-hungry) elements outside the updated fragment will also be updated.
19823
-
19824
19965
  @param [up-scroll='auto']
19825
19966
  How to scroll after the new fragment was rendered.
19826
19967
 
@@ -19995,13 +20136,13 @@ up.follow = up.link.follow;
19995
20136
 
19996
20137
 
19997
20138
  /***/ }),
19998
- /* 86 */
20139
+ /* 87 */
19999
20140
  /***/ (() => {
20000
20141
 
20001
20142
  // extracted by mini-css-extract-plugin
20002
20143
 
20003
20144
  /***/ }),
20004
- /* 87 */
20145
+ /* 88 */
20005
20146
  /***/ (() => {
20006
20147
 
20007
20148
  /*-
@@ -20040,7 +20181,7 @@ up.form = (function () {
20040
20181
  up.form.config.submitSelectors.push('form')
20041
20182
  ```
20042
20183
 
20043
- Individual forms may opt out with an `[up-submit=follow]` attribute.
20184
+ Individual forms may opt out with an `[up-submit=false]` attribute.
20044
20185
  You may configure additional exceptions in `config.noSubmitSelectors`.
20045
20186
 
20046
20187
  @param {Array<string>} [config.noSubmitSelectors]
@@ -21295,7 +21436,7 @@ up.validate = up.form.validate;
21295
21436
 
21296
21437
 
21297
21438
  /***/ }),
21298
- /* 88 */
21439
+ /* 89 */
21299
21440
  /***/ (() => {
21300
21441
 
21301
21442
  /*-
@@ -21729,7 +21870,7 @@ up.feedback = (function () {
21729
21870
 
21730
21871
 
21731
21872
  /***/ }),
21732
- /* 89 */
21873
+ /* 90 */
21733
21874
  /***/ (() => {
21734
21875
 
21735
21876
  /*-
@@ -21745,7 +21886,6 @@ This package contains functionality to passively receive updates from the server
21745
21886
  */
21746
21887
  up.radio = (function () {
21747
21888
  const u = up.util;
21748
- const e = up.element;
21749
21889
  /*-
21750
21890
  Configures defaults for passive updates.
21751
21891
 
@@ -21763,7 +21903,7 @@ up.radio = (function () {
21763
21903
  @param {boolean|string|Function(Element)} [config.pollEnabled=true]
21764
21904
  Whether Unpoly will follow instructions to poll fragments, like the `[up-poll]` attribute.
21765
21905
 
21766
- When set to `'auto'` Unpoly will poll if one of the following applies:
21906
+ When set to `'auto'` Unpoly will skip polling updates while one of the following applies:
21767
21907
 
21768
21908
  - The browser tab is in the foreground
21769
21909
  - The fragment's layer is the [frontmost layer](/up.layer.front).
@@ -21775,6 +21915,9 @@ up.radio = (function () {
21775
21915
 
21776
21916
  You may also pass a function that accepts the polling fragment and returns `true`, `false` or `'auto'`.
21777
21917
 
21918
+ When an update is skipped due to polling being disabled,
21919
+ Unpoly will try to poll again after the configured interval.
21920
+
21778
21921
  @stable
21779
21922
  */
21780
21923
  const config = new up.Config(() => ({
@@ -21808,62 +21951,32 @@ up.radio = (function () {
21808
21951
  /*-
21809
21952
  Starts [polling](/up-poll) the given element.
21810
21953
 
21954
+ The given element does not need an `[up-poll]` attribute.
21955
+
21811
21956
  @function up.radio.startPolling
21812
- @param {Element|jQuery|string} fragment
21957
+ @param {Element} fragment
21813
21958
  The fragment to reload periodically.
21814
21959
  @param {number} options.interval
21815
21960
  The reload interval in milliseconds.
21816
21961
 
21817
21962
  Defaults to `up.radio.config.pollInterval`.
21963
+ @param {string} options.url
21964
+ Defaults to the element's closest `[up-source]` attribute.
21818
21965
  @stable
21819
21966
  */
21820
21967
  function startPolling(fragment, options = {}) {
21821
- const interval = (options.interval ?? e.numberAttr(fragment, 'up-interval')) ?? config.pollInterval;
21822
- let stopped = false;
21823
- let lastRequest = null;
21824
- options.onQueued = request => lastRequest = request;
21825
- function doReload() {
21826
- // The setTimeout(doReload) callback might already be scheduled
21827
- // before the polling stopped.
21828
- if (stopped) {
21829
- return;
21830
- }
21831
- if (shouldPoll(fragment)) {
21832
- u.always(up.reload(fragment, options), doSchedule);
21833
- }
21834
- else {
21835
- up.puts('[up-poll]', 'Polling is disabled');
21836
- // Reconsider after 10 seconds at most
21837
- doSchedule(Math.min(10 * 1000, interval));
21838
- }
21839
- }
21840
- function doSchedule(delay = interval) {
21841
- // The up.reload().then(doSchedule) callback might already be
21842
- // registered before the polling stopped.
21843
- if (stopped) {
21844
- return;
21845
- }
21846
- setTimeout(doReload, delay);
21847
- }
21848
- function destructor() {
21849
- stopped = true; // Don't execute already-scheduled callbacks
21850
- lastRequest?.abort(); // Abort any pending request
21851
- }
21852
- // up.radio.stopPolling() will emit up:poll:stop to signal cancelation.
21853
- up.on(fragment, 'up:poll:stop', destructor);
21854
- doSchedule();
21855
- return destructor;
21968
+ up.FragmentPolling.forFragment(fragment).forceStart(options);
21856
21969
  }
21857
21970
  /*-
21858
21971
  Stops [polling](/up-poll) the given element.
21859
21972
 
21860
21973
  @function up.radio.stopPolling
21861
- @param {Element|jQuery|string} fragment
21974
+ @param {Element} fragment
21862
21975
  The fragment to stop reloading.
21863
21976
  @stable
21864
21977
  */
21865
21978
  function stopPolling(element) {
21866
- up.emit(element, 'up:poll:stop');
21979
+ up.FragmentPolling.forFragment(element).forceStop();
21867
21980
  }
21868
21981
  function shouldPoll(fragment) {
21869
21982
  const setting = u.evalOption(config.pollEnabled, fragment);
@@ -21914,7 +22027,17 @@ up.radio = (function () {
21914
22027
  </div>
21915
22028
  ```
21916
22029
 
21917
- ### Skipping updates when nothing changed
22030
+ ### Skipping updates on the client
22031
+
22032
+ Client-side code may skip an update by preventing an `up:fragment:poll` event
22033
+ on the polling fragment.
22034
+
22035
+ Unpoly will also choose to skip updates under certain conditions,
22036
+ e.g. when the browser tab is in the background. See `up.radio.config.pollEnabled` for details.
22037
+
22038
+ When an update is skipped, Unpoly will try to poll again after the configured interval.
22039
+
22040
+ ### Skipping updates on the server
21918
22041
 
21919
22042
  When polling a fragment periodically we want to avoid rendering unchanged content.
21920
22043
  This saves <b>CPU time</b> and reduces the <b>bandwidth cost</b> for a
@@ -21923,26 +22046,57 @@ up.radio = (function () {
21923
22046
  To achieve this we timestamp your fragments with an `[up-time]` attribute to indicate
21924
22047
  when the underlying data was last changed. See `[up-time]` for a detailed example.
21925
22048
 
22049
+ If the server has no more recent changes, it may skip the update by responding
22050
+ with an HTTP status `304 Not Modified`.
22051
+
22052
+ When an update is skipped, Unpoly will try to poll again after the configured interval.
22053
+
22054
+ ### Stopping polling
22055
+
22056
+ - The fragment from the server response no longer has an `[up-poll]` attribute.
22057
+ - Client-side code has called `up.radio.stopPolling()` with the polling element.
22058
+ - Polling was [disabled globally](/up.radio.config#config.pollEnabled).
22059
+
21926
22060
  @selector [up-poll]
21927
22061
  @param [up-interval]
21928
22062
  The reload interval in milliseconds.
21929
22063
 
21930
22064
  Defaults to `up.radio.config.pollInterval`.
22065
+ @param [up-source]
22066
+ The URL from which to reload the fragment.
22067
+
22068
+ Defaults to the closest `[up-source]` attribute of an ancestor element.
21931
22069
  @stable
21932
22070
  */
21933
- up.compiler('[up-poll]', startPolling);
22071
+ up.compiler('[up-poll]', (fragment) => {
22072
+ up.FragmentPolling.forFragment(fragment).onPollAttributeObserved();
22073
+ });
22074
+ /*-
22075
+ This event is emitted before a [polling](/up-poll) fragment is reloaded from the server.
22076
+
22077
+ Listener may prevent the `up:fragment:poll` event to prevent the fragment from being reloaded.
22078
+ Preventing the event will only skip a single update. It will *not* stop future polling.
22079
+
22080
+ @event up:fragment:poll
22081
+ @param {Element} event.target
22082
+ The polling fragment.
22083
+ @param event.preventDefault()
22084
+ Event listeners may call this method to prevent the fragment from being reloaded.
22085
+ @experimental
22086
+ */
21934
22087
  up.on('up:framework:reset', reset);
21935
22088
  return {
21936
22089
  config,
21937
22090
  hungrySelector,
21938
22091
  startPolling,
21939
- stopPolling
22092
+ stopPolling,
22093
+ shouldPoll,
21940
22094
  };
21941
22095
  })();
21942
22096
 
21943
22097
 
21944
22098
  /***/ }),
21945
- /* 90 */
22099
+ /* 91 */
21946
22100
  /***/ (() => {
21947
22101
 
21948
22102
  /*
@@ -22082,15 +22236,16 @@ __webpack_require__(73);
22082
22236
  __webpack_require__(74);
22083
22237
  __webpack_require__(75);
22084
22238
  __webpack_require__(76);
22085
- __webpack_require__(78);
22086
- __webpack_require__(80);
22239
+ __webpack_require__(77);
22240
+ __webpack_require__(79);
22087
22241
  __webpack_require__(81);
22088
- __webpack_require__(83);
22089
- __webpack_require__(85);
22090
- __webpack_require__(87);
22242
+ __webpack_require__(82);
22243
+ __webpack_require__(84);
22244
+ __webpack_require__(86);
22091
22245
  __webpack_require__(88);
22092
22246
  __webpack_require__(89);
22093
22247
  __webpack_require__(90);
22248
+ __webpack_require__(91);
22094
22249
  up.framework.onEvaled();
22095
22250
 
22096
22251
  })();