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

@@ -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
  })();