unpoly-rails 2.0.0.pre.rc6 → 2.0.0.pre.rc11

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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6ae929555ac3d1c4f901618fed559ec3c2d53f5117de889d72c81518e158f946
4
- data.tar.gz: 4a7bbc9f22a3fab1127b6c4bf3e0f930f1a300725549367025bc50c45c6ebdca
3
+ metadata.gz: 16c5d23ef0ef94cd9a7cb5ef926ff4931aa1e2b19b32548c35b0fd527de83d91
4
+ data.tar.gz: 4748c57d0da382a24dd48f594ca3f61838387dc3fd3630da416843d8c45dc079
5
5
  SHA512:
6
- metadata.gz: 3ce5945794168936c808619d4ebd3a7490355dfadd7337324d40b68f2d211fc13149c46439abf693776e27c452a02f4acee78247b4196fc60bf27f94a1856b6f
7
- data.tar.gz: d9c4f06cbc704414871a006c17b6ec1b7cb4d2f76c70c091f6585dc89265fa7f7e650e376e3ba632e4f75bb04049999fe0bc6644875b950616fb6ced4246b7dd
6
+ metadata.gz: 4b5ff85fee318e8200aef941b878d8bdac28872ff0a46e2e2468c3c28e883065daa30f96858418f900f6566632b0d469632ec8736cca550db2aa71c97fecacf0
7
+ data.tar.gz: 8f51f5822089f69e36da2a3c8cf7942bec84965014f0de1ebb524aaf13288697301e8fa68c747ee4b8d89a5e623eed5768bd904a87e0989ad0490527bdca2774
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- [Unpoly](https://unpoly.com)
1
+ [Unpoly 2](https://unpoly.com)
2
2
  ======
3
3
 
4
4
  Unobtrusive JavaScript framework for server-side applications
@@ -6,7 +6,9 @@ Unobtrusive JavaScript framework for server-side applications
6
6
 
7
7
  [Unpoly](https://unpoly.com) enables fast and flexible frontends with minimal changes to your server-side code.
8
8
 
9
- This repository is home to both the Unpoly JavaScript code and its (optional) bindings for Ruby on Rails (`unpoly-rails` gem).
9
+ This repository is home to both the Unpoly 2 JavaScript code and its (optional) bindings for Ruby on Rails (`unpoly-rails` gem).
10
+
11
+ If you're looking for the code of Unpoly 0.x or 1.0, use the [`1.x-stable`](https://github.com/unpoly/unpoly/tree/1.x-stable) branch.
10
12
 
11
13
 
12
14
  Getting started
@@ -33,6 +35,7 @@ Install dependencies for tests:
33
35
 
34
36
  - Install Ruby 2.3.8
35
37
  - Install Bundler by running `gem install bundler`
38
+ - Install Node.js (required for building the library)
36
39
  - `cd` into `spec_app`
37
40
  - Install dependencies by running `bundle install`
38
41
 
@@ -50,11 +53,9 @@ To run RSpec tests for the `unpoly-rails` gem:
50
53
 
51
54
  ### Making a new release
52
55
 
53
- We are currently feeding four release channels:
56
+ We are currently feeding two release channels:
54
57
 
55
- - Manual download from GitHub
56
58
  - npm
57
- - Bower (which is based on Git and version tags)
58
59
  - Rubygems (as the `unpoly-rails` gem)
59
60
 
60
61
  We always release to all channel simultaneously.
@@ -856,6 +856,11 @@ Returns the first descendant element matching the given selector.
856
856
  });
857
857
 
858
858
  }).call(this);
859
+
860
+ /***
861
+ @module up.layer
862
+ */
863
+
859
864
  (function() {
860
865
  var e, u;
861
866
 
@@ -1178,6 +1183,26 @@ This feature is now deprecated.
1178
1183
  (function() {
1179
1184
  up.migrate.renamedProperty(up.radio.config, 'hungry', 'hungrySelectors');
1180
1185
 
1186
+ }).call(this);
1187
+ (function() {
1188
+ var u;
1189
+
1190
+ u = up.util;
1191
+
1192
+ up.migrate.postCompile = function(elements, compiler) {
1193
+ var element, i, keepValue, len, results, value;
1194
+ if (keepValue = compiler.keep) {
1195
+ up.migrate.warn('The { keep: true } option for up.compiler() has been removed. Have the compiler set [up-keep] attribute instead.');
1196
+ value = u.isString(keepValue) ? keepValue : '';
1197
+ results = [];
1198
+ for (i = 0, len = elements.length; i < len; i++) {
1199
+ element = elements[i];
1200
+ results.push(element.setAttribute('up-keep', value));
1201
+ }
1202
+ return results;
1203
+ }
1204
+ };
1205
+
1181
1206
  }).call(this);
1182
1207
 
1183
1208
  /***
@@ -1 +1 @@
1
- (function(){up.framework.startExtension()}).call(this),function(){var u,p,e,t,r,a,n,i,o,l,c,s,d,m,g=[].slice;u=up.util,up.migrate=(p=new up.Config(function(){return{logLevel:"warn"}}),c=function(e,t,r){var a;return a=function(){return d("Property { %s } has been renamed to { %s } (found in %o)",t,r,e)},Object.defineProperty(e,t,{get:function(){return a(),this[r]},set:function(e){return a(),this[r]=e}})},a=function(e,t,r){if(u.isDefined(e[t]))return d("Property { %s } has been renamed to { %s } (found in %o)",t,r,e),u.renameKey(e,t,r)},o={},i=function(e,t){return o[e]=t},t=function(e){var t;return(t=o[e])?(d("Event "+e+" has been renamed to "+t),t):e},r=function(e){return u.uniq(u.map(e,t))},l=function(e,t){return Object.defineProperty(up,e,{get:function(){return d("up."+e+" has been renamed to up."+t),up[t]}})},m={},d=function(e){var t,r,a,n;if(a=e,t=2<=arguments.length?g.call(arguments,1):[],r=u.sprintf.apply(u,[a].concat(g.call(t))),!m[r])return m[r]=!0,(n=up.log)[p.logLevel].apply(n,["DEPRECATION",a].concat(g.call(t)))},e=function(e,t){return d(e+" has been deprecated. Use "+t+" instead.")},n=function(e){var t,r;return r=Promise.resolve(),t=r.then,r.then=function(){return d(e+" is now a sync function"),t.apply(this,arguments)},r},s=function(){return p.reset()},up.on("up:framework:reset",s),{deprecated:e,renamedPackage:l,renamedProperty:c,formerlyAsync:n,renamedEvent:i,fixEventTypes:r,fixKey:a,warn:d,loaded:!0,config:p})}.call(this),function(){var a=[].slice;up.util.only=function(e){var t,r;return r=e,t=2<=arguments.length?a.call(arguments,1):[],up.migrate.deprecated("up.util.only(object, ...keys)","up.util.pick(object, keys)"),up.util.pick(r,t)},up.util.except=function(e){var t,r;return r=e,t=2<=arguments.length?a.call(arguments,1):[],up.migrate.deprecated("up.util.except(object, ...keys)","up.util.omit(object, keys)"),up.util.omit(r,t)},up.util.parseUrl=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.parseUrl() has been renamed to up.util.parseURL()"),(t=up.util).parseURL.apply(t,e)},up.util.any=function(){var e;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.any() has been renamed to up.util.some()"),some.apply(null,e)},up.util.all=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.all() has been renamed to up.util.every()"),(t=up.util).every.apply(t,e)},up.util.detect=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.detect() has been renamed to up.util.find()"),(t=up.util).find.apply(t,e)},up.util.select=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.select() has been renamed to up.util.filter()"),(t=up.util).filter.apply(t,e)},up.util.setTimer=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.setTimer() has been renamed to up.util.timer()"),(t=up.util).timer.apply(t,e)},up.util.escapeHtml=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.deprecated("up.util.escapeHtml","up.util.escapeHTML"),(t=up.util).escapeHTML.apply(t,e)},up.util.selectorForElement=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.selectorForElement() has been renamed to up.fragment.toTarget()"),(t=up.fragment).toTarget.apply(t,e)},up.util.nextFrame=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.nextFrame() has been renamed to up.util.task()"),(t=up.util).task.apply(t,e)}}.call(this),function(){var r=[].slice;up.element.first=function(){var e,t;return e=1<=arguments.length?r.call(arguments,0):[],up.migrate.deprecated("up.element.first()","up.element.get()"),(t=up.element).get.apply(t,e)},up.element.createFromHtml=function(){var e,t;return e=1<=arguments.length?r.call(arguments,0):[],up.migrate.deprecated("up.element.createFromHtml","up.element.createFromHTML"),(t=up.element).createFromHTML.apply(t,e)}}.call(this),function(){var t=[].slice;up.migrate.renamedPackage("bus","event"),up.event.nobodyPrevents=function(){var e;return e=1<=arguments.length?t.call(arguments,0):[],up.migrate.deprecated("up.event.nobodyPrevents(type)","!up.emit(type).defaultPrevented"),!up.emit.apply(up,e).defaultPrevented}}.call(this),function(){up.migrate.renamedProperty(up.form.config,"fields","fieldSelectors"),up.migrate.renamedProperty(up.form.config,"submitButtons","submitButtonSelectors")}.call(this),function(){var p,r=[].slice;p=up.util,up.migrate.renamedPackage("flow","fragment"),up.migrate.renamedPackage("dom","fragment"),up.migrate.renamedProperty(up.fragment.config,"fallbacks","mainTargets"),up.migrate.handleResponseDocOptions=function(e){return up.migrate.fixKey(e,"html","document")},up.replace=function(e,t,r){return up.migrate.deprecated("up.replace(target, url)","up.navigate(target, { url })"),up.navigate(p.merge(r,{target:e,url:t}))},up.extract=function(e,t,r){return up.migrate.deprecated("up.extract(target, document)","up.navigate(target, { document })"),up.navigate(p.merge(r,{target:e,document:t}))},up.fragment.first=function(){var e,t;return e=1<=arguments.length?r.call(arguments,0):[],up.migrate.deprecated("up.fragment.first()","up.fragment.get()"),(t=up.fragment).get.apply(t,e)},up.first=up.fragment.first,up.migrate.handleScrollOptions=function(e){if(p.isUndefined(e.scroll)&&(p.isString(e.reveal)?(up.migrate.deprecated("Option { reveal: '"+e.reveal+"' }","{ scroll: '"+e.reveal+"' }"),e.scroll=e.reveal):!0===e.reveal?(up.migrate.deprecated("Option { reveal: true }","{ scroll: 'target' }"),e.scroll="target"):!1===e.reveal&&(up.migrate.deprecated("Option { reveal: false }","{ scroll: false }"),e.scroll=!1),p.isDefined(e.resetScroll)&&(up.migrate.deprecated("Option { resetScroll: true }","{ scroll: 'reset' }"),e.scroll="teset"),p.isDefined(e.restoreScroll)))return up.migrate.deprecated("Option { restoreScroll: true }","{ scroll: 'restore' }"),e.scroll="restore"},up.migrate.handleHistoryOption=function(e){if(p.isString(e.history)&&"auto"!==e.history)return up.migrate.warn("Passing a URL as { history } option is deprecated. Pass it as { location } instead."),e.location=e.history,e.history="auto"},up.migrate.handleRenderOptions=function(e){var t,r,a,n,u;for(up.migrate.handleHistoryOption(e),u=[],t=0,r=(n=["target","origin"]).length;t<r;t++)a=n[t],p.isJQuery(e[a])?(up.migrate.warn("Passing a jQuery collection as { %s } is deprecated. Pass it as a native element instead.",a),u.push(e[a]=up.element.get(e[a]))):u.push(void 0);return u}}.call(this),function(){up.migrate.renamedProperty(up.history.config,"popTargets","restoreTargets"),up.history.url=function(){return up.migrate.deprecated("up.history.url()","up.history.location"),up.history.location},up.migrate.renamedEvent("up:history:push","up:location:changed"),up.migrate.renamedEvent("up:history:pushed","up:location:changed"),up.migrate.renamedEvent("up:history:restore","up:location:changed"),up.migrate.renamedEvent("up:history:restored","up:location:changed"),up.migrate.renamedEvent("up:history:replaced","up:location:changed")}.call(this),function(){up.migrate.renamedPackage("navigation","feedback"),up.migrate.renamedProperty(up.feedback.config,"navs","navSelectors")}.call(this),function(){up.migrate.parseFollowOptions=function(e){return e.string("flavor"),e.string("width"),e.string("height"),e["boolean"]("closable"),e.booleanOrString("reveal"),e["boolean"]("resetScroll"),e["boolean"]("restoreScroll")}}.call(this),function(){up.migrate.handleLayerOptions=function(e){var t,r,a,n;for(up.migrate.fixKey(e,"flavor","mode"),up.migrate.fixKey(e,"closable","dismissable"),up.migrate.fixKey(e,"closeLabel","dismissLabel"),r=0,a=(n=["width","maxWidth","height"]).length;r<a;r++)e[t=n[r]]&&up.migrate.warn("Layer option { "+t+" } has been removed. Use { size } or { class } instead.");if(e.sticky&&up.migrate.warn("Layer option { sticky } has been removed. Give links an [up-peel=false] attribute to prevent layer dismissal on click."),e.template&&up.migrate.warn("Layer option { template } has been removed. Use { class } or modify the layer HTML on up:layer:open."),"page"===e.layer&&(up.migrate.warn("Option { layer: 'page' } has been renamed to { layer: 'root' }."),e.layer="root"),"modal"===e.layer||"popup"===e.layer)return up.migrate.warn("Option { layer: '"+e.layer+"' } has been removed. Did you mean { layer: 'overlay' }?"),e.layer="overlay"},up.migrate.handleTetherOptions=function(e){var t,r,a;if(r=(a=e.position.split("-"))[0],t=a[1])return up.migrate.warn("The position value %o is deprecated. Use %o instead.",e.position,{position:r,align:t}),e.position=r,e.align=t},up.migrate.registerLayerCloser=function(r){return r.registerClickCloser("up-close",function(e,t){return up.migrate.deprecated("[up-close]","[up-dismiss]"),r.dismiss(e,t)})},up.migrate.handleLayerConfig=function(e){return up.migrate.fixKey(e,"history","historyVisible")}}.call(this),function(){var e,a;a=up.util,e=new Error("up.modal.flavors has been removed without direct replacement. You may give new layers a { class } or modify layer elements on up:layer:open."),up.modal=a.literal({visit:function(e,t){return null==t&&(t={}),up.migrate.deprecated("up.modal.visit(url)",'up.layer.open({ url, mode: "modal" })'),up.layer.open(a.merge(t,{url:e,mode:"modal"}))},follow:function(e,t){return null==t&&(t={}),up.migrate.deprecated("up.modal.follow(link)",'up.follow(link, { layer: "modal" })'),up.follow(e,a.merge(t,{layer:"modal"}))},extract:function(e,t,r){return null==r&&(r={}),up.migrate.deprecated("up.modal.extract(target, document)",'up.layer.open({ document, mode: "modal" })'),up.layer.open(a.merge(r,{target:e,html:t,layer:"modal"}))},close:function(e){return null==e&&(e={}),up.migrate.deprecated("up.modal.close()","up.layer.dismiss()"),up.layer.dismiss(null,e),up.migrate.formerlyAsync("up.layer.dismiss()")},url:function(){return up.migrate.deprecated("up.modal.url()","up.layer.location"),up.layer.location},coveredUrl:function(){var e;return up.migrate.deprecated("up.modal.coveredUrl()","up.layer.parent.location"),null!=(e=up.layer.parent)?e.location:void 0},get_config:function(){return up.migrate.deprecated("up.modal.config","up.layer.config.modal"),up.layer.config.modal},contains:function(e){return up.migrate.deprecated("up.modal.contains()","up.layer.contains()"),up.layer.contains(e)},isOpen:function(){return up.migrate.deprecated("up.modal.isOpen()","up.layer.isOverlay()"),up.layer.isOverlay()},get_flavors:function(){throw e},flavor:function(){throw e}}),up.migrate.renamedEvent("up:modal:open","up:layer:open"),up.migrate.renamedEvent("up:modal:opened","up:layer:opened"),up.migrate.renamedEvent("up:modal:close","up:layer:dismiss"),up.migrate.renamedEvent("up:modal:closed","up:layer:dismissed"),up.link.targetMacro("up-modal",{"up-layer":"new modal"},function(){return up.migrate.deprecated("a[up-modal]",'a[up-layer="new modal"]')}),up.link.targetMacro("up-drawer",{"up-layer":"new drawer"},function(){return up.migrate.deprecated("a[up-drawer]",'a[up-layer="new drawer"]')})}.call(this),function(){var r;r=up.util,up.element,up.popup=r.literal({attach:function(e,t){return null==t&&(t={}),e=up.fragment.get(e),up.migrate.deprecated("up.popup.attach(origin)","up.layer.open({ origin, layer: 'popup' })"),up.layer.open(r.merge(t,{origin:e,layer:"popup"}))},close:function(e){return null==e&&(e={}),up.migrate.deprecated("up.popup.close()","up.layer.dismiss()"),up.layer.dismiss(null,e)},url:function(){return up.migrate.deprecated("up.popup.url()","up.layer.location"),up.layer.location},coveredUrl:function(){var e;return up.migrate.deprecated("up.popup.coveredUrl()","up.layer.parent.location"),null!=(e=up.layer.parent)?e.location:void 0},get_config:function(){return up.migrate.deprecated("up.popup.config","up.layer.config.popup"),up.layer.config.popup},contains:function(e){return up.migrate.deprecated("up.popup.contains()","up.layer.contains()"),up.layer.contains(e)},isOpen:function(){return up.migrate.deprecated("up.popup.isOpen()","up.layer.isOverlay()"),up.layer.isOverlay()},sync:function(){return up.migrate.deprecated("up.popup.sync()","up.layer.sync()"),up.layer.sync()}}),up.migrate.renamedEvent("up:popup:open","up:layer:open"),up.migrate.renamedEvent("up:popup:opened","up:layer:opened"),up.migrate.renamedEvent("up:popup:close","up:layer:dismiss"),up.migrate.renamedEvent("up:popup:closed","up:layer:dismissed"),up.link.targetMacro("up-popup",{"up-layer":"new popup"},function(){return up.migrate.deprecated("[up-popup]",'[up-layer="new popup"]')})}.call(this),function(){up.tooltip=up.macro("[up-tooltip]",function(e){return up.migrate.warn("[up-tooltip] has been deprecated. A [title] was set instead."),up.element.setMissingAttr(e,"title",e.getAttribute("up-tooltip"))})}.call(this),function(){var t,r,a=[].slice;r=up.util,up.migrate.renamedPackage("proxy","network"),up.migrate.renamedEvent("up:proxy:load","up:request:load"),up.migrate.renamedEvent("up:proxy:received","up:request:loaded"),up.migrate.renamedEvent("up:proxy:loaded","up:request:loaded"),up.migrate.renamedEvent("up:proxy:fatal","up:request:fatal"),up.migrate.renamedEvent("up:proxy:aborted","up:request:aborted"),up.migrate.renamedEvent("up:proxy:slow","up:request:late"),up.migrate.renamedEvent("up:proxy:recover","up:request:recover"),t=function(){return up.migrate.deprecated("up.proxy.config.preloadDelay","up.link.config.preloadDelay")},Object.defineProperty(up.network.config,"preloadDelay",{get:function(){return t(),up.link.config.preloadDelay},set:function(e){return t(),up.link.config.preloadDelay=e}}),up.migrate.renamedProperty(up.network.config,"maxRequests","concurrency"),up.migrate.renamedProperty(up.network.config,"slowDelay","badResponseTime"),up.migrate.handleNetworkPreloadArgs=function(){var e,t;if(e=1<=arguments.length?a.call(arguments,0):[],r.isElementish(e[0]))return up.migrate.warn("up.proxy.preload(link) has been renamed to up.link.preload(link)"),(t=up.link).preload.apply(t,e)},up.migrate.handleRequestOptions=function(e){return up.migrate.fixKey(e,"data","params")},up.ajax=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.deprecated("up.ajax()","up.request()"),t=function(e){return e.text},up.request.apply(up,e).then(t)},up.network.clear=function(){return up.migrate.deprecated("up.proxy.clear()","up.cache.clear()"),up.cache.clear()},up.Request.prototype.navigate=function(){return up.migrate.deprecated("up.Request#navigate()","up.Request#loadPage()"),this.loadPage()},up.Response.prototype.isSuccess=function(){return up.migrate.deprecated("up.Response#isSuccess()","up.Response#ok"),this.ok},up.Response.prototype.isError=function(){return up.migrate.deprecated("up.Response#isError()","!up.Response#ok"),!this.ok}}.call(this),function(){up.migrate.renamedProperty(up.radio.config,"hungry","hungrySelectors")}.call(this),function(){var r=[].slice;up.migrate.renamedPackage("layout","viewport"),up.migrate.renamedProperty(up.viewport.config,"viewports","viewportSelectors"),up.migrate.renamedProperty(up.viewport.config,"snap","revealSnap"),up.viewport.closest=function(){var e,t;return e=1<=arguments.length?r.call(arguments,0):[],up.migrate.deprecated("up.viewport.closest()","up.viewport.get()"),(t=up.viewport).get.apply(t,e)}}.call(this),function(){up.framework.stopExtension()}.call(this),function(){}.call(this);
1
+ (function(){up.framework.startExtension()}).call(this),function(){var u,p,e,t,r,a,n,i,o,l,c,s,m,d,g=[].slice;u=up.util,up.migrate=(p=new up.Config(function(){return{logLevel:"warn"}}),c=function(e,t,r){var a;return a=function(){return m("Property { %s } has been renamed to { %s } (found in %o)",t,r,e)},Object.defineProperty(e,t,{get:function(){return a(),this[r]},set:function(e){return a(),this[r]=e}})},a=function(e,t,r){if(u.isDefined(e[t]))return m("Property { %s } has been renamed to { %s } (found in %o)",t,r,e),u.renameKey(e,t,r)},o={},i=function(e,t){return o[e]=t},t=function(e){var t;return(t=o[e])?(m("Event "+e+" has been renamed to "+t),t):e},r=function(e){return u.uniq(u.map(e,t))},l=function(e,t){return Object.defineProperty(up,e,{get:function(){return m("up."+e+" has been renamed to up."+t),up[t]}})},d={},m=function(e){var t,r,a,n;if(a=e,t=2<=arguments.length?g.call(arguments,1):[],r=u.sprintf.apply(u,[a].concat(g.call(t))),!d[r])return d[r]=!0,(n=up.log)[p.logLevel].apply(n,["DEPRECATION",a].concat(g.call(t)))},e=function(e,t){return m(e+" has been deprecated. Use "+t+" instead.")},n=function(e){var t,r;return r=Promise.resolve(),t=r.then,r.then=function(){return m(e+" is now a sync function"),t.apply(this,arguments)},r},s=function(){return p.reset()},up.on("up:framework:reset",s),{deprecated:e,renamedPackage:l,renamedProperty:c,formerlyAsync:n,renamedEvent:i,fixEventTypes:r,fixKey:a,warn:m,loaded:!0,config:p})}.call(this),function(){var a=[].slice;up.util.only=function(e){var t,r;return r=e,t=2<=arguments.length?a.call(arguments,1):[],up.migrate.deprecated("up.util.only(object, ...keys)","up.util.pick(object, keys)"),up.util.pick(r,t)},up.util.except=function(e){var t,r;return r=e,t=2<=arguments.length?a.call(arguments,1):[],up.migrate.deprecated("up.util.except(object, ...keys)","up.util.omit(object, keys)"),up.util.omit(r,t)},up.util.parseUrl=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.parseUrl() has been renamed to up.util.parseURL()"),(t=up.util).parseURL.apply(t,e)},up.util.any=function(){var e;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.any() has been renamed to up.util.some()"),some.apply(null,e)},up.util.all=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.all() has been renamed to up.util.every()"),(t=up.util).every.apply(t,e)},up.util.detect=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.detect() has been renamed to up.util.find()"),(t=up.util).find.apply(t,e)},up.util.select=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.select() has been renamed to up.util.filter()"),(t=up.util).filter.apply(t,e)},up.util.setTimer=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.setTimer() has been renamed to up.util.timer()"),(t=up.util).timer.apply(t,e)},up.util.escapeHtml=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.deprecated("up.util.escapeHtml","up.util.escapeHTML"),(t=up.util).escapeHTML.apply(t,e)},up.util.selectorForElement=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.selectorForElement() has been renamed to up.fragment.toTarget()"),(t=up.fragment).toTarget.apply(t,e)},up.util.nextFrame=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.nextFrame() has been renamed to up.util.task()"),(t=up.util).task.apply(t,e)}}.call(this),function(){var r=[].slice;up.element.first=function(){var e,t;return e=1<=arguments.length?r.call(arguments,0):[],up.migrate.deprecated("up.element.first()","up.element.get()"),(t=up.element).get.apply(t,e)},up.element.createFromHtml=function(){var e,t;return e=1<=arguments.length?r.call(arguments,0):[],up.migrate.deprecated("up.element.createFromHtml","up.element.createFromHTML"),(t=up.element).createFromHTML.apply(t,e)}}.call(this),function(){var t=[].slice;up.migrate.renamedPackage("bus","event"),up.event.nobodyPrevents=function(){var e;return e=1<=arguments.length?t.call(arguments,0):[],up.migrate.deprecated("up.event.nobodyPrevents(type)","!up.emit(type).defaultPrevented"),!up.emit.apply(up,e).defaultPrevented}}.call(this),function(){up.migrate.renamedProperty(up.form.config,"fields","fieldSelectors"),up.migrate.renamedProperty(up.form.config,"submitButtons","submitButtonSelectors")}.call(this),function(){var p,r=[].slice;p=up.util,up.migrate.renamedPackage("flow","fragment"),up.migrate.renamedPackage("dom","fragment"),up.migrate.renamedProperty(up.fragment.config,"fallbacks","mainTargets"),up.migrate.handleResponseDocOptions=function(e){return up.migrate.fixKey(e,"html","document")},up.replace=function(e,t,r){return up.migrate.deprecated("up.replace(target, url)","up.navigate(target, { url })"),up.navigate(p.merge(r,{target:e,url:t}))},up.extract=function(e,t,r){return up.migrate.deprecated("up.extract(target, document)","up.navigate(target, { document })"),up.navigate(p.merge(r,{target:e,document:t}))},up.fragment.first=function(){var e,t;return e=1<=arguments.length?r.call(arguments,0):[],up.migrate.deprecated("up.fragment.first()","up.fragment.get()"),(t=up.fragment).get.apply(t,e)},up.first=up.fragment.first,up.migrate.handleScrollOptions=function(e){if(p.isUndefined(e.scroll)&&(p.isString(e.reveal)?(up.migrate.deprecated("Option { reveal: '"+e.reveal+"' }","{ scroll: '"+e.reveal+"' }"),e.scroll=e.reveal):!0===e.reveal?(up.migrate.deprecated("Option { reveal: true }","{ scroll: 'target' }"),e.scroll="target"):!1===e.reveal&&(up.migrate.deprecated("Option { reveal: false }","{ scroll: false }"),e.scroll=!1),p.isDefined(e.resetScroll)&&(up.migrate.deprecated("Option { resetScroll: true }","{ scroll: 'reset' }"),e.scroll="teset"),p.isDefined(e.restoreScroll)))return up.migrate.deprecated("Option { restoreScroll: true }","{ scroll: 'restore' }"),e.scroll="restore"},up.migrate.handleHistoryOption=function(e){if(p.isString(e.history)&&"auto"!==e.history)return up.migrate.warn("Passing a URL as { history } option is deprecated. Pass it as { location } instead."),e.location=e.history,e.history="auto"},up.migrate.handleRenderOptions=function(e){var t,r,a,n,u;for(up.migrate.handleHistoryOption(e),u=[],t=0,r=(n=["target","origin"]).length;t<r;t++)a=n[t],p.isJQuery(e[a])?(up.migrate.warn("Passing a jQuery collection as { %s } is deprecated. Pass it as a native element instead.",a),u.push(e[a]=up.element.get(e[a]))):u.push(void 0);return u}}.call(this),function(){up.migrate.renamedProperty(up.history.config,"popTargets","restoreTargets"),up.history.url=function(){return up.migrate.deprecated("up.history.url()","up.history.location"),up.history.location},up.migrate.renamedEvent("up:history:push","up:location:changed"),up.migrate.renamedEvent("up:history:pushed","up:location:changed"),up.migrate.renamedEvent("up:history:restore","up:location:changed"),up.migrate.renamedEvent("up:history:restored","up:location:changed"),up.migrate.renamedEvent("up:history:replaced","up:location:changed")}.call(this),function(){up.migrate.renamedPackage("navigation","feedback"),up.migrate.renamedProperty(up.feedback.config,"navs","navSelectors")}.call(this),function(){up.migrate.parseFollowOptions=function(e){return e.string("flavor"),e.string("width"),e.string("height"),e["boolean"]("closable"),e.booleanOrString("reveal"),e["boolean"]("resetScroll"),e["boolean"]("restoreScroll")}}.call(this),function(){up.migrate.handleLayerOptions=function(e){var t,r,a,n;for(up.migrate.fixKey(e,"flavor","mode"),up.migrate.fixKey(e,"closable","dismissable"),up.migrate.fixKey(e,"closeLabel","dismissLabel"),r=0,a=(n=["width","maxWidth","height"]).length;r<a;r++)e[t=n[r]]&&up.migrate.warn("Layer option { "+t+" } has been removed. Use { size } or { class } instead.");if(e.sticky&&up.migrate.warn("Layer option { sticky } has been removed. Give links an [up-peel=false] attribute to prevent layer dismissal on click."),e.template&&up.migrate.warn("Layer option { template } has been removed. Use { class } or modify the layer HTML on up:layer:open."),"page"===e.layer&&(up.migrate.warn("Option { layer: 'page' } has been renamed to { layer: 'root' }."),e.layer="root"),"modal"===e.layer||"popup"===e.layer)return up.migrate.warn("Option { layer: '"+e.layer+"' } has been removed. Did you mean { layer: 'overlay' }?"),e.layer="overlay"},up.migrate.handleTetherOptions=function(e){var t,r,a;if(r=(a=e.position.split("-"))[0],t=a[1])return up.migrate.warn("The position value %o is deprecated. Use %o instead.",e.position,{position:r,align:t}),e.position=r,e.align=t},up.migrate.registerLayerCloser=function(r){return r.registerClickCloser("up-close",function(e,t){return up.migrate.deprecated("[up-close]","[up-dismiss]"),r.dismiss(e,t)})},up.migrate.handleLayerConfig=function(e){return up.migrate.fixKey(e,"history","historyVisible")}}.call(this),function(){var e,a;a=up.util,e=new Error("up.modal.flavors has been removed without direct replacement. You may give new layers a { class } or modify layer elements on up:layer:open."),up.modal=a.literal({visit:function(e,t){return null==t&&(t={}),up.migrate.deprecated("up.modal.visit(url)",'up.layer.open({ url, mode: "modal" })'),up.layer.open(a.merge(t,{url:e,mode:"modal"}))},follow:function(e,t){return null==t&&(t={}),up.migrate.deprecated("up.modal.follow(link)",'up.follow(link, { layer: "modal" })'),up.follow(e,a.merge(t,{layer:"modal"}))},extract:function(e,t,r){return null==r&&(r={}),up.migrate.deprecated("up.modal.extract(target, document)",'up.layer.open({ document, mode: "modal" })'),up.layer.open(a.merge(r,{target:e,html:t,layer:"modal"}))},close:function(e){return null==e&&(e={}),up.migrate.deprecated("up.modal.close()","up.layer.dismiss()"),up.layer.dismiss(null,e),up.migrate.formerlyAsync("up.layer.dismiss()")},url:function(){return up.migrate.deprecated("up.modal.url()","up.layer.location"),up.layer.location},coveredUrl:function(){var e;return up.migrate.deprecated("up.modal.coveredUrl()","up.layer.parent.location"),null!=(e=up.layer.parent)?e.location:void 0},get_config:function(){return up.migrate.deprecated("up.modal.config","up.layer.config.modal"),up.layer.config.modal},contains:function(e){return up.migrate.deprecated("up.modal.contains()","up.layer.contains()"),up.layer.contains(e)},isOpen:function(){return up.migrate.deprecated("up.modal.isOpen()","up.layer.isOverlay()"),up.layer.isOverlay()},get_flavors:function(){throw e},flavor:function(){throw e}}),up.migrate.renamedEvent("up:modal:open","up:layer:open"),up.migrate.renamedEvent("up:modal:opened","up:layer:opened"),up.migrate.renamedEvent("up:modal:close","up:layer:dismiss"),up.migrate.renamedEvent("up:modal:closed","up:layer:dismissed"),up.link.targetMacro("up-modal",{"up-layer":"new modal"},function(){return up.migrate.deprecated("a[up-modal]",'a[up-layer="new modal"]')}),up.link.targetMacro("up-drawer",{"up-layer":"new drawer"},function(){return up.migrate.deprecated("a[up-drawer]",'a[up-layer="new drawer"]')})}.call(this),function(){var r;r=up.util,up.element,up.popup=r.literal({attach:function(e,t){return null==t&&(t={}),e=up.fragment.get(e),up.migrate.deprecated("up.popup.attach(origin)","up.layer.open({ origin, layer: 'popup' })"),up.layer.open(r.merge(t,{origin:e,layer:"popup"}))},close:function(e){return null==e&&(e={}),up.migrate.deprecated("up.popup.close()","up.layer.dismiss()"),up.layer.dismiss(null,e)},url:function(){return up.migrate.deprecated("up.popup.url()","up.layer.location"),up.layer.location},coveredUrl:function(){var e;return up.migrate.deprecated("up.popup.coveredUrl()","up.layer.parent.location"),null!=(e=up.layer.parent)?e.location:void 0},get_config:function(){return up.migrate.deprecated("up.popup.config","up.layer.config.popup"),up.layer.config.popup},contains:function(e){return up.migrate.deprecated("up.popup.contains()","up.layer.contains()"),up.layer.contains(e)},isOpen:function(){return up.migrate.deprecated("up.popup.isOpen()","up.layer.isOverlay()"),up.layer.isOverlay()},sync:function(){return up.migrate.deprecated("up.popup.sync()","up.layer.sync()"),up.layer.sync()}}),up.migrate.renamedEvent("up:popup:open","up:layer:open"),up.migrate.renamedEvent("up:popup:opened","up:layer:opened"),up.migrate.renamedEvent("up:popup:close","up:layer:dismiss"),up.migrate.renamedEvent("up:popup:closed","up:layer:dismissed"),up.link.targetMacro("up-popup",{"up-layer":"new popup"},function(){return up.migrate.deprecated("[up-popup]",'[up-layer="new popup"]')})}.call(this),function(){up.tooltip=up.macro("[up-tooltip]",function(e){return up.migrate.warn("[up-tooltip] has been deprecated. A [title] was set instead."),up.element.setMissingAttr(e,"title",e.getAttribute("up-tooltip"))})}.call(this),function(){var t,r,a=[].slice;r=up.util,up.migrate.renamedPackage("proxy","network"),up.migrate.renamedEvent("up:proxy:load","up:request:load"),up.migrate.renamedEvent("up:proxy:received","up:request:loaded"),up.migrate.renamedEvent("up:proxy:loaded","up:request:loaded"),up.migrate.renamedEvent("up:proxy:fatal","up:request:fatal"),up.migrate.renamedEvent("up:proxy:aborted","up:request:aborted"),up.migrate.renamedEvent("up:proxy:slow","up:request:late"),up.migrate.renamedEvent("up:proxy:recover","up:request:recover"),t=function(){return up.migrate.deprecated("up.proxy.config.preloadDelay","up.link.config.preloadDelay")},Object.defineProperty(up.network.config,"preloadDelay",{get:function(){return t(),up.link.config.preloadDelay},set:function(e){return t(),up.link.config.preloadDelay=e}}),up.migrate.renamedProperty(up.network.config,"maxRequests","concurrency"),up.migrate.renamedProperty(up.network.config,"slowDelay","badResponseTime"),up.migrate.handleNetworkPreloadArgs=function(){var e,t;if(e=1<=arguments.length?a.call(arguments,0):[],r.isElementish(e[0]))return up.migrate.warn("up.proxy.preload(link) has been renamed to up.link.preload(link)"),(t=up.link).preload.apply(t,e)},up.migrate.handleRequestOptions=function(e){return up.migrate.fixKey(e,"data","params")},up.ajax=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.deprecated("up.ajax()","up.request()"),t=function(e){return e.text},up.request.apply(up,e).then(t)},up.network.clear=function(){return up.migrate.deprecated("up.proxy.clear()","up.cache.clear()"),up.cache.clear()},up.Request.prototype.navigate=function(){return up.migrate.deprecated("up.Request#navigate()","up.Request#loadPage()"),this.loadPage()},up.Response.prototype.isSuccess=function(){return up.migrate.deprecated("up.Response#isSuccess()","up.Response#ok"),this.ok},up.Response.prototype.isError=function(){return up.migrate.deprecated("up.Response#isError()","!up.Response#ok"),!this.ok}}.call(this),function(){up.migrate.renamedProperty(up.radio.config,"hungry","hungrySelectors")}.call(this),function(){var o;o=up.util,up.migrate.postCompile=function(e,t){var r,a,n,u,p,i;if(n=t.keep){for(up.migrate.warn("The { keep: true } option for up.compiler() has been removed. Have the compiler set [up-keep] attribute instead."),i=o.isString(n)?n:"",p=[],a=0,u=e.length;a<u;a++)r=e[a],p.push(r.setAttribute("up-keep",i));return p}}}.call(this),function(){var r=[].slice;up.migrate.renamedPackage("layout","viewport"),up.migrate.renamedProperty(up.viewport.config,"viewports","viewportSelectors"),up.migrate.renamedProperty(up.viewport.config,"snap","revealSnap"),up.viewport.closest=function(){var e,t;return e=1<=arguments.length?r.call(arguments,0):[],up.migrate.deprecated("up.viewport.closest()","up.viewport.get()"),(t=up.viewport).get.apply(t,e)}}.call(this),function(){up.framework.stopExtension()}.call(this),function(){}.call(this);
data/dist/unpoly.js CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  (function() {
7
7
  window.up = {
8
- version: "2.0.0-rc6"
8
+ version: "2.0.0-rc11"
9
9
  };
10
10
 
11
11
  }).call(this);
@@ -110,20 +110,21 @@ to not include another library in your asset bundle.
110
110
  };
111
111
 
112
112
  /***
113
- Normalizes relative paths and absolute paths to a full URL
114
- that can be checked for equality with other normalized URLs.
115
-
116
- By default hashes are ignored, search queries are included.
113
+ Normalizes the given URL or path.
117
114
 
118
115
  @function up.util.normalizeURL
119
116
  @param {boolean} [options.host='cross-domain']
120
117
  Whether to include protocol, hostname and port in the normalized URL.
118
+
119
+ By default the host is only included if it differ's from the page's hostname.
121
120
  @param {boolean} [options.hash=false]
122
121
  Whether to include an `#hash` anchor in the normalized URL
123
122
  @param {boolean} [options.search=true]
124
123
  Whether to include a `?query` string in the normalized URL
125
124
  @param {boolean} [options.stripTrailingSlash=false]
126
125
  Whether to strip a trailing slash from the pathname
126
+ @return {string}
127
+ The normalized URL.
127
128
  @internal
128
129
  */
129
130
  normalizeURL = function(urlOrAnchor, options) {
@@ -178,6 +179,15 @@ to not include another library in your asset bundle.
178
179
  If the given URL is not fully qualified, it is assumed to be relative
179
180
  to the current page.
180
181
 
182
+ \#\#\# Example
183
+
184
+ ```js
185
+ let parsed = up.util.parseURL('/path?foo=value')
186
+ parsed.pathname // => '/path'
187
+ parsed.search // => '/?foo=value'
188
+ parsed.hash // => ''
189
+ ```
190
+
181
191
  @function up.util.parseURL
182
192
  @return {Object}
183
193
  The parsed URL as an object with
@@ -732,7 +742,7 @@ to not include another library in your asset bundle.
732
742
  @function up.util.isList
733
743
  @param value
734
744
  @return {boolean}
735
- @experimental
745
+ @stable
736
746
  */
737
747
  isList = function(value) {
738
748
  return isArray(value) || isNodeList(value) || isArguments(value) || isJQuery(value) || isHTMLCollection(value);
@@ -775,9 +785,20 @@ to not include another library in your asset bundle.
775
785
  };
776
786
 
777
787
  /***
788
+ Returns the given value if it is [array-like](/up.util.isList), otherwise
789
+ returns an array with the given value as its only element.
790
+
791
+ \#\#\# Example
792
+
793
+ ```js
794
+ up.util.wrapList([1, 2, 3]) // => [1, 2, 3]
795
+ up.util.wrapList('foo') // => ['foo']
796
+ ```
797
+
778
798
  @function up.util.wrapList
799
+ @param {any} value
779
800
  @return {Array|NodeList|jQuery}
780
- @internal
801
+ @experimental
781
802
  */
782
803
  wrapList = function(value) {
783
804
  if (isList(value)) {
@@ -1281,6 +1302,7 @@ to not include another library in your asset bundle.
1281
1302
  @function up.util.pick
1282
1303
  @param {Object} object
1283
1304
  @param {Array} keys
1305
+ @return {Object}
1284
1306
  @stable
1285
1307
  */
1286
1308
  pick = function(object, keys) {
@@ -1294,6 +1316,20 @@ to not include another library in your asset bundle.
1294
1316
  }
1295
1317
  return filtered;
1296
1318
  };
1319
+
1320
+ /***
1321
+ Returns a copy of the given object that only contains
1322
+ properties that pass the given tester function.
1323
+
1324
+ @function up.util.pickBy
1325
+ @param {Object} object
1326
+ @param {Function<string, string, object>} tester
1327
+ A function that will be called with each property.
1328
+
1329
+ The arguments are the property value, key and the entire object.
1330
+ @return {Object}
1331
+ @experimental
1332
+ */
1297
1333
  pickBy = function(object, tester) {
1298
1334
  var filtered, key, value;
1299
1335
  tester = iteratee(tester);
@@ -1359,8 +1395,20 @@ to not include another library in your asset bundle.
1359
1395
  If the given `value` is a function, calls the function with the given `args`.
1360
1396
  Otherwise it just returns `value`.
1361
1397
 
1398
+ \#\#\# Example
1399
+
1400
+ ```js
1401
+ up.util.evalOption(5) // => 5
1402
+
1403
+ let fn = () => 1 + 2
1404
+ up.util.evalOption(fn) // => 3
1405
+ ```
1406
+
1362
1407
  @function up.util.evalOption
1363
- @internal
1408
+ @param {any} value
1409
+ @param {Array} ...args
1410
+ @return {any}
1411
+ @experimental
1364
1412
  */
1365
1413
  evalOption = function() {
1366
1414
  var args, value;
@@ -1384,7 +1432,7 @@ to not include another library in your asset bundle.
1384
1432
 
1385
1433
  @function up.util.escapeHTML
1386
1434
  @param {string} string
1387
- The text that should be escaped
1435
+ The text that should be escaped.
1388
1436
  @stable
1389
1437
  */
1390
1438
  escapeHTML = function(string) {
@@ -1400,6 +1448,17 @@ to not include another library in your asset bundle.
1400
1448
  escapeRegExp = function(string) {
1401
1449
  return string.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
1402
1450
  };
1451
+
1452
+ /***
1453
+ Deletes the property with the given key from the given object
1454
+ and returns its value.
1455
+
1456
+ @function up.util.pluckKey
1457
+ @param {Object} object
1458
+ @param {string} key
1459
+ @return {any}
1460
+ @experimental
1461
+ */
1403
1462
  pluckKey = function(object, key) {
1404
1463
  var value;
1405
1464
  value = object[key];
@@ -1431,7 +1490,6 @@ to not include another library in your asset bundle.
1431
1490
  @param {Array<Function()>} functions
1432
1491
  @return {Function()}
1433
1492
  A function that will call all `functions` if called.
1434
-
1435
1493
  @internal
1436
1494
  */
1437
1495
  sequence = function(functions) {
@@ -1447,7 +1505,13 @@ to not include another library in your asset bundle.
1447
1505
  };
1448
1506
 
1449
1507
  /***
1450
- Flattens the given `array` a single level deep.
1508
+ Flattens the given `array` a single depth level.
1509
+
1510
+ \#\#\# Example
1511
+
1512
+ ```js
1513
+ let nested = [1, [2, 3], [4]]
1514
+ up.util.flatten(nested) // => [1, 2, 3, 4]
1451
1515
 
1452
1516
  @function up.util.flatten
1453
1517
  @param {Array} array
@@ -1472,7 +1536,7 @@ to not include another library in your asset bundle.
1472
1536
 
1473
1537
  /***
1474
1538
  Maps each element using a mapping function,
1475
- then flattens the result into a new array.
1539
+ then [flattens](/up.util.flatten) the result into a new array.
1476
1540
 
1477
1541
  @function up.util.flatMap
1478
1542
  @param {Array} array
@@ -2239,7 +2303,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
2239
2303
  var slice = [].slice;
2240
2304
 
2241
2305
  up.element = (function() {
2242
- var CSS_LENGTH_PROPS, MATCH_FN_NAME, SINGLETON_PATTERN, SINGLETON_TAG_NAMES, affix, all, ancestor, around, attributeSelector, booleanAttr, booleanOrStringAttr, callbackAttr, closest, closestAttr, computedStyle, computedStyleNumber, concludeCSSTransition, createDocumentFromHTML, createFromHTML, createFromSelector, cssLength, elementTagName, extractFromStyleObject, first, fixedToAbsolute, getList, getOne, getRoot, hasCSSTransition, hide, idSelector, inlineStyle, insertBefore, isDetached, isInSubtree, isSingleton, isSingletonSelector, isVisible, jsonAttr, matches, metaContent, normalizeStyleValueForWrite, numberAttr, paint, remove, replace, setAttrs, setInlineStyle, setMissingAttr, setMissingAttrs, setTemporaryAttrs, setTemporaryStyle, show, stringAttr, subtree, toSelector, toggle, toggleAttr, toggleClass, trueAttributeSelector, u, unwrap, upAttrs, valueToList, wrapChildren;
2306
+ var CSS_LENGTH_PROPS, MATCH_FN_NAME, SINGLETON_PATTERN, SINGLETON_TAG_NAMES, affix, all, ancestor, around, attributeSelector, booleanAttr, booleanOrStringAttr, callbackAttr, classSelector, closest, closestAttr, computedStyle, computedStyleNumber, concludeCSSTransition, createDocumentFromHTML, createFromHTML, createFromSelector, cssLength, elementTagName, extractFromStyleObject, first, fixedToAbsolute, getList, getOne, getRoot, hasCSSTransition, hide, idSelector, inlineStyle, insertBefore, isDetached, isInSubtree, isSingleton, isSingletonSelector, isVisible, jsonAttr, matches, metaContent, normalizeStyleValueForWrite, numberAttr, paint, remove, replace, setAttrs, setInlineStyle, setMissingAttr, setMissingAttrs, setTemporaryAttrs, setTemporaryStyle, show, stringAttr, subtree, toSelector, toggle, toggleAttr, toggleClass, trueAttributeSelector, u, unwrap, upAttrs, valueToList, wrapChildren;
2243
2307
  u = up.util;
2244
2308
  MATCH_FN_NAME = up.browser.isIE11() ? 'msMatchesSelector' : 'matches';
2245
2309
 
@@ -2521,6 +2585,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
2521
2585
  [this WHATWG mailing list post](http://lists.w3.org/Archives/Public/public-whatwg-archive/2014Apr/0094.html).
2522
2586
 
2523
2587
  @function up.element.show
2588
+ @param {Element} element
2524
2589
  @stable
2525
2590
  */
2526
2591
  show = function(element) {
@@ -2559,8 +2624,10 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
2559
2624
  @param {Element} element
2560
2625
  The element for which to add or remove the class.
2561
2626
  @param {string} className
2562
- A boolean value to determine whether the class should be added or removed.
2563
- @param {string} state
2627
+ The class which should be added or removed.
2628
+ @param {Boolean} [newPresent]
2629
+ Pass `true` to add the class to the element or `false` to remove it.
2630
+
2564
2631
  If omitted, the class will be added if missing and removed if present.
2565
2632
  @stable
2566
2633
  */
@@ -2909,6 +2976,15 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
2909
2976
  }
2910
2977
  };
2911
2978
 
2979
+ /***
2980
+ @function up.element.classSelector
2981
+ @internal
2982
+ */
2983
+ classSelector = function(klass) {
2984
+ klass = klass.replace(/:/g, '\\:');
2985
+ return "." + klass;
2986
+ };
2987
+
2912
2988
  /***
2913
2989
  Always creates a full document with a <html> root, even if the given `html`
2914
2990
  is only a fragment.
@@ -3442,6 +3518,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
3442
3518
  affix: affix,
3443
3519
  toSelector: toSelector,
3444
3520
  idSelector: idSelector,
3521
+ classSelector: classSelector,
3445
3522
  isSingleton: isSingleton,
3446
3523
  isSingletonSelector: isSingletonSelector,
3447
3524
  attributeSelector: attributeSelector,
@@ -4986,7 +5063,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
4986
5063
  };
4987
5064
 
4988
5065
  CompilerPass.prototype.runCompiler = function(compiler) {
4989
- var i, j, keepValue, len, len1, match, matches, results, value;
5066
+ var base, i, len, match, matches;
4990
5067
  matches = this.select(compiler.selector);
4991
5068
  if (!matches.length) {
4992
5069
  return;
@@ -5002,15 +5079,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
5002
5079
  this.compileOneElement(compiler, match);
5003
5080
  }
5004
5081
  }
5005
- if (keepValue = compiler.keep) {
5006
- value = u.isString(keepValue) ? keepValue : '';
5007
- results = [];
5008
- for (j = 0, len1 = matches.length; j < len1; j++) {
5009
- match = matches[j];
5010
- results.push(match.setAttribute('up-keep', value));
5011
- }
5012
- return results;
5013
- }
5082
+ return typeof (base = up.migrate).postCompile === "function" ? base.postCompile(matches, compiler) : void 0;
5014
5083
  };
5015
5084
 
5016
5085
  CompilerPass.prototype.compileOneElement = function(compiler, element) {
@@ -6259,66 +6328,45 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
6259
6328
 
6260
6329
 
6261
6330
  /***
6262
- This layer's mode which governs its appearance and behavior.
6263
-
6264
- Available layer modes are:
6331
+ Whether fragment updates within this layer can affect browser history and window title.
6265
6332
 
6266
- - `'root'`
6267
- - `'modal'`
6268
- - `'popup'`
6269
- - `'drawer'`
6270
- - `'cover'`
6333
+ If a layer does not have visible history, its desendant layers cannot have history either.
6271
6334
 
6272
- @property up.Layer#mode
6273
- @param {string} mode
6274
- @stable
6335
+ @property up.Layer#historyVisible
6336
+ @param {boolean} historyVisible
6275
6337
  */
6276
6338
 
6277
6339
 
6278
6340
  /***
6279
- Whether fragment updates within this layer can affect browser history and window title.
6341
+ This layer's mode which governs its appearance and behavior.
6280
6342
 
6281
- @property up.Layer#historyVisible
6282
- @param {boolean} historyVisible
6343
+ @see layer-terminology
6344
+
6345
+ @property up.Layer#mode
6346
+ @param {string} mode
6347
+ @stable
6283
6348
  */
6284
6349
 
6285
6350
 
6286
6351
  /***
6287
- This layer's context object.
6288
-
6289
- Think of *context* as [session storage](/https://makandracards.com/makandra/32865), but specific to a [layer](/up.layer)
6290
- rather than specific to an entire browser tab.
6291
-
6292
- You may access the context object's properties like a regular JavaScript object.
6352
+ This layer's [context](/context).
6293
6353
 
6294
6354
  \#\#\# Example
6295
6355
 
6356
+ You may access the context properties like a regular JavaScript object.
6357
+
6296
6358
  ```js
6297
6359
  let layer = up.layer.current
6298
6360
  layer.context.message = 'Please select a contact'
6299
6361
  console.log(layer.context) // logs "{ message: 'Please select a contact' }"
6300
6362
  ```
6301
6363
 
6302
- \#\#\# Accessing the context from the server
6303
-
6304
- The context is is sent as an `X-Up-Context` header along with every
6305
- [request](/up.request) to the server. The server may also update the updating
6306
- layer's context by including an `X-Up-Context` header in its response.
6307
-
6308
6364
  @property up.Layer#context
6309
6365
  @param {Object} context
6310
- @stable
6311
- */
6312
-
6313
-
6314
- /***
6315
- Whether fragment updates within this layer will affect [browser history](/up.history).
6316
-
6317
- If a layer does not have visible history, its desendant layers cannot have history either.
6366
+ The context object.
6318
6367
 
6319
- @property up.Layer#historyVisible
6320
- @param {boolean} historyVisible
6321
- @stable
6368
+ If no context has been set an empty object is returned.
6369
+ @experimental
6322
6370
  */
6323
6371
 
6324
6372
  Layer.prototype.keys = function() {
@@ -6661,7 +6709,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
6661
6709
 
6662
6710
 
6663
6711
  /***
6664
- Listens to a ([DOM event](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Events) that originated
6712
+ Listens to a [DOM event](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Events) that originated
6665
6713
  on an element [contained](/up.Layer.prototype.contains) by this layer.
6666
6714
 
6667
6715
  This will ignore events emitted on elements in [descendant](/up.Layer.prototype.descendants) overlays,
@@ -9304,7 +9352,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
9304
9352
 
9305
9353
 
9306
9354
  /***
9307
- Instances of `up.Request` normalizes properties of an [`AJAX request`](/up.request)
9355
+ Instances of `up.Request` normalizes properties of an [AJAX request](/up.request)
9308
9356
  such as the requested URL, form parameters and HTTP method.
9309
9357
 
9310
9358
  You can queue a request using the `up.request()` method:
@@ -9341,6 +9389,23 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
9341
9389
  */
9342
9390
 
9343
9391
 
9392
+ /***
9393
+ The [hash component](https://en.wikipedia.org/wiki/URI_fragment) of this request's URL.
9394
+
9395
+ The `{ hash }` property is automatically extracted from the given URL:
9396
+
9397
+ ```js
9398
+ let request = up.request({ url: '/path#section' })
9399
+ request.url // => '/path'
9400
+ request.hash // => '#section'
9401
+ ```
9402
+
9403
+ @property up.Request#hash
9404
+ @param {string} hash
9405
+ @stable
9406
+ */
9407
+
9408
+
9344
9409
  /***
9345
9410
  [Parameters](/up.Params) that should be sent as the request's payload.
9346
9411
 
@@ -9351,7 +9416,9 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
9351
9416
 
9352
9417
 
9353
9418
  /***
9354
- The CSS selector that will be sent as an `X-Up-Target` header.
9419
+ The CSS selector targeted by this request.
9420
+
9421
+ The selector will be sent as an `X-Up-Target` header.
9355
9422
 
9356
9423
  @property up.Request#target
9357
9424
  @param {string} target
@@ -9360,7 +9427,10 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
9360
9427
 
9361
9428
 
9362
9429
  /***
9363
- The CSS selector that will be sent as an `X-Up-Fail-Target` header.
9430
+ The CSS selector targeted by this request in case the server responds
9431
+ with an [error code](/server-errors).
9432
+
9433
+ The selector will be sent as an `X-Up-Fail-Target` header.
9364
9434
 
9365
9435
  @property up.Request#failTarget
9366
9436
  @param {string} failTarget
@@ -9371,7 +9441,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
9371
9441
  /***
9372
9442
  An object of additional HTTP headers.
9373
9443
 
9374
- Note that Unpoly will by default send a number of custom request headers.
9444
+ Unpoly will by default send a number of custom request headers.
9375
9445
  See `up.protocol` and `up.network.config.metaKeys` for details.
9376
9446
 
9377
9447
  @property up.Request#headers
@@ -9407,25 +9477,67 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
9407
9477
 
9408
9478
 
9409
9479
  /***
9410
- TODO: Docs
9480
+ The [context](/contact) of the layer targeted by this request.
9481
+
9482
+ The context object will be sent as an `X-Up-Context` header.
9411
9483
 
9412
9484
  @property up.Request#context
9413
9485
  @param {Object} context
9414
- @stable
9486
+ @experimental
9415
9487
  */
9416
9488
 
9417
9489
 
9418
9490
  /***
9419
- TODO: Docs
9491
+ The [context](/contact) of the layer targeted by this request in case the server responds with an [error code](/server-errors).
9492
+
9493
+ The context object will be sent as an `X-Up-Fail-Context` header.
9420
9494
 
9421
9495
  @property up.Request#failContext
9422
9496
  @param {Object} failContext
9423
- @stable
9497
+ @experimental
9424
9498
  */
9425
9499
 
9426
9500
 
9427
9501
  /***
9428
- TODO: Docs
9502
+ The [layer](/up.layer) targeted by this request.
9503
+
9504
+ To prevent memory leaks, this property is removed shortly after the response is received.
9505
+
9506
+ @property up.Request#layer
9507
+ @param {up.Layer} layer
9508
+ @experimental
9509
+ */
9510
+
9511
+
9512
+ /***
9513
+ The [layer](/up.layer) targeted by this request in case the server responds with an [error code](/server-errors).
9514
+
9515
+ To prevent memory leaks, this property is removed shortly after the response is received.
9516
+
9517
+ @property up.Request#failLayer
9518
+ @param {up.Layer} layer
9519
+ @experimental
9520
+ */
9521
+
9522
+
9523
+ /***
9524
+ The element that triggered the request.
9525
+
9526
+ For example, when this request was triggered by a click on a link, the lonk
9527
+ element is set as the `{ origin }`.
9528
+
9529
+ To prevent memory leaks, this property is removed shortly after the response is received.
9530
+
9531
+ @property up.Request#origin
9532
+ @param {Element} origin
9533
+ @experimental
9534
+ */
9535
+
9536
+
9537
+ /***
9538
+ The [mode](/up.Layer.prototype.mode) of the layer targeted by this request.
9539
+
9540
+ The value will be sent as an `X-Up-Mode` header.
9429
9541
 
9430
9542
  @property up.Request#mode
9431
9543
  @param {string} mode
@@ -9434,7 +9546,9 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
9434
9546
 
9435
9547
 
9436
9548
  /***
9437
- TODO: Docs
9549
+ The [mode](/up.Layer.prototype.mode) of the layer targeted by this request in case the server responds with an [error code](/server-errors).
9550
+
9551
+ The value will be sent as an `X-Up-Fail-Mode` header.
9438
9552
 
9439
9553
  @property up.Request#failMode
9440
9554
  @param {string} failMode
@@ -9443,7 +9557,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
9443
9557
 
9444
9558
 
9445
9559
  /***
9446
- TODO: Docs
9560
+ The format in which the [request params](/up.Layer.prototype.params) will be encoded.
9447
9561
 
9448
9562
  @property up.Request#contentType
9449
9563
  @param {string} contentType
@@ -9452,13 +9566,22 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
9452
9566
 
9453
9567
 
9454
9568
  /***
9455
- TODO: Docs
9569
+ The payload that the request will encode into its body.
9570
+
9571
+ By default Unpoly will build a payload from the given `{ params }` option.
9456
9572
 
9457
9573
  @property up.Request#payload
9458
9574
  @param {string} payload
9459
9575
  @stable
9460
9576
  */
9461
9577
 
9578
+
9579
+ /***
9580
+ @property up.Request#preload
9581
+ @param {boolean} preload
9582
+ @experimental
9583
+ */
9584
+
9462
9585
  Request.prototype.keys = function() {
9463
9586
  return ['method', 'url', 'hash', 'params', 'target', 'failTarget', 'headers', 'timeout', 'preload', 'cache', 'clearCache', 'layer', 'mode', 'context', 'failLayer', 'failMode', 'failContext', 'origin', 'solo', 'queueTime', 'wrapMethod', 'contentType', 'payload', 'onQueued'];
9464
9587
  };
@@ -10180,7 +10303,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
10180
10303
 
10181
10304
 
10182
10305
  /***
10183
- Instances of `up.Response` describe the server response to an [`AJAX request`](/up.request).
10306
+ Instances of `up.Response` describe the server response to an [AJAX request](/up.request).
10184
10307
 
10185
10308
  \#\#\# Example
10186
10309
 
@@ -10292,6 +10415,14 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
10292
10415
  @experimental
10293
10416
  */
10294
10417
 
10418
+
10419
+ /***
10420
+ Changes to the current [context](/context) as [set by the server](/X-Up-Context).
10421
+
10422
+ @property up.Response#context
10423
+ @experimental
10424
+ */
10425
+
10295
10426
  Response.prototype.keys = function() {
10296
10427
  return ['method', 'url', 'text', 'status', 'request', 'xhr', 'target', 'title', 'acceptLayer', 'dismissLayer', 'eventPlans', 'context', 'clearCache', 'headers'];
10297
10428
  };
@@ -10838,7 +10969,8 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
10838
10969
 
10839
10970
  }).call(this);
10840
10971
  (function() {
10841
- var e, u;
10972
+ var e, u,
10973
+ bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
10842
10974
 
10843
10975
  u = up.util;
10844
10976
 
@@ -10846,6 +10978,8 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
10846
10978
 
10847
10979
  up.Tether = (function() {
10848
10980
  function Tether(options) {
10981
+ this.sync = bind(this.sync, this);
10982
+ this.scheduleSync = bind(this.scheduleSync, this);
10849
10983
  var base;
10850
10984
  if (typeof (base = up.migrate).handleTetherOptions === "function") {
10851
10985
  base.handleTetherOptions(options);
@@ -11179,6 +11313,9 @@ document.addEventListener('up:modal:open', (event) => {
11179
11313
  })
11180
11314
  ```
11181
11315
 
11316
+ @see up.on
11317
+ @see up.emit
11318
+
11182
11319
  @module up.event
11183
11320
  */
11184
11321
 
@@ -11681,7 +11818,11 @@ document.addEventListener('up:modal:open', (event) => {
11681
11818
  This hyperlink will emit an `user:select` event when clicked:
11682
11819
 
11683
11820
  ```
11684
- <a href='/users/5" up-emit='user:select' up-emit-props='{ "id": 5, "firstName": "Alice" }'>Alice</a>
11821
+ <a href='/users/5'
11822
+ up-emit='user:select'
11823
+ up-emit-props='{ "id": 5, "firstName": "Alice" }'>
11824
+ Alice
11825
+ </a>
11685
11826
 
11686
11827
  <script>
11687
11828
  up.on('a', 'user:select', function(event) {
@@ -11696,6 +11837,7 @@ document.addEventListener('up:modal:open', (event) => {
11696
11837
  The type of the event to be emitted.
11697
11838
  @param [up-emit-props='{}']
11698
11839
  The event properties, serialized as JSON.
11840
+ @stable
11699
11841
  */
11700
11842
  executeEmitAttr = function(event, element) {
11701
11843
  var eventProps, eventType, forkedEvent;
@@ -11764,7 +11906,7 @@ There are existing implementations for various web frameworks:
11764
11906
  - [Roda](https://github.com/adam12/roda-unpoly)
11765
11907
  - [Rack](https://github.com/adam12/rack-unpoly) (Sinatra, Padrino, Hanami, Cuba, ...)
11766
11908
  - [Phoenix](https://elixirforum.com/t/unpoly-a-framework-like-turbolinks/3614/15) (Elixir)
11767
- - [PHP](https://github.com/adam12/rack-unpoly) (Symfony, Laravel, Stack)
11909
+ - [PHP](https://github.com/webstronauts/php-unpoly) (Symfony, Laravel, Stack)
11768
11910
 
11769
11911
  @module up.protocol
11770
11912
  */
@@ -11987,53 +12129,20 @@ There are existing implementations for various web frameworks:
11987
12129
  The timestamp must be explicitely set by the user as an `[up-time]` attribute on the fragment.
11988
12130
  It should indicate the time when the fragment's underlying data was last changed.
11989
12131
 
11990
- Its value is the number of seconds elapsed since the [Unix epoch](https://en.wikipedia.org/wiki/Unix_time).
11991
-
11992
- If no timestamp is known, Unpoly will send a value of zero (`X-Up-Reload-From-Time: 0`).
11993
-
11994
- \#\#\# Example
12132
+ See `[up-time]` for a detailed example.
11995
12133
 
11996
- You may timestamp your fragments with an `[up-time]` attribute to indicate when the underlying data
11997
- was last changed. For instance, when the last message in a list was received from December 24th, 1:51:46 PM UTC:
12134
+ \#\#\# Format
11998
12135
 
11999
- ```html
12000
- <div class="messages" up-time="1608730818">
12001
- ...
12002
- </div>
12003
- ```
12136
+ The time is encoded is the number of seconds elapsed since the [Unix epoch](https://en.wikipedia.org/wiki/Unix_time).
12004
12137
 
12005
- When reloading the `.messages` fragment, Unpoly will echo that timestamp in an `X-Up-Reload-From-Time` header:
12138
+ For instance, a modification date of December 24th, 1:51:46 PM UTC would produce the following header:
12006
12139
 
12007
12140
  ```http
12141
+ X-Up-Target: .unread-count
12008
12142
  X-Up-Reload-From-Time: 1608730818
12009
12143
  ```
12010
12144
 
12011
- \#\# Cheap polling responses
12012
-
12013
- A use case for the `X-Up-Reload-From-Time` header is to avoid rendering unchanged content
12014
- while [polling](/up-poll).
12015
-
12016
- The server can compare the time from the request with the time of the last data update.
12017
- If no more recent data is available, the server can [render nothing](/X-Up-Target):
12018
-
12019
- ```ruby
12020
- class MessagesController < ApplicationController
12021
-
12022
- def index
12023
- if up.reload_from_time == current_user.last_message_at
12024
- up.render_nothing
12025
- else
12026
- @messages = current_user.messages.order(time: :desc).to_a
12027
- render 'index'
12028
- end
12029
- end
12030
-
12031
- end
12032
- ```
12033
-
12034
- Only rendering when needed saves <b>CPU time</b> on your server, which spends most of its response time rendering HTML.
12035
-
12036
- This also reduces the <b>bandwidth cost</b> for a request/response exchange to **~1 KB**.
12145
+ If no timestamp is known, Unpoly will send a value of zero (`X-Up-Reload-From-Time: 0`).
12037
12146
 
12038
12147
  @header X-Up-Reload-From-Time
12039
12148
  @stable
@@ -12043,7 +12152,7 @@ There are existing implementations for various web frameworks:
12043
12152
  };
12044
12153
 
12045
12154
  /***
12046
- This request header contains the targeted layer's [context](/up.context), serialized as JSON.
12155
+ This request header contains the targeted layer's [context](/context), serialized as JSON.
12047
12156
 
12048
12157
  The user may choose to not send this header by configuring
12049
12158
  `up.network.config.requestMetaKeys`.
@@ -12084,11 +12193,11 @@ There are existing implementations for various web frameworks:
12084
12193
  the request was in flight will get overridden by the server-provided context.
12085
12194
 
12086
12195
  @header X-Up-Context
12087
- @stable
12196
+ @experimental
12088
12197
  */
12089
12198
 
12090
12199
  /***
12091
- This request header contains the [context](/up.context) of the layer
12200
+ This request header contains the [context](/context) of the layer
12092
12201
  targeted for a failed fragment update, serialized as JSON.
12093
12202
 
12094
12203
  A fragment update is considered *failed* if the server responds with a
@@ -12107,7 +12216,7 @@ There are existing implementations for various web frameworks:
12107
12216
  ```
12108
12217
 
12109
12218
  @header X-Up-Fail-Context
12110
- @stable
12219
+ @experimental
12111
12220
  */
12112
12221
 
12113
12222
  /***
@@ -12425,10 +12534,12 @@ There are existing implementations for various web frameworks:
12425
12534
  Configures strings used in the optional [server protocol](/up.protocol).
12426
12535
 
12427
12536
  @property up.protocol.config
12537
+
12428
12538
  @param {string} [config.csrfHeader='X-CSRF-Token']
12429
12539
  The name of the HTTP header that will include the
12430
12540
  [CSRF token](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Synchronizer_token_pattern)
12431
12541
  for AJAX requests.
12542
+
12432
12543
  @param {string|Function(): string} [config.csrfParam]
12433
12544
  The `name` of the hidden `<input>` used for sending a
12434
12545
  [CSRF token](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Synchronizer_token_pattern) when
@@ -12440,7 +12551,10 @@ There are existing implementations for various web frameworks:
12440
12551
 
12441
12552
  Defaults to the `content` attribute of a `<meta>` tag named `csrf-param`:
12442
12553
 
12443
- <meta name="csrf-param" content="authenticity_token" />
12554
+ ```html
12555
+ <meta name="csrf-param" content="authenticity_token" />
12556
+ ```
12557
+
12444
12558
  @param {string|Function(): string} [config.csrfToken]
12445
12559
  The [CSRF token](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Synchronizer_token_pattern)
12446
12560
  to send for unsafe requests. The token will be sent as either a HTTP header (for AJAX requests)
@@ -12451,7 +12565,10 @@ There are existing implementations for various web frameworks:
12451
12565
 
12452
12566
  Defaults to the `content` attribute of a `<meta>` tag named `csrf-token`:
12453
12567
 
12454
- <meta name='csrf-token' content='secret12345'>
12568
+ ```
12569
+ <meta name='csrf-token' content='secret12345'>
12570
+ ```
12571
+
12455
12572
  @param {string} [config.methodParam='_method']
12456
12573
  The name of request parameter containing the original request method when Unpoly needs to wrap
12457
12574
  the method.
@@ -12559,11 +12676,14 @@ You can activate logging by calling [`up.log.enable()`](/up.log.enable).
12559
12676
  Debugging information includes which elements are being [compiled](/up.syntax)
12560
12677
  and which [events](/up.event) are being emitted.
12561
12678
  Note that errors will always be printed, regardless of this setting.
12562
- @internal
12679
+ @param {boolean} [options.banner=true]
12680
+ Print the Unpoly banner to the developer console.
12681
+ @stable
12563
12682
  */
12564
12683
  config = new up.Config(function() {
12565
12684
  return {
12566
- enabled: sessionStore.get('enabled')
12685
+ enabled: sessionStore.get('enabled'),
12686
+ banner: true
12567
12687
  };
12568
12688
  });
12569
12689
  reset = function() {
@@ -12621,6 +12741,9 @@ You can activate logging by calling [`up.log.enable()`](/up.log.enable).
12621
12741
  };
12622
12742
  printBanner = function() {
12623
12743
  var color, logo, text;
12744
+ if (!config.banner) {
12745
+ return;
12746
+ }
12624
12747
  logo = " __ _____ ___ ___ / /_ __\n" + ("/ // / _ \\/ _ \\/ _ \\/ / // / " + up.version + "\n") + "\\___/_//_/ .__/\\___/_/\\_. / \n" + " / / / /\n\n";
12625
12748
  text = "";
12626
12749
  if (!up.migrate.loaded) {
@@ -12638,7 +12761,7 @@ You can activate logging by calling [`up.log.enable()`](/up.log.enable).
12638
12761
  return console.log(logo + text);
12639
12762
  }
12640
12763
  };
12641
- up.on('up:framework:boot', printBanner);
12764
+ up.on('up:app:boot', printBanner);
12642
12765
  up.on('up:framework:reset', reset);
12643
12766
  setEnabled = function(value) {
12644
12767
  sessionStore.set('enabled', value);
@@ -12756,20 +12879,11 @@ You can activate logging by calling [`up.log.enable()`](/up.log.enable).
12756
12879
  Custom JavaScript
12757
12880
  =================
12758
12881
 
12759
- Every app needs a way to pair JavaScript snippets with certain HTML elements,
12760
- in order to integrate libraries or implement custom behavior.
12761
-
12762
- Unpoly lets you organize your JavaScript snippets using [compilers](/up.compiler).
12763
-
12764
- For instance, to activate the [Masonry](http://masonry.desandro.com/) library for every element
12765
- with a `grid` class, use this compiler:
12766
-
12767
- up.compiler('.grid', function(element) {
12768
- new Masonry(element, { itemSelector: '.grid--item' })
12769
- })
12882
+ The `up.syntax` package lets you pair HTML elements with JavaScript behavior.
12770
12883
 
12771
- The compiler function will be called on matching elements when the page loads
12772
- or when a matching fragment is [inserted via AJAX](/up.link) later.
12884
+ @see up.compiler
12885
+ @see [up-data]
12886
+ @see up.macro
12773
12887
 
12774
12888
  @module up.syntax
12775
12889
  */
@@ -12804,14 +12918,17 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
12804
12918
  Use compilers to activate your custom Javascript behavior on matching
12805
12919
  elements.
12806
12920
 
12807
- You should migrate your [`DOMContentLoaded`](https://api.jquery.com/ready/)
12921
+ You should migrate your [`DOMContentLoaded`](https://developer.mozilla.org/en-US/docs/Web/API/Window/DOMContentLoaded_event)
12808
12922
  callbacks to compilers. This will make sure they run both at page load and
12809
12923
  when a new fragment is inserted later.
12810
- It will also organize your JavaScript snippets by selector of affected elements.
12924
+ See [Making JavaScripts work with fragment updates](/legacy-scripts) for advice
12925
+ on migrating legacy scripts.
12926
+
12927
+ It will also organize your JavaScript snippets by selector.
12811
12928
 
12812
12929
  \#\#\# Example
12813
12930
 
12814
- This jQuery compiler will insert the current time into a
12931
+ This compiler will insert the current time into a
12815
12932
  `<div class='current-time'></div>`:
12816
12933
 
12817
12934
  ```js
@@ -12872,55 +12989,34 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
12872
12989
 
12873
12990
  An alternative way to register a destructor function is `up.destructor()`.
12874
12991
 
12875
- \#\#\# Attaching structured data
12876
-
12877
- In case you want to attach structured data to the event you're observing,
12878
- you can serialize the data to JSON and put it into an `[up-data]` attribute.
12879
- For instance, a container for a [Google Map](https://developers.google.com/maps/documentation/javascript/tutorial)
12880
- might attach the location and names of its marker pins:
12881
-
12882
- ```html
12883
- <div class='google-map' up-data='[
12884
- { "lat": 48.36, "lng": 10.99, "title": "Friedberg" },
12885
- { "lat": 48.75, "lng": 11.45, "title": "Ingolstadt" }
12886
- ]'></div>
12887
- ```
12992
+ \#\#\# Passing parameters to a compiler
12888
12993
 
12889
- The JSON will be parsed and handed to your compiler as a second argument:
12994
+ Use the `[up-data]` attribute to attach structured data to a DOM element.
12995
+ The data will be parsed and passed to your compiler function.
12890
12996
 
12891
- ```js
12892
- up.compiler('.google-map', function(element, pins) {
12893
- var map = new google.maps.Map(element)
12997
+ Alternatively your compiler may access attributes for the compiled element
12998
+ via the standard [`Element#getAttribute()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttribute)
12999
+ method.
12894
13000
 
12895
- pins.forEach(function(pin) {
12896
- var position = new google.maps.LatLng(pin.lat, pin.lng)
12897
- new google.maps.Marker({
12898
- position: position,
12899
- map: map,
12900
- title: pin.title
12901
- })
12902
- })
12903
- })
12904
- ```
13001
+ Unpoly also provides utility functions to read an element attribute and
13002
+ cast it to a given type:
12905
13003
 
12906
- @see legacy-scripts
13004
+ - `up.element.booleanAttr(element, attr)`
13005
+ - `up.element.numberAttr(element, attr)`
13006
+ - `up.element.jsonAttr(element, attr)`
12907
13007
 
12908
13008
  @function up.compiler
12909
13009
  @param {string} selector
12910
13010
  The selector to match.
12911
13011
  @param {number} [options.priority=0]
12912
13012
  The priority of this compiler.
13013
+
12913
13014
  Compilers with a higher priority are run first.
12914
13015
  Two compilers with the same priority are run in the order they were registered.
12915
13016
  @param {boolean} [options.batch=false]
12916
13017
  If set to `true` and a fragment insertion contains multiple
12917
- elements matching the selector, `compiler` is only called once
12918
- with a jQuery collection containing all matching elements.
12919
- @param {boolean} [options.keep=false]
12920
- If set to `true` compiled fragment will be [persisted](/up-keep) during
12921
- fragment updates.
12922
-
12923
- This has the same effect as setting an `up-keep` attribute on the element.
13018
+ elements matching `selector`, the `compiler` function is only called once
13019
+ with all these elements.
12924
13020
  @param {Function(element, data)} compiler
12925
13021
  The function to call when a matching element is inserted.
12926
13022
 
@@ -12957,10 +13053,12 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
12957
13053
  This jQuery compiler will insert the current time into a
12958
13054
  `<div class='current-time'></div>`:
12959
13055
 
12960
- up.$compiler('.current-time', function($element) {
12961
- var now = new Date()
12962
- $element.text(now.toString())
12963
- })
13056
+ ```js
13057
+ up.$compiler('.current-time', function($element) {
13058
+ var now = new Date()
13059
+ $element.text(now.toString())
13060
+ })
13061
+ ```
12964
13062
 
12965
13063
  @function up.$compiler
12966
13064
  @param {string} selector
@@ -12984,33 +13082,40 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
12984
13082
  /***
12985
13083
  Registers a [compiler](/up.compiler) that is run before all other compilers.
12986
13084
 
12987
- Use `up.macro()` to register a compiler that sets multiple Unpoly attributes.
13085
+ A macro lets you set UJS attributes that will be compiled afterwards.
13086
+
13087
+ If you want default attributes for *every* link and form, consider customizing your
13088
+ [navigation options](/navigation).
12988
13089
 
12989
13090
  \#\#\# Example
12990
13091
 
12991
13092
  You will sometimes find yourself setting the same combination of UJS attributes again and again:
12992
13093
 
12993
- <a href="/page1" up-target=".content" up-transition="cross-fade" up-duration="300">Page 1</a>
12994
- <a href="/page2" up-target=".content" up-transition="cross-fade" up-duration="300">Page 2</a>
12995
- <a href="/page3" up-target=".content" up-transition="cross-fade" up-duration="300">Page 3</a>
13094
+ ```html
13095
+ <a href="/page1" up-layer="new modal" up-class="warning" up-animation="shake">Page 1</a>
13096
+ <a href="/page1" up-layer="new modal" up-class="warning" up-animation="shake">Page 1</a>
13097
+ <a href="/page1" up-layer="new modal" up-class="warning" up-animation="shake">Page 1</a>
13098
+ ```
12996
13099
 
12997
- We would much rather define a new `[content-link]` attribute that let's us
13100
+ We would much rather define a new `[smooth-link]` attribute that let's us
12998
13101
  write the same links like this:
12999
13102
 
13000
- <a href="/page1" content-link>Page 1</a>
13001
- <a href="/page2" content-link>Page 2</a>
13002
- <a href="/page3" content-link>Page 3</a>
13103
+ ```html
13104
+ <a href="/page1" smooth-link>Page 1</a>
13105
+ <a href="/page2" smooth-link>Page 2</a>
13106
+ <a href="/page3" smooth-link>Page 3</a>
13107
+ ```
13003
13108
 
13004
13109
  We can define the `[content-link]` attribute by registering a macro that
13005
13110
  sets the `[up-target]`, `[up-transition]` and `[up-duration]` attributes for us:
13006
13111
 
13007
- up.macro('[content-link]', function(link) {
13008
- link.setAttribute('up-target', '.content')
13009
- link.setAttribute('up-transition', 'cross-fade')
13010
- link.setAttribute('up-duration', '300')
13011
- })
13012
-
13013
- Examples for built-in macros are [`a[up-dash]`](/a-up-dash) and [`[up-expand]`](/up-expand).
13112
+ ```
13113
+ up.macro('[smooth-link]', function(link) {
13114
+ link.setAttribute('up-target', '.content')
13115
+ link.setAttribute('up-transition', 'cross-fade')
13116
+ link.setAttribute('up-duration', '300')
13117
+ })
13118
+ ```
13014
13119
 
13015
13120
  @function up.macro
13016
13121
  @param {string} selector
@@ -13043,13 +13148,15 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
13043
13148
 
13044
13149
  \#\#\# Example
13045
13150
 
13046
- up.$macro('[content-link]', function($link) {
13047
- $link.attr(
13048
- 'up-target': '.content',
13049
- 'up-transition': 'cross-fade',
13050
- 'up-duration':'300'
13051
- )
13052
- })
13151
+ ```js
13152
+ up.$macro('[content-link]', function($link) {
13153
+ $link.attr(
13154
+ 'up-target': '.content',
13155
+ 'up-transition': 'cross-fade',
13156
+ 'up-duration':'300'
13157
+ )
13158
+ })
13159
+ ```
13053
13160
 
13054
13161
  @function up.$macro
13055
13162
  @param {string} selector
@@ -13111,6 +13218,7 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
13111
13218
 
13112
13219
  /***
13113
13220
  Applies all compilers on the given element and its descendants.
13221
+
13114
13222
  Unlike [`up.hello()`](/up.hello), this doesn't emit any events.
13115
13223
 
13116
13224
  @function up.syntax.compile
@@ -13139,8 +13247,8 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
13139
13247
  })
13140
13248
  ```
13141
13249
 
13142
- An alternative way to register a destructor function is to `return`
13143
- it from your compiler function.
13250
+ An alternative way to register a destructor function is to
13251
+ [`return` it from your compiler function](/up.compiler#cleaning-up-after-yourself).
13144
13252
 
13145
13253
  @function up.destructor
13146
13254
  @param {Element} element
@@ -13164,6 +13272,7 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
13164
13272
 
13165
13273
  /***
13166
13274
  Runs any destructor on the given fragment and its descendants in the same layer.
13275
+
13167
13276
  Unlike [`up.destroy()`](/up.destroy), this does not emit any events
13168
13277
  and does not remove the element from the DOM.
13169
13278
 
@@ -13182,20 +13291,23 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
13182
13291
  };
13183
13292
 
13184
13293
  /***
13185
- Checks if the given element has an [`up-data`](/up-data) attribute.
13186
- If yes, parses the attribute value as JSON and returns the parsed object.
13294
+ Returns the given element's `[up-data]`, parsed as a JavaScript object.
13187
13295
 
13188
- Returns `undefined` if the element has no `up-data` attribute.
13296
+ Returns `undefined` if the element has no `[up-data]` attribute.
13189
13297
 
13190
13298
  \#\#\# Example
13191
13299
 
13192
13300
  You have an element with JSON data serialized into an `up-data` attribute:
13193
13301
 
13194
- <span class='person' up-data='{ "age": 18, "name": "Bob" }'>Bob</span>
13302
+ ```html
13303
+ <span class='person' up-data='{ "age": 18, "name": "Bob" }'>Bob</span>
13304
+ ```
13195
13305
 
13196
13306
  Calling `up.syntax.data()` will deserialize the JSON string into a JavaScript object:
13197
13307
 
13198
- up.syntax.data('.person') // returns { age: 18, name: 'Bob' }
13308
+ ```js
13309
+ up.syntax.data('.person') // returns { age: 18, name: 'Bob' }
13310
+ ```
13199
13311
 
13200
13312
  @function up.data
13201
13313
  @param {string|Element|jQuery} element
@@ -13208,39 +13320,49 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
13208
13320
  */
13209
13321
 
13210
13322
  /***
13211
- If an element with an `up-data` attribute enters the DOM,
13323
+ Attaches structured data to an element, to be consumed by a compiler.
13324
+
13325
+ If an element with an `[up-data]` attribute enters the DOM,
13212
13326
  Unpoly will parse the JSON and pass the resulting object to any matching
13213
- [`up.compiler()`](/up.compiler) handlers.
13327
+ [`up.compiler()`](/up.compiler) functions.
13328
+
13329
+ \#\#\# Example
13214
13330
 
13215
13331
  For instance, a container for a [Google Map](https://developers.google.com/maps/documentation/javascript/tutorial)
13216
13332
  might attach the location and names of its marker pins:
13217
13333
 
13218
- <div class='google-map' up-data='[
13219
- { "lat": 48.36, "lng": 10.99, "title": "Friedberg" },
13220
- { "lat": 48.75, "lng": 11.45, "title": "Ingolstadt" }
13221
- ]'></div>
13334
+ ```html
13335
+ <div class='google-map' up-data='[
13336
+ { "lat": 48.36, "lng": 10.99, "title": "Friedberg" },
13337
+ { "lat": 48.75, "lng": 11.45, "title": "Ingolstadt" }
13338
+ ]'></div>
13339
+ ```
13222
13340
 
13223
13341
  The JSON will be parsed and handed to your compiler as a second argument:
13224
13342
 
13225
- up.compiler('.google-map', function(element, pins) {
13226
- var map = new google.maps.Map(element)
13227
- pins.forEach(function(pin) {
13228
- var position = new google.maps.LatLng(pin.lat, pin.lng)
13229
- new google.maps.Marker({
13230
- position: position,
13231
- map: map,
13232
- title: pin.title
13233
- })
13234
- })
13343
+ ```js
13344
+ up.compiler('.google-map', function(element, pins) {
13345
+ var map = new google.maps.Map(element)
13346
+ pins.forEach(function(pin) {
13347
+ var position = new google.maps.LatLng(pin.lat, pin.lng)
13348
+ new google.maps.Marker({
13349
+ position: position,
13350
+ map: map,
13351
+ title: pin.title
13235
13352
  })
13353
+ })
13354
+ })
13355
+ ```
13236
13356
 
13237
13357
  Similarly, when an event is triggered on an element annotated with
13238
13358
  [`up-data`], the parsed object will be passed to any matching
13239
13359
  [`up.on()`](/up.on) handlers.
13240
13360
 
13241
- up.on('click', '.google-map', function(event, element, pins) {
13242
- console.log("There are %d pins on the clicked map", pins.length)
13243
- })
13361
+ ```js
13362
+ up.on('click', '.google-map', function(event, element, pins) {
13363
+ console.log("There are %d pins on the clicked map", pins.length)
13364
+ })
13365
+ ```
13244
13366
 
13245
13367
  @selector [up-data]
13246
13368
  @param up-data
@@ -13297,6 +13419,9 @@ In an Unpoly app, every page has an URL.
13297
13419
 
13298
13420
  [Fragment updates](/up.link) automatically update the URL.
13299
13421
 
13422
+ @see up.history.location
13423
+ @see up:location:changed
13424
+
13300
13425
  @module up.history
13301
13426
  */
13302
13427
 
@@ -13536,9 +13661,11 @@ In an Unpoly app, every page has an URL.
13536
13661
  register = function() {
13537
13662
  window.history.scrollRestoration = 'manual';
13538
13663
  window.addEventListener('popstate', pop);
13539
- return replace(currentLocation(), {
13540
- event: false
13541
- });
13664
+ if (up.protocol.initialRequestMethod() === 'GET') {
13665
+ return replace(currentLocation(), {
13666
+ event: false
13667
+ });
13668
+ }
13542
13669
  };
13543
13670
  if (typeof jasmine !== "undefined" && jasmine !== null) {
13544
13671
  return register();
@@ -13601,31 +13728,48 @@ In an Unpoly app, every page has an URL.
13601
13728
  })();
13602
13729
 
13603
13730
  }).call(this);
13731
+ (function() {
13732
+ var e, u,
13733
+ slice = [].slice;
13604
13734
 
13605
- /***
13606
- Fragment update API
13607
- ===================
13608
-
13609
- The `up.fragment` module exposes a high-level Javascript API to [update](/up.replace) or
13610
- [destroy](/up.destroy) page fragments.
13611
-
13612
- Fragments are [compiled](/up.compiler) elements that can be updated from a server URL.
13613
- They also exist on a layer (page, modal, popup).
13735
+ u = up.util;
13614
13736
 
13615
- Most of Unpoly's functionality (like [fragment links](/up.link) or [modals](/up.modal))
13616
- is built from `up.fragment` functions. You may use them to extend Unpoly from your
13617
- [custom Javascript](/up.syntax).
13737
+ e = up.element;
13618
13738
 
13619
- @module up.fragment
13620
- */
13621
13739
 
13622
- (function() {
13623
- var slice = [].slice;
13740
+ /***
13741
+ Fragment API
13742
+ ===========
13743
+
13744
+ The `up.fragment` module offers a high-level JavaScript API to work with DOM elements.
13745
+
13746
+ A fragment is an element with some additional properties that are useful in the context of
13747
+ a server-rendered web application:
13748
+
13749
+ - Fragments are [identified by a CSS selector](/up.fragment.toTarget), like a `.class` or `#id`.
13750
+ - Fragments are usually updated by a [link](/a-up-follow) for [form](/form-up-submits) that targets their selector.
13751
+ When the server renders HTML with a matching element, the fragment is swapped with a new version.
13752
+ - As fragments enter the page they are automatically [compiled](/up.compiler) to activate JavaScript behavior.
13753
+ - Fragment changes may be [animated](/up.motion).
13754
+ - Fragments are placed on a [layer](/up.layer) that is isolated from other layers.
13755
+ Unpoly functions will only see or change fragments from the [current layer](/up.layer.current)
13756
+ unless you [explicitly target another layer](/layer-option).
13757
+ - Fragments [know the URL from where they were loaded](/up.source).
13758
+ They can be [reloaded](/up.reload) or [polled periodically](/up-polled).
13759
+
13760
+ For low-level DOM utilities that complement the browser's native API, see `up.element`.
13761
+
13762
+ @see up.render
13763
+ @see up.navigate
13764
+ @see up.destroy
13765
+ @see up.reload
13766
+ @see up.fragment.get
13767
+ @see up.hello
13768
+
13769
+ @module up.fragment
13770
+ */
13624
13771
 
13625
13772
  up.fragment = (function() {
13626
- var CSS_HAS_SUFFIX_PATTERN, closest, config, contains, destroy, e, emitFragmentDestroyed, emitFragmentInserted, emitFragmentKeep, emitFragmentKept, emitFromKeepPlan, expandTargets, failKey, getAll, getDumb, getSmart, getSubtree, hasAutoHistory, hello, isDestroying, isGoodClassForTarget, isNotDestroying, markFragmentAsDestroying, matches, navigate, parseSelector, parseTargetAndOptions, reload, render, renderLocalContent, renderRemoteContent, reset, resolveOriginReference, sourceOf, successKey, timeOf, toTarget, u, visit;
13627
- u = up.util;
13628
- e = up.element;
13629
13773
 
13630
13774
  /***
13631
13775
  Configures defaults for fragment updates.
@@ -13699,6 +13843,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
13699
13843
 
13700
13844
  @stable
13701
13845
  */
13846
+ var CSS_HAS_SUFFIX_PATTERN, closest, config, contains, destroy, emitFragmentDestroyed, emitFragmentInserted, emitFragmentKeep, emitFragmentKept, emitFromKeepPlan, expandTargets, failKey, getAll, getDumb, getSmart, getSubtree, hasAutoHistory, hello, isDestroying, isGoodClassForTarget, isNotDestroying, markFragmentAsDestroying, matches, navigate, parseSelector, parseTargetAndOptions, reload, render, renderLocalContent, renderRemoteContent, reset, resolveOriginReference, sourceOf, successKey, timeOf, toTarget, visit;
13702
13847
  config = new up.Config(function() {
13703
13848
  return {
13704
13849
  badTargetClasses: [/^up-/],
@@ -13719,13 +13864,8 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
13719
13864
  autoScroll: ['hash', 'layer-if-main']
13720
13865
  };
13721
13866
  });
13722
- Object.defineProperty(config, 'mainTargets', {
13723
- get: function() {
13724
- return up.layer.config.any.mainTargets;
13725
- },
13726
- set: function(value) {
13727
- return up.layer.config.any.mainTargets = value;
13728
- }
13867
+ u.delegate(config, 'mainTargets', function() {
13868
+ return up.layer.config.any;
13729
13869
  });
13730
13870
  reset = function() {
13731
13871
  return config.reset();
@@ -13779,6 +13919,74 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
13779
13919
  return e.closestAttr(element, 'up-time') || '0';
13780
13920
  };
13781
13921
 
13922
+ /***
13923
+ Sets the time when the fragment's underlying data was last changed.
13924
+
13925
+ This can be used to avoid rendering unchanged HTML when [reloading](/up.reload)
13926
+ a fragment. This saves <b>CPU time</b> and reduces the <b>bandwidth cost</b> for a
13927
+ request/response exchange to **~1 KB**.
13928
+
13929
+ \#\# Example
13930
+
13931
+ Let's say we display a list of recent messages.
13932
+ We use the `[up-poll]` attribute to reload the `.messages` fragment every 30 seconds:
13933
+
13934
+ ```html
13935
+ <div class="messages" up-poll>
13936
+ ...
13937
+ </div>
13938
+ ```
13939
+
13940
+ The list is now always up to date. But most of the time there will not be new messages,
13941
+ and we waste resources sending the same unchanged HTML from the server.
13942
+
13943
+ We can improve this by setting an `[up-time]` attribute and the message list.
13944
+ The attribute value is the time of the most recent message.
13945
+
13946
+ The time is encoded as the number of seconds since [Unix epoch](https://en.wikipedia.org/wiki/Unix_time).
13947
+ When, for instance, the last message in a list was received from December 24th, 1:51:46 PM UTC,
13948
+ we use the following HTML:
13949
+
13950
+ ```html
13951
+ <div class="messages" up-time="1608730818" up-poll>
13952
+ ...
13953
+ </div>
13954
+ ```
13955
+
13956
+ When reloading Unpoly will echo the `[up-time]` timestamp in an `X-Up-Reload-From-Time` header:
13957
+
13958
+ ```http
13959
+ X-Up-Reload-From-Time: 1608730818
13960
+ ```
13961
+
13962
+ The server can compare the time from the request with the time of the last data update.
13963
+ If no more recent data is available, the server can render nothing and respond with
13964
+ an [`X-Up-Target: :none`](/X-Up-Target) header.
13965
+
13966
+ Here is an example with [unpoly-rails](https://unpoly.com/install/rails):
13967
+
13968
+ ```ruby
13969
+ class MessagesController < ApplicationController
13970
+
13971
+ def index
13972
+ if up.reload_from_time == current_user.last_message_at
13973
+ up.render_nothing
13974
+ else
13975
+ @messages = current_user.messages.order(time: :desc).to_a
13976
+ render 'index'
13977
+ end
13978
+ end
13979
+
13980
+ end
13981
+ ```
13982
+
13983
+ @selector [up-time]
13984
+ @param {string} up-time
13985
+ The number of seconds between the [Unix epoch](https://en.wikipedia.org/wiki/Unix_time).
13986
+ and the time when the element's underlying data was last changed.
13987
+ @experimental
13988
+ */
13989
+
13782
13990
  /***
13783
13991
  Sets this element's source URL for [reloading](/up.reload) and [polling](/up-poll)
13784
13992
 
@@ -13800,7 +14008,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
13800
14008
  </div>
13801
14009
 
13802
14010
  @selector [up-source]
13803
- @param {String} up-source
14011
+ @param {string} up-source
13804
14012
  The URL from which to reload this element.
13805
14013
  @stable
13806
14014
  */
@@ -13978,7 +14186,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
13978
14186
  If set to `false`, the history will remain unchanged.
13979
14187
 
13980
14188
  [Overlays](/up.layer) will only change the browser URL and window title if the overlay
13981
- has [visible history](/up.layer.historyVisible), even with `{ history: true }`.
14189
+ has [visible history](/up.layer.historyVisible), even when `{ history: true }` is passed.
13982
14190
 
13983
14191
  @param {string} [options.title]
13984
14192
  An explicit document title to use after rendering.
@@ -14058,7 +14266,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
14058
14266
  This is only relevant when updating a layer that is not the [frontmost layer](/up.layer.front).
14059
14267
 
14060
14268
  @param {Object} [options.context]
14061
- An object that will be merged into the [context](/up.context) of the current layer once the fragment is rendered.
14269
+ An object that will be merged into the [context](/context) of the current layer once the fragment is rendered.
14062
14270
 
14063
14271
  @param {boolean} [options.keep=true]
14064
14272
  Whether [`[up-keep]`](/up-keep) elements will be preserved in the updated fragment.
@@ -14601,7 +14809,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
14601
14809
  - The [`up.element.all()`](/up.element.get) function simply returns the all elements matching a selector
14602
14810
  without further filtering.
14603
14811
 
14604
- @function up.fragment.get
14812
+ @function up.fragment.all
14605
14813
 
14606
14814
  @param {Element|jQuery} [root=document]
14607
14815
  The root element for the search. Only the root's children will be matched.
@@ -14836,7 +15044,8 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
14836
15044
 
14837
15045
  \#\#\# Skipping updates when nothing changed
14838
15046
 
14839
- TODO: Document [up-time] and X-Up-Reload-From-Time (currently both documented in `X-Up-Reload-From-Time`).
15047
+ You may use the `[up-time]` attribute to avoid rendering unchanged HTML when reloading
15048
+ a fragment. See `[up-time]` for a detailed example.
14840
15049
 
14841
15050
  @function up.reload
14842
15051
  @param {string|Element|jQuery} [target]
@@ -14918,7 +15127,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
14918
15127
  element.className = 'klass'
14919
15128
  selector = up.fragment.toTarget(element) // returns '.klass'
14920
15129
 
14921
- @function up.element.toTarget
15130
+ @function up.fragment.toTarget
14922
15131
  @param {string|Element|jQuery}
14923
15132
  The element for which to create a selector.
14924
15133
  @stable
@@ -14941,7 +15150,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
14941
15150
  selector = '';
14942
15151
  for (i = 0, len = goodClasses.length; i < len; i++) {
14943
15152
  klass = goodClasses[i];
14944
- selector += "." + klass;
15153
+ selector += e.classSelector(klass);
14945
15154
  }
14946
15155
  return selector;
14947
15156
  } else {
@@ -15133,8 +15342,10 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
15133
15342
 
15134
15343
  \#\#\# Shorthand
15135
15344
 
15136
- Instead of `:origin` you may also use `&`
15137
- ([like in Sass](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector)).
15345
+ Instead of `:origin` you may also use the ampersand character (`&`).
15346
+
15347
+ You may be familiar with the ampersand from the [Sass](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector)
15348
+ CSS preprocessor.
15138
15349
 
15139
15350
  @selector :origin
15140
15351
  @experimental
@@ -15245,36 +15456,39 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
15245
15456
 
15246
15457
  up.visit = up.fragment.visit;
15247
15458
 
15459
+
15460
+ /***
15461
+ Returns the current [context](/context).
15462
+
15463
+ This is aliased as `up.layer.context`.
15464
+
15465
+ @property up.context
15466
+ @param {Object} context
15467
+ The context object.
15468
+
15469
+ If no context has been set an empty object is returned.
15470
+ @experimental
15471
+ */
15472
+
15473
+ u.delegate(up, 'context', function() {
15474
+ return up.layer.current;
15475
+ });
15476
+
15248
15477
  }).call(this);
15249
15478
 
15250
15479
  /***
15251
15480
  Scrolling viewports
15252
15481
  ===================
15253
15482
 
15254
- The `up.viewport` module controls the scroll position of scrollable containers ("viewports").
15483
+ The `up.viewport` module controls the scroll position and focus within scrollable containers ("viewports").
15255
15484
 
15256
15485
  The default viewport for any web application is the main document. An application may
15257
15486
  define additional viewports by giving the CSS property `{ overflow-y: scroll }` to any `<div>`.
15258
15487
 
15488
+ Also see documentation for the [scroll option](/scroll-option) and [focus option](focus-option).
15259
15489
 
15260
- \#\#\# Revealing new content
15261
-
15262
- When following a [link to a fragment](/a-up-follow) Unpoly will automatically
15263
- scroll the document's viewport to [reveal](/up.viewport) the updated content.
15264
-
15265
- You should [make Unpoly aware](/up.viewport.config#config.fixedTop) of fixed elements in your
15266
- layout, such as navigation bars or headers. Unpoly will respect these sticky
15267
- elements when [revealing updated fragments](/up.reveal).
15268
-
15269
- You should also [tell Unpoly](/up.viewport.config#config.viewportSelectors) when your application has more than one viewport,
15270
- so Unpoly can pick the right viewport to scroll for each fragment update.
15271
-
15272
-
15273
- \#\#\# Bootstrap integration
15274
-
15275
- When using Bootstrap integration (`unpoly-bootstrap3.js` and `unpoly-bootstrap3.css`)
15276
- Unpoly will automatically be aware of sticky Bootstrap components such as
15277
- [fixed navbar](https://getbootstrap.com/examples/navbar-fixed-top/).
15490
+ @see up.reveal
15491
+ @see [up-fixed=top]
15278
15492
 
15279
15493
  @module up.viewport
15280
15494
  */
@@ -15283,29 +15497,31 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
15283
15497
  var slice = [].slice;
15284
15498
 
15285
15499
  up.viewport = (function() {
15286
- var absolutize, allSelector, anchoredRight, autofocus, closest, config, doFocus, e, f, firstHashTarget, fixedElements, getAll, getAround, getRoot, getScrollTops, getSubtree, isNativelyFocusable, isRoot, makeFocusable, parseOptions, pureHash, reset, resetScroll, restoreScroll, reveal, revealHash, rootHasReducedWidthFromScrollbar, rootHeight, rootOverflowElement, rootSelector, rootWidth, saveScroll, scroll, scrollTopKey, scrollTops, scrollbarWidth, scrollingController, setScrollTops, tryFocus, u, userScrolled, wasChosenAsOverflowingElement;
15500
+ var absolutize, allSelector, anchoredRight, closest, config, doFocus, e, f, firstHashTarget, fixedElements, getAll, getAround, getRoot, getScrollTops, getSubtree, isNativelyFocusable, isRoot, makeFocusable, parseOptions, pureHash, reset, resetScroll, restoreScroll, reveal, revealHash, rootHasReducedWidthFromScrollbar, rootHeight, rootOverflowElement, rootSelector, rootWidth, saveScroll, scroll, scrollTopKey, scrollTops, scrollbarWidth, scrollingController, setScrollTops, tryFocus, u, userScrolled, wasChosenAsOverflowingElement;
15287
15501
  u = up.util;
15288
15502
  e = up.element;
15289
15503
  f = up.fragment;
15290
15504
 
15291
15505
  /***
15292
- Configures the application layout.
15506
+ Configures defaults for scrolling.
15293
15507
 
15294
15508
  @property up.viewport.config
15295
15509
  @param {Array} [config.viewportSelectors]
15296
- An array of CSS selectors that find viewports
15297
- (containers that scroll their contents).
15510
+ An array of CSS selectors that match viewports.
15298
15511
  @param {Array} [config.fixedTop]
15299
15512
  An array of CSS selectors that find elements fixed to the
15300
15513
  top edge of the screen (using `position: fixed`).
15514
+
15301
15515
  See [`[up-fixed="top"]`](/up-fixed-top) for details.
15302
15516
  @param {Array} [config.fixedBottom]
15303
- An array of CSS selectors that find elements fixed to the
15517
+ An array of CSS selectors that match elements fixed to the
15304
15518
  bottom edge of the screen (using `position: fixed`).
15519
+
15305
15520
  See [`[up-fixed="bottom"]`](/up-fixed-bottom) for details.
15306
15521
  @param {Array} [config.anchoredRight]
15307
15522
  An array of CSS selectors that find elements anchored to the
15308
15523
  right edge of the screen (using `right:0` with `position: fixed` or `position: absolute`).
15524
+
15309
15525
  See [`[up-anchored="right"]`](/up-anchored-right) for details.
15310
15526
  @param {number} [config.revealSnap]
15311
15527
  When [revealing](/up.reveal) elements, Unpoly will scroll an viewport
@@ -15419,19 +15635,9 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
15419
15635
  };
15420
15636
 
15421
15637
  /***
15422
- Scroll's the given element's viewport so the first rows of the
15638
+ Scrolls the given element's viewport so the first rows of the
15423
15639
  element are visible for the user.
15424
15640
 
15425
- \#\#\# How Unpoly finds the viewport
15426
-
15427
- The viewport (the container that is going to be scrolled)
15428
- is the closest parent of the element that is either:
15429
-
15430
- - the currently open [modal](/up.modal)
15431
- - an element with the attribute `[up-viewport]`
15432
- - the `<body>` element
15433
- - an element matching the selector you have configured using `up.viewport.config.viewportSelectors.push('my-custom-selector')`
15434
-
15435
15641
  \#\#\# Fixed elements obstructing the viewport
15436
15642
 
15437
15643
  Many applications have a navigation bar fixed to the top or bottom,
@@ -15439,14 +15645,16 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
15439
15645
 
15440
15646
  You can make `up.reveal()` aware of these fixed elements
15441
15647
  so it can scroll the viewport far enough so the revealed element is fully visible.
15442
- To make `up.reveal()` aware fixed elements you can either:
15648
+ To make `up.reveal()` aware of fixed elements you can either:
15443
15649
 
15444
15650
  - give the element an attribute [`up-fixed="top"`](/up-fixed-top) or [`up-fixed="bottom"`](up-fixed-bottom)
15445
15651
  - [configure default options](/up.viewport.config) for `fixedTop` or `fixedBottom`
15446
15652
 
15447
15653
  @function up.reveal
15654
+
15448
15655
  @param {string|Element|jQuery} element
15449
15656
  The element to reveal.
15657
+
15450
15658
  @param {number} [options.scrollSpeed=1]
15451
15659
  The speed of the scrolling motion when scrolling with `{ behavior: 'smooth' }`.
15452
15660
 
@@ -15454,6 +15662,7 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
15454
15662
  [native smooth scrolling](https://developer.mozilla.org/en-US/docs/Web/API/ScrollToOptions/behavior).
15455
15663
 
15456
15664
  Defaults to `up.viewport.config.scrollSpeed`.
15665
+
15457
15666
  @param {string} [options.revealSnap]
15458
15667
  When the the revealed element would be closer to the viewport's top edge
15459
15668
  than this value, Unpoly will scroll the viewport to the top.
@@ -15461,35 +15670,40 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
15461
15670
  Set to `0` to disable snapping.
15462
15671
 
15463
15672
  Defaults to `up.viewport.config.revealSnap`.
15673
+
15464
15674
  @param {string|Element|jQuery} [options.viewport]
15465
15675
  The scrolling element to scroll.
15466
15676
 
15467
15677
  Defaults to the [given element's viewport](/up.viewport.closest).
15678
+
15468
15679
  @param {boolean} [options.top]
15469
15680
  Whether to scroll the viewport so that the first element row aligns
15470
15681
  with the top edge of the viewport.
15471
15682
 
15472
15683
  Defaults to `up.viewport.config.revealTop`.
15684
+
15473
15685
  @param {string}[options.behavior='auto']
15474
15686
  When set to `'auto'`, this will immediately scroll to the new position.
15475
15687
 
15476
15688
  When set to `'smooth'`, this will scroll smoothly to the new position.
15689
+
15477
15690
  @param {number}[options.speed]
15478
15691
  The speed of the scrolling motion when scrolling with `{ behavior: 'smooth' }`.
15479
15692
 
15480
15693
  Defaults to `up.viewport.config.scrollSpeed`.
15694
+
15481
15695
  @param {number} [options.padding]
15482
15696
  The desired padding between the revealed element and the
15483
15697
  closest [viewport](/up.viewport) edge (in pixels).
15484
15698
 
15485
15699
  Defaults to `up.viewport.config.revealPadding`.
15700
+
15486
15701
  @param {number|boolean} [options.snap]
15487
15702
  Whether to snap to the top of the viewport if the new scroll position
15488
15703
  after revealing the element is close to the top edge.
15489
15704
 
15490
15705
  Defaults to `up.viewport.config.revealSnap`.
15491
- @param {boolean} [options.peel=true]
15492
- Whether to close overlays obscuring the layer of `element`.
15706
+
15493
15707
  @return {Promise}
15494
15708
  A promise that fulfills when the element is revealed.
15495
15709
 
@@ -15498,13 +15712,12 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
15498
15712
 
15499
15713
  When the scrolling is not animated, the promise will fulfill
15500
15714
  in the next [microtask](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/).
15715
+
15501
15716
  @stable
15502
15717
  */
15503
15718
  reveal = function(element, options) {
15504
15719
  var motion;
15505
- options = u.options(options, {
15506
- peel: true
15507
- });
15720
+ options = u.options(options);
15508
15721
  element = f.get(element, options);
15509
15722
  if (!(options.layer = up.layer.get(element))) {
15510
15723
  return up.error.failed.async('Cannot reveal a detached element');
@@ -15517,7 +15730,19 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
15517
15730
  };
15518
15731
 
15519
15732
  /***
15520
- TODO: Docs
15733
+ Focuses the given element.
15734
+
15735
+ Focusing an element will also [reveal](/up.reveal) it, unless `{ preventScroll: true }` is passed.
15736
+
15737
+ @function up.focus
15738
+
15739
+ @param {string|Element|jQuery} element
15740
+ The element to focus.
15741
+
15742
+ @param {[options.preventScroll=false]}
15743
+ Whether to prevent changes to the acroll position.
15744
+
15745
+ @experimental
15521
15746
  */
15522
15747
  doFocus = function(element, options) {
15523
15748
  var oldScrollTop, viewport;
@@ -15542,13 +15767,6 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
15542
15767
  doFocus(element, options);
15543
15768
  return element === document.activeElement;
15544
15769
  };
15545
- autofocus = function(element, options) {
15546
- var autofocusElement;
15547
- if (autofocusElement = e.subtree(element, '[autofocus]')[0]) {
15548
- doDocus(autofocusElement, options);
15549
- return true;
15550
- }
15551
- };
15552
15770
  isNativelyFocusable = function(element) {
15553
15771
  return e.matches(element, 'a[href], button, textarea, input, select');
15554
15772
  };
@@ -15618,6 +15836,9 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
15618
15836
  Returns a list of all the viewports contained within the
15619
15837
  given selector or element.
15620
15838
 
15839
+ If the given element is itself a viewport, the element is included
15840
+ in the returned list.
15841
+
15621
15842
  @function up.viewport.subtree
15622
15843
  @param {string|Element|jQuery} target
15623
15844
  @param {Object} options
@@ -15810,30 +16031,11 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
15810
16031
 
15811
16032
  The scroll positions will be associated with the current URL.
15812
16033
  They can later be restored by calling [`up.viewport.restoreScroll()`](/up.viewport.restoreScroll)
15813
- at the same URL, or by following a link with an [`[up-restore-scroll]`](/a-up-follow#up-restore-scroll)
16034
+ at the same URL, or by following a link with an [`[scroll="restore"]`](/a-up-follow#up-restore-scroll)
15814
16035
  attribute.
15815
16036
 
15816
- Unpoly automatically saves scroll positions before a [fragment update](/up.replace)
15817
- you will rarely need to call this function yourself.
15818
-
15819
- \#\#\# Examples
15820
-
15821
- Should you need to save the current scroll positions outside of a [fragment update](/up.replace),
15822
- you may call:
15823
-
15824
- up.viewport.saveScroll()
15825
-
15826
- Instead of saving the current scroll positions for the current URL, you may also pass another
15827
- url or vertical scroll positionsfor each viewport:
15828
-
15829
- up.viewport.saveScroll({
15830
- url: '/inbox',
15831
- tops: {
15832
- 'body': 0,
15833
- '.sidebar', 100,
15834
- '.main', 320
15835
- }
15836
- })
16037
+ Unpoly automatically saves scroll positions before [navigating](/navigation).
16038
+ You will rarely need to call this function yourself.
15837
16039
 
15838
16040
  @function up.viewport.saveScroll
15839
16041
  @param {string} [options.location]
@@ -16160,7 +16362,6 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
16160
16362
  absolutize: absolutize,
16161
16363
  focus: doFocus,
16162
16364
  tryFocus: tryFocus,
16163
- autofocus: autofocus,
16164
16365
  makeFocusable: makeFocusable
16165
16366
  });
16166
16367
  })();
@@ -16204,12 +16405,17 @@ and [predefined animations](/up.animate#named-animations).
16204
16405
  You can define custom animations using `up.transition()` and
16205
16406
  `up.animation()`.
16206
16407
 
16408
+ @see up.animation
16409
+ @see up.animate
16410
+ @see up.transition
16411
+ @see up.morph
16412
+
16207
16413
  @module up.motion
16208
16414
  */
16209
16415
 
16210
16416
  (function() {
16211
16417
  up.motion = (function() {
16212
- var animCount, animate, animateNow, applyConfig, composeTransitionFn, config, e, findAnimationFn, findNamedAnimation, findTransitionFn, finish, isEnabled, isNone, morph, motionController, namedAnimations, namedTransitions, pickDefault, registerAnimation, registerMoveMotions, registerOpacityAnimation, registerTransition, reset, skipAnimate, swapElementsDirectly, translateCSS, u, untranslatedBox, warnIfDisabled, willAnimate;
16418
+ var animate, animateNow, applyConfig, composeTransitionFn, config, e, findAnimationFn, findNamedAnimation, findTransitionFn, finish, isEnabled, isNone, morph, motionController, namedAnimations, namedTransitions, pickDefault, registerAnimation, registerMoveMotions, registerOpacityAnimation, registerTransition, reset, skipAnimate, swapElementsDirectly, translateCSS, u, untranslatedBox, warnIfDisabled, willAnimate;
16213
16419
  u = up.util;
16214
16420
  e = up.element;
16215
16421
  namedAnimations = {};
@@ -16342,7 +16548,6 @@ You can define custom animations using `up.transition()` and
16342
16548
  var animationFn, runNow, willRun;
16343
16549
  element = up.fragment.get(element);
16344
16550
  options = u.options(options);
16345
- applyConfig(options);
16346
16551
  animationFn = findAnimationFn(animation);
16347
16552
  willRun = willAnimate(element, animation, options);
16348
16553
  if (willRun) {
@@ -16355,6 +16560,7 @@ You can define custom animations using `up.transition()` and
16355
16560
  }
16356
16561
  };
16357
16562
  willAnimate = function(element, animationOrTransition, options) {
16563
+ applyConfig(options);
16358
16564
  return isEnabled() && !isNone(animationOrTransition) && options.duration > 0 && !e.isSingleton(element);
16359
16565
  };
16360
16566
  skipAnimate = function(element, animation) {
@@ -16363,7 +16569,6 @@ You can define custom animations using `up.transition()` and
16363
16569
  }
16364
16570
  return Promise.resolve();
16365
16571
  };
16366
- animCount = 0;
16367
16572
 
16368
16573
  /***
16369
16574
  Animates the given element's CSS properties using CSS transitions.
@@ -16669,7 +16874,7 @@ You can define custom animations using `up.transition()` and
16669
16874
  If you choose to *not* use `up.animate()` and roll your own
16670
16875
  animation code instead, your code must honor the following contract:
16671
16876
 
16672
- 1. It must honor the options `{ duration, easing }` if given
16877
+ 1. It must honor the options `{ duration, easing }`, if given.
16673
16878
  2. It must *not* remove any of the given elements from the DOM.
16674
16879
  3. It returns a promise that is fulfilled when the transition has ended
16675
16880
  4. If during the animation an event `up:motion:finish` is emitted on
@@ -16892,7 +17097,11 @@ You can define custom animations using `up.transition()` and
16892
17097
  - [Instantaneous feedback for links that are currently loading](/a.up-active)
16893
17098
  - [Follow links on `mousedown` instead of `click`](/a-up-instant)
16894
17099
 
16895
- @module up.request
17100
+ @see up.request
17101
+ @see up.Request
17102
+ @see up.Response
17103
+
17104
+ @module up.network
16896
17105
  */
16897
17106
 
16898
17107
  up.network = (function() {
@@ -17620,15 +17829,30 @@ You can define custom animations using `up.transition()` and
17620
17829
  Layers
17621
17830
  ======
17622
17831
 
17623
- TODO
17832
+ Unpoly allows you to [open page fragments in an overlay](/opening-overlays). Overlays may be stacked infinitely.
17833
+
17834
+ A variety of [overlay modes](/layer-terminology) are supported,
17835
+ such as modal dialogs, popup overlays or drawers. You may [customize their appearance and behavior](/customizing-overlays).
17836
+
17837
+ Layers are isolated, meaning a screen in one layer will not accidentally see elements
17838
+ or events from another layer. For instance, [fragment links](/up.link) will only update elements from the [current layer](/up.layer.current)
17839
+ unless you [explicitly target another layer](/layer-option).
17840
+
17841
+ Overlays allow you to break up a complex screen into [subinteractions](/subinteractions).
17842
+ Subinteractions take place in overlays and may span one or many pages. The original screen remains open in the background.
17843
+ Once the subinteraction is *done*, the overlay is closed and a result value is communicated back to the parent layer.
17844
+
17845
+ @see a[up-layer=new]
17846
+ @see up.layer.current
17847
+ @see up.layer.on
17848
+ @see up.layer.ask
17624
17849
 
17625
17850
  @module up.layer
17626
17851
  */
17627
17852
 
17628
17853
  up.layer = (function() {
17629
- var LAYER_CLASSES, OVERLAY_CLASSES, OVERLAY_MODES, anySelector, api, ask, build, closeCallbackAttr, config, handlers, isOverlayMode, mainTargets, modeConfigs, normalizeOptions, open, openCallbackAttr, optionToString, reset, stack;
17854
+ var LAYER_CLASSES, OVERLAY_CLASSES, anySelector, api, ask, build, closeCallbackAttr, config, handlers, mainTargets, modeConfigs, normalizeOptions, open, openCallbackAttr, optionToString, reset, stack;
17630
17855
  OVERLAY_CLASSES = [up.Layer.Modal, up.Layer.Popup, up.Layer.Drawer, up.Layer.Cover];
17631
- OVERLAY_MODES = u.map(OVERLAY_CLASSES, 'mode');
17632
17856
  LAYER_CLASSES = [up.Layer.Root].concat(OVERLAY_CLASSES);
17633
17857
 
17634
17858
  /***
@@ -17826,16 +18050,17 @@ You can define custom animations using `up.transition()` and
17826
18050
  });
17827
18051
 
17828
18052
  /***
17829
- TODO: Docs
18053
+ A list of layers that are currently open.
18054
+
18055
+ The first element in the list is the [root layer](/up.layer.root).
18056
+ The last element is the [frontmost layer](/up.layer.front).
17830
18057
 
17831
- @function up.layer.stack
18058
+ @property up.layer.stack
18059
+ @param {List<up.Layer>} stack
17832
18060
  @stable
17833
18061
  */
17834
18062
  stack = null;
17835
18063
  handlers = [];
17836
- isOverlayMode = function(mode) {
17837
- return u.contains(OVERLAY_MODES, mode);
17838
- };
17839
18064
  mainTargets = function(mode) {
17840
18065
  return u.flatMap(modeConfigs(mode), 'mainTargets');
17841
18066
  };
@@ -17959,7 +18184,7 @@ You can define custom animations using `up.transition()` and
17959
18184
  How the overlay may be [dismissed](/closing-overlays) by the user.
17960
18185
 
17961
18186
  Supported values are `'key'`, `'outside'` and `'button'`.
17962
- See [user dismiss controls](/closing-overlays#user-facing-dismiss-controls)
18187
+ See [customizing dismiss controls](/closing-overlays#customizing-dismiss-controls)
17963
18188
  for details.
17964
18189
 
17965
18190
  You may enable multiple dismiss controls by passing an array or
@@ -18072,13 +18297,38 @@ You can define custom animations using `up.transition()` and
18072
18297
  };
18073
18298
 
18074
18299
  /***
18075
- TODO: Docs
18076
- TODO: Document that listeners may manipulate options
18077
- TODO: Document that it's emitted on the document
18300
+ This event is emitted before an overlay is opened.
18301
+
18302
+ The overlay is not yet part of the [layer stack](/up.layer.stack) and has not yet been placed
18303
+ in the DOM. Listeners may prevent this event to prevent the overlay from opening.
18304
+
18305
+ The event is emitted on the `document`.
18306
+
18307
+ \#\#\# Changing layer options
18308
+
18309
+ Listeners may inspect and manipulate options for the overlay that is about to open.
18310
+
18311
+ For example, to give overlays the CSS class `.warning` if the initial URL contains
18312
+ the word `"confirm"`:
18313
+
18314
+ ```js
18315
+ up.on('up:layer:open', function(event) {
18316
+ if (event.layerOptions.url.includes('confirm')) {
18317
+ event.layerOptions.class = 'warning'
18318
+ }
18319
+ })
18320
+ ```
18078
18321
 
18079
18322
  @event up:layer:open
18080
18323
  @param {Object} event.layerOptions
18324
+ Options for the overlay that is about to open.
18325
+
18326
+ Listeners may inspect and change the options.
18327
+ All options for `up.layer.open()` may be used.
18081
18328
  @param {Element} event.origin
18329
+ The link element that is opening the overlay.
18330
+ @param event.preventDefault()
18331
+ Event listeners may call this method to prevent the overlay from opening.
18082
18332
  @stable
18083
18333
  */
18084
18334
 
@@ -18208,7 +18458,7 @@ You can define custom animations using `up.transition()` and
18208
18458
  @param [up-dismissable]
18209
18459
  How the overlay may be [dismissed](/closing-overlays) by the user.
18210
18460
 
18211
- See [user dismiss controls](/closing-overlays#user-facing-dismiss-controls)
18461
+ See [customizing dismiss controls](/closing-overlays#customizing-dismiss-controls)
18212
18462
  for details.
18213
18463
 
18214
18464
  You may enable multiple dismiss controls by passing a space-separated string.
@@ -18465,7 +18715,7 @@ You can define custom animations using `up.transition()` and
18465
18715
 
18466
18716
  If no overlay is open, an empty array is returned.
18467
18717
 
18468
- @function up.layer.overlays
18718
+ @property up.layer.overlays
18469
18719
  @param {Array<up.Layer>} overlays
18470
18720
  @stable
18471
18721
  */
@@ -18490,9 +18740,9 @@ You can define custom animations using `up.transition()` and
18490
18740
  Afterwards the only remaining layer will be the [root layer](/up.layer.root).
18491
18741
 
18492
18742
  @function up.layer.dismissOverlays
18493
- @param {any} value
18743
+ @param {any} [value]
18494
18744
  The dismissal value.
18495
- @param {Object} options
18745
+ @param {Object} [options]
18496
18746
  See options for `up.layer.dismiss()`.
18497
18747
  @stable
18498
18748
  */
@@ -18558,7 +18808,7 @@ You can define custom animations using `up.transition()` and
18558
18808
  */
18559
18809
 
18560
18810
  /***
18561
- Listens to a ([DOM event](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Events)
18811
+ Listens to a [DOM event](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Events)
18562
18812
  that originated on an element [contained](/up.Layer.prototype.contains) by the [current layer](/up.layer.current).
18563
18813
 
18564
18814
  This is a shortcut for `up.layer.current.on()`.
@@ -18638,23 +18888,35 @@ You can define custom animations using `up.transition()` and
18638
18888
  @param {string} location
18639
18889
  @stable
18640
18890
  */
18891
+
18892
+ /***
18893
+ The [current layer](/up.layer.current)'s mode which governs its appearance and behavior.
18894
+
18895
+ @see layer-terminology
18896
+
18897
+ @property up.layer.mode
18898
+ @param {string} mode
18899
+ @stable
18900
+ */
18901
+
18902
+ /***
18903
+ The [context](/context) of the [current layer](/up.layer.current).
18904
+
18905
+ This is aliased as `up.context`.
18906
+
18907
+ @property up.layer.context
18908
+ @param {string} context
18909
+ The context object.
18910
+
18911
+ If no context has been set an empty object is returned.
18912
+ @experimental
18913
+ */
18641
18914
  u.delegate(api, ['accept', 'dismiss', 'isRoot', 'isOverlay', 'isFront', 'on', 'off', 'emit', 'parent', 'historyVisible', 'location', 'mode', 'context', 'element', 'contains', 'size', 'affix'], function() {
18642
18915
  return stack.current;
18643
18916
  });
18644
18917
  return api;
18645
18918
  })();
18646
18919
 
18647
-
18648
- /***
18649
- TODO: Docs
18650
- @property up.context
18651
- @pram {Object} context
18652
- */
18653
-
18654
- u.getter(up, 'context', function() {
18655
- return up.layer.context;
18656
- });
18657
-
18658
18920
  }).call(this);
18659
18921
 
18660
18922
  /***
@@ -18727,6 +18989,11 @@ With these [`up-target`](/a-up-follow#up-target) annotations Unpoly only updates
18727
18989
  The JavaScript environment will persist and the user will not see a white flash while the
18728
18990
  new page is loading.
18729
18991
 
18992
+ @see a[up-follow]
18993
+ @see a[up-instant]
18994
+ @see a[up-preload]
18995
+ @see up.follow
18996
+
18730
18997
  @module up.link
18731
18998
  */
18732
18999
 
@@ -18835,7 +19102,7 @@ new page is loading.
18835
19102
  config = new up.Config(function() {
18836
19103
  return {
18837
19104
  followSelectors: combineFollowableSelectors(LINKS_WITH_REMOTE_HTML, ATTRIBUTES_SUGGESTING_FOLLOW).concat(LINKS_WITH_LOCAL_HTML),
18838
- noFollowSelectors: ['[up-follow=false]', 'a[rel=download]', 'a[target]', 'a[href^="#"]:not([up-content]):not([up-fragment]):not([up-document])', 'a[href^="javascript:"]'],
19105
+ noFollowSelectors: ['[up-follow=false]', 'a[download]', 'a[target]', 'a[href^="#"]:not([up-content]):not([up-fragment]):not([up-document])', 'a[href^="javascript:"]'],
18839
19106
  instantSelectors: ['[up-instant]'],
18840
19107
  noInstantSelectors: ['[up-instant=false]', '[onclick]'],
18841
19108
  preloadSelectors: combineFollowableSelectors(LINKS_WITH_REMOTE_HTML, ['[up-preload]']),
@@ -18898,8 +19165,7 @@ new page is loading.
18898
19165
  };
18899
19166
 
18900
19167
  /***
18901
- Fetches the given link's `[href]` with JavaScript and [replaces](/up.replace) the
18902
- [current layer](/up.layer.current) with HTML from the response.
19168
+ Follows the given link with JavaScript and updates a fragment with the server response.
18903
19169
 
18904
19170
  By default the layer's [main element](/main)
18905
19171
  will be replaced. Attributes like `a[up-target]`
@@ -19043,7 +19309,20 @@ new page is loading.
19043
19309
 
19044
19310
  The event is emitted on the `<a>` element that is being followed.
19045
19311
 
19046
- TODO: Document that listeners may manipulate options
19312
+ \#\#\# Changing render options
19313
+
19314
+ Listeners may inspect and manipulate [render options](/up.render) for the coming fragment update.
19315
+
19316
+ The code below will open all form-contained links in an overlay, as to not
19317
+ lose the user's form data:
19318
+
19319
+ ```js
19320
+ up.on('up:link:follow', function(event, link) {
19321
+ if (link.closest('form')) {
19322
+ event.renderOptions.layer = 'new'
19323
+ }
19324
+ })
19325
+ ```
19047
19326
 
19048
19327
  @event up:link:follow
19049
19328
  @param {Element} event.target
@@ -19347,8 +19626,7 @@ new page is loading.
19347
19626
  };
19348
19627
 
19349
19628
  /***
19350
- [Follows](/up.follow) this link with JavaScript and replaces a CSS selector
19351
- on the current page with a corresponding element from the response.
19629
+ [Follows](/up.follow) this link with JavaScript and updates a fragment with the server response.
19352
19630
 
19353
19631
  Following a link is considered [navigation](/navigation) by default.
19354
19632
 
@@ -19377,7 +19655,7 @@ new page is loading.
19377
19655
  - `[up-transition]`
19378
19656
  - `[up-content]`
19379
19657
  - `[up-fragment]`
19380
- - `[up-document]'
19658
+ - `[up-document]`
19381
19659
 
19382
19660
  Such a link will still be followed through Unpoly.
19383
19661
 
@@ -19484,7 +19762,7 @@ new page is loading.
19484
19762
  If set to `false`, the history will remain unchanged.
19485
19763
 
19486
19764
  [Overlays](/up.layer) will only change the browser URL and window title if the overlay
19487
- has [visible history](/up.layer.historyVisible), even with `{ history: true }`.
19765
+ has [visible history](/up.layer.historyVisible), even when `[up-history=true]` is set.
19488
19766
 
19489
19767
  @param [up-title]
19490
19768
  An explicit document title to use after rendering.
@@ -19559,7 +19837,7 @@ new page is loading.
19559
19837
  This is only relevant when updating a layer that is not the [frontmost layer](/up.layer.front).
19560
19838
 
19561
19839
  @param [up-context]
19562
- A JSON object that will be merged into the [context](/up.context)
19840
+ A JSON object that will be merged into the [context](/context)
19563
19841
  of the current layer once the fragment is rendered.
19564
19842
 
19565
19843
  @param [up-keep='true']
@@ -19614,12 +19892,7 @@ new page is loading.
19614
19892
  });
19615
19893
 
19616
19894
  /***
19617
- TODO: Explain that this generates an up:click event, works on any elements, can can be used to accelerate links
19618
-
19619
- By adding an `up-instant` attribute to a link, the destination will be
19620
- fetched on `mousedown` instead of `click` (`mouseup`).
19621
-
19622
- <a href="/users" up-follow up-instant>User list</a>
19895
+ Follows this link on `mousedown` instead of `click`.
19623
19896
 
19624
19897
  This will save precious milliseconds that otherwise spent
19625
19898
  on waiting for the user to release the mouse button. Since an
@@ -19631,6 +19904,10 @@ new page is loading.
19631
19904
  navigation actions this isn't needed. E.g. popular operation
19632
19905
  systems switch tabs on `mousedown` instead of `click`.
19633
19906
 
19907
+ \#\#\# Example
19908
+
19909
+ <a href="/users" up-follow up-instant>User list</a>
19910
+
19634
19911
  \#\#\# Accessibility
19635
19912
 
19636
19913
  If the user activates an element using their keyboard, the `up:click` event will be emitted
@@ -19729,11 +20006,9 @@ new page is loading.
19729
20006
  });
19730
20007
 
19731
20008
  /***
19732
- Links with an `up-preload` attribute will silently fetch their target
19733
- when the user hovers over the click area, or when the user puts her
19734
- mouse/finger down (before releasing).
20009
+ Preloads this link when the user hovers over it.
19735
20010
 
19736
- When the link is clicked later, the response will already be cached,
20011
+ When the link is clicked later the response will already be cached,
19737
20012
  making the interaction feel instant.
19738
20013
 
19739
20014
  @selector a[up-preload]
@@ -19776,9 +20051,12 @@ new page is loading.
19776
20051
  Forms
19777
20052
  =====
19778
20053
 
19779
- Unpoly comes with functionality to [submit](/form-up-submit) and [validate](/input-up-validate)
19780
- forms without leaving the current page. This means you can replace page fragments,
19781
- open dialogs with sub-forms, etc. all without losing form state.
20054
+ The `up.form` module helps you work with non-trivial forms.
20055
+
20056
+ @see form[up-submit]
20057
+ @see form[up-validate]
20058
+ @see input[up-switch]
20059
+ @see form[up-autosubmit]
19782
20060
 
19783
20061
  @module up.form
19784
20062
  */
@@ -20025,7 +20303,6 @@ open dialogs with sub-forms, etc. all without losing form state.
20025
20303
  The `<form>` element that will be submitted.
20026
20304
  @param {Object} event.renderOptions
20027
20305
  An object with [render options](/up.render) for the fragment update
20028
- that will show the validation results.
20029
20306
 
20030
20307
  Listeners may inspect and modify these options.
20031
20308
  @param event.preventDefault()
@@ -20336,18 +20613,21 @@ open dialogs with sub-forms, etc. all without losing form state.
20336
20613
  };
20337
20614
 
20338
20615
  /***
20339
- Forms with an `up-target` attribute are [submitted via AJAX](/up.submit)
20340
- instead of triggering a full page reload.
20341
-
20342
- <form method="post" action="/users" up-target=".main">
20343
- ...
20344
- </form>
20616
+ Submits this form via JavaScript and updates a fragment with the server response.
20345
20617
 
20346
20618
  The server response is searched for the selector given in `up-target`.
20347
20619
  The selector content is then [replaced](/up.replace) in the current page.
20348
20620
 
20349
20621
  The programmatic variant of this is the [`up.submit()`](/up.submit) function.
20350
20622
 
20623
+ \#\#\# Example
20624
+
20625
+ ```html
20626
+ <form method="post" action="/users" up-submit>
20627
+ ...
20628
+ </form>
20629
+ ```
20630
+
20351
20631
  \#\#\# Failed submission
20352
20632
 
20353
20633
  When the server was unable to save the form due to invalid params,
@@ -20567,11 +20847,13 @@ open dialogs with sub-forms, etc. all without losing form state.
20567
20847
  */
20568
20848
 
20569
20849
  /***
20570
- Performs [server-side validation](/input-up-validate) when any fieldset within this form changes.
20850
+ Validates this form on the server when any field changes and shows validation errors.
20571
20851
 
20572
20852
  You can configure what Unpoly considers a fieldset by adding CSS selectors to the
20573
20853
  `up.form.config.validateTargets` array.
20574
20854
 
20855
+ See `input[up-validate]` for detailed documentation.
20856
+
20575
20857
  @selector form[up-validate]
20576
20858
  @param up-validate
20577
20859
  The CSS selector to update with the server response.
@@ -20588,7 +20870,7 @@ open dialogs with sub-forms, etc. all without losing form state.
20588
20870
  });
20589
20871
 
20590
20872
  /***
20591
- Show or hide elements when a `<select>` or `<input>` has a given value.
20873
+ Show or hide elements when a form field is set to a given value.
20592
20874
 
20593
20875
  \#\#\# Example: Select options
20594
20876
 
@@ -20708,6 +20990,15 @@ open dialogs with sub-forms, etc. all without losing form state.
20708
20990
 
20709
20991
  <input name="query" up-observe="showSuggestions(value)">
20710
20992
 
20993
+ Note that the parameter name in the markup must be called `value` or it will not work.
20994
+ The parameter name can be called whatever you want in the JavaScript, however.
20995
+
20996
+ Also note that the function must be declared on the `window` object to work, like so:
20997
+
20998
+ window.showSuggestions = function(selectedValue) {
20999
+ console.log(`Called showSuggestions() with ${selectedValue}`);
21000
+ }
21001
+
20711
21002
  \#\#\# Callback context
20712
21003
 
20713
21004
  The script given to `[up-observe]` runs with the following context:
@@ -20817,7 +21108,7 @@ open dialogs with sub-forms, etc. all without losing form state.
20817
21108
  */
20818
21109
 
20819
21110
  /***
20820
- Submits the form when *any* field changes.
21111
+ Submits the form when any field changes.
20821
21112
 
20822
21113
  Both the form and the field will be assigned a CSS class [`up-active`](/form-up-active)
20823
21114
  while the autosubmitted form is loading.
@@ -20909,13 +21200,16 @@ Once the response is received the URL will change to `/bar` and the `up-active`
20909
21200
  <a href="/bar" up-follow class="up-current">Bar</a>
20910
21201
  </nav>
20911
21202
 
21203
+ @see [up-nav]
21204
+ @see a.up-current
21205
+ @see a.up-active
20912
21206
 
20913
21207
  @module up.feedback
20914
21208
  */
20915
21209
 
20916
21210
  (function() {
20917
21211
  up.feedback = (function() {
20918
- var CLASS_ACTIVE, SELECTOR_LINK, around, aroundForOptions, config, e, findActivatableArea, linkURLs, navSelector, normalizeURL, onBrowserLocationChanged, reset, start, stop, u, updateFragment, updateLayerIfLocationChanged, updateLinks, updateLinksWithinNavs;
21212
+ var CLASS_ACTIVE, SELECTOR_LINK, around, aroundForOptions, config, e, findActivatableArea, getLayerLocation, linkURLs, navSelector, normalizeURL, onBrowserLocationChanged, reset, start, stop, u, updateFragment, updateLayerIfLocationChanged, updateLinks, updateLinksWithinNavs;
20919
21213
  u = up.util;
20920
21214
  e = up.element;
20921
21215
 
@@ -20956,23 +21250,29 @@ Once the response is received the URL will change to `/bar` and the `up-active`
20956
21250
  linkURLs = function(link) {
20957
21251
  return link.upFeedbackURLs || (link.upFeedbackURLs = new up.LinkFeedbackURLs(link));
20958
21252
  };
20959
- updateFragment = function(fragment, options) {
20960
- var links;
20961
- if (e.closest(fragment, navSelector())) {
20962
- links = e.subtree(fragment, SELECTOR_LINK);
20963
- return updateLinks(links, options);
21253
+ updateFragment = function(fragment) {
21254
+ var layerOption, links;
21255
+ layerOption = {
21256
+ layer: up.layer.get(fragment)
21257
+ };
21258
+ if (up.fragment.closest(fragment, navSelector(), layerOption)) {
21259
+ links = up.fragment.subtree(fragment, SELECTOR_LINK, layerOption);
21260
+ return updateLinks(links, layerOption);
20964
21261
  } else {
20965
- return updateLinksWithinNavs(fragment, options);
21262
+ return updateLinksWithinNavs(fragment, layerOption);
20966
21263
  }
20967
21264
  };
20968
21265
  updateLinksWithinNavs = function(fragment, options) {
20969
21266
  var links, navs;
20970
- navs = e.subtree(fragment, navSelector());
21267
+ navs = up.fragment.subtree(fragment, navSelector(), options);
20971
21268
  links = u.flatMap(navs, function(nav) {
20972
21269
  return e.subtree(nav, SELECTOR_LINK);
20973
21270
  });
20974
21271
  return updateLinks(links, options);
20975
21272
  };
21273
+ getLayerLocation = function(layer) {
21274
+ return layer.feedbackLocation || layer.location;
21275
+ };
20976
21276
  updateLinks = function(links, options) {
20977
21277
  var layer, layerLocation;
20978
21278
  if (options == null) {
@@ -20982,7 +21282,7 @@ Once the response is received the URL will change to `/bar` and the `up-active`
20982
21282
  return;
20983
21283
  }
20984
21284
  layer = options.layer || up.layer.get(links[0]);
20985
- if (layerLocation = layer.feedbackLocation) {
21285
+ if (layerLocation = getLayerLocation(layer)) {
20986
21286
  return u.each(links, function(link) {
20987
21287
  var currentClass, i, isCurrent, len, ref;
20988
21288
  isCurrent = linkURLs(link).isCurrent(layerLocation);
@@ -21251,11 +21551,11 @@ Once the response is received the URL will change to `/bar` and the `up-active`
21251
21551
  return updateLayerIfLocationChanged(frontLayer);
21252
21552
  }
21253
21553
  };
21254
- up.on('up:location:changed', function(event) {
21554
+ up.on('up:location:changed', function(_event) {
21255
21555
  return onBrowserLocationChanged();
21256
21556
  });
21257
- up.on('up:fragment:inserted', function(event, newFragment) {
21258
- return updateFragment(newFragment, event);
21557
+ up.on('up:fragment:inserted', function(_event, newFragment) {
21558
+ return updateFragment(newFragment);
21259
21559
  });
21260
21560
  up.on('up:layer:location:changed', function(event) {
21261
21561
  return updateLayerIfLocationChanged(event.layer);
@@ -21277,8 +21577,10 @@ Once the response is received the URL will change to `/bar` and the `up-active`
21277
21577
  Passive updates
21278
21578
  ===============
21279
21579
 
21280
- This work-in-progress package will contain functionality to
21281
- passively receive updates from the server.
21580
+ This package contains functionality to passively receive updates from the server.
21581
+
21582
+ @see [up-hungry]
21583
+ @see [up-poll]
21282
21584
 
21283
21585
  @module up.radio
21284
21586
  */
@@ -21293,13 +21595,16 @@ passively receive updates from the server.
21293
21595
  Configures defaults for passive updates.
21294
21596
 
21295
21597
  @property up.radio.config
21598
+
21296
21599
  @param {Array<string>} [config.hungrySelectors]
21297
21600
  An array of CSS selectors that is replaced whenever a matching element is found in a response.
21298
21601
  These elements are replaced even when they were not targeted directly.
21299
21602
 
21300
21603
  By default this contains the [`[up-hungry]`](/up-hungry) attribute.
21604
+
21301
21605
  @param {number} [config.pollInterval=30000]
21302
21606
  The default [polling](/up-poll] interval in milliseconds.
21607
+
21303
21608
  @param {boolean|string|Function(Element)} [config.pollEnabled=true]
21304
21609
  Whether Unpoly will follow instructions to poll fragments, like the `[up-poll]` attribute.
21305
21610
 
@@ -21314,6 +21619,7 @@ passively receive updates from the server.
21314
21619
  When set to `false`, Unpoly will never allow polling.
21315
21620
 
21316
21621
  You may also pass a function that accepts the polling fragment and returns `true`, `false` or `'auto'`.
21622
+
21317
21623
  @stable
21318
21624
  */
21319
21625
  config = new up.Config(function() {
@@ -21336,9 +21642,8 @@ passively receive updates from the server.
21336
21642
  };
21337
21643
 
21338
21644
  /***
21339
- Elements with an `[up-hungry]` attribute are [updated](/up.replace) whenever there is a
21340
- matching element found in a successful response. The element is replaced even
21341
- when it isn't targeted directly.
21645
+ Elements with an `[up-hungry]` attribute are updated whenever the server
21646
+ sends a matching element, even if the element isn't targeted.
21342
21647
 
21343
21648
  Use cases for this are unread message counters or notification flashes.
21344
21649
  Such elements often live in the layout, outside of the content area that is
@@ -21430,21 +21735,27 @@ passively receive updates from the server.
21430
21735
  Assume an application layout with an unread message counter.
21431
21736
  You can use `[up-poll]` to refresh the counter every 30 seconds:
21432
21737
 
21433
- <div class="unread-count" up-poll>
21434
- 2 new messages
21435
- </div>
21738
+ ```html
21739
+ <div class="unread-count" up-poll>
21740
+ 2 new messages
21741
+ </div>
21742
+ ```
21436
21743
 
21437
21744
  \#\#\# Controlling the reload interval
21438
21745
 
21439
21746
  You may set an optional `[up-interval]` attribute to set the reload interval in milliseconds:
21440
21747
 
21441
- <div class="unread-count" up-poll up-interval="10000">
21442
- 2 new messages
21443
- </div>
21748
+ ```html
21749
+ <div class="unread-count" up-poll up-interval="10000">
21750
+ 2 new messages
21751
+ </div>
21752
+ ```
21444
21753
 
21445
21754
  If the value is omitted, a global default is used. You may configure the default like this:
21446
21755
 
21447
- up.radio.config.pollInterval = 10000
21756
+ ```js
21757
+ up.radio.config.pollInterval = 10000
21758
+ ```
21448
21759
 
21449
21760
  \#\#\# Controlling the source URL
21450
21761
 
@@ -21452,13 +21763,20 @@ passively receive updates from the server.
21452
21763
 
21453
21764
  To reload from another URL, set an `[up-source]` attribute on the polling element:
21454
21765
 
21455
- <div class="unread-count" up-poll up-source="/unread-count">
21456
- 2 new messages
21457
- </div>
21766
+ ```html
21767
+ <div class="unread-count" up-poll up-source="/unread-count">
21768
+ 2 new messages
21769
+ </div>
21770
+ ```
21458
21771
 
21459
21772
  \#\#\# Skipping updates when nothing changed
21460
21773
 
21461
- TODO: Document [up-time] and X-Up-Reload-From-Time (currently both documented in `X-Up-Reload-From-Time`).
21774
+ When polling a fragment periodically we want to avoid rendering unchanged content.
21775
+ This saves <b>CPU time</b> and reduces the <b>bandwidth cost</b> for a
21776
+ request/response exchange to **~1 KB**.
21777
+
21778
+ To achieve this we timestamp your fragments with an `[up-time]` attribute to indicate
21779
+ when the underlying data was last changed. See `[up-time]` for a detailed example.
21462
21780
 
21463
21781
  @selector [up-poll]
21464
21782
  @param [up-interval]