mirror of
https://github.com/bigskysoftware/htmx.git
synced 2025-09-29 22:11:22 +00:00
Experimental support for the [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API)
This commit is contained in:
parent
36780c034f
commit
fd87ffd516
35
src/htmx.js
35
src/htmx.js
@ -70,6 +70,7 @@ return (function () {
|
||||
scrollBehavior: 'smooth',
|
||||
defaultFocusScroll: false,
|
||||
getCacheBusterParam: false,
|
||||
globalViewTransitions: false,
|
||||
},
|
||||
parseInterval:parseInterval,
|
||||
_:internalEval,
|
||||
@ -2396,6 +2397,9 @@ return (function () {
|
||||
if (modifier.indexOf("settle:") === 0) {
|
||||
swapSpec["settleDelay"] = parseInterval(modifier.substr(7));
|
||||
}
|
||||
if (modifier.indexOf("transition:") === 0) {
|
||||
swapSpec["transition"] = modifier.substr(11) === "true";
|
||||
}
|
||||
if (modifier.indexOf("scroll:") === 0) {
|
||||
var scrollSpec = modifier.substr(7);
|
||||
var splitSpec = scrollSpec.split(":");
|
||||
@ -3127,9 +3131,13 @@ return (function () {
|
||||
var swapSpec = getSwapSpecification(elt, swapOverride);
|
||||
|
||||
target.classList.add(htmx.config.swappingClass);
|
||||
|
||||
// optional transition API promise callbacks
|
||||
var settleResolve = null;
|
||||
var settleReject = null;
|
||||
|
||||
var doSwap = function () {
|
||||
try {
|
||||
|
||||
var activeElt = document.activeElement;
|
||||
var selectionInfo = {};
|
||||
try {
|
||||
@ -3228,6 +3236,7 @@ return (function () {
|
||||
}
|
||||
handleTrigger(xhr, "HX-Trigger-After-Settle", finalElt);
|
||||
}
|
||||
maybeCall(settleResolve);
|
||||
}
|
||||
|
||||
if (swapSpec.settleDelay > 0) {
|
||||
@ -3237,10 +3246,34 @@ return (function () {
|
||||
}
|
||||
} catch (e) {
|
||||
triggerErrorEvent(elt, 'htmx:swapError', responseInfo);
|
||||
maybeCall(settleReject);
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
var shouldTransition = htmx.config.globalViewTransitions
|
||||
if(swapSpec.hasOwnProperty('transition')){
|
||||
shouldTransition = swapSpec.transition;
|
||||
}
|
||||
|
||||
if(shouldTransition &&
|
||||
triggerEvent(elt, 'htmx:beforeTransition', responseInfo) &&
|
||||
typeof Promise !== "undefined" && document.startViewTransition){
|
||||
var settlePromise = new Promise(function (_resolve, _reject) {
|
||||
settleResolve = _resolve;
|
||||
settleReject = _reject;
|
||||
});
|
||||
// wrap the original doSwap() in a call to startViewTransition()
|
||||
var innerDoSwap = doSwap;
|
||||
doSwap = function() {
|
||||
document.startViewTransition(function () {
|
||||
innerDoSwap();
|
||||
return settlePromise;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (swapSpec.swapDelay > 0) {
|
||||
setTimeout(doSwap, swapSpec.swapDelay)
|
||||
} else {
|
||||
|
@ -14,6 +14,36 @@
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<style>
|
||||
@keyframes fade-in {
|
||||
from { opacity: 0; }
|
||||
}
|
||||
|
||||
@keyframes fade-out {
|
||||
to { opacity: 0; }
|
||||
}
|
||||
|
||||
@keyframes slide-from-right {
|
||||
from { transform: translateX(30px); }
|
||||
}
|
||||
|
||||
@keyframes slide-to-left {
|
||||
to { transform: translateX(-30px); }
|
||||
}
|
||||
|
||||
::view-transition-old(root) {
|
||||
animation: 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
|
||||
300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
|
||||
}
|
||||
|
||||
::view-transition-new(root) {
|
||||
animation: 210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
|
||||
300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
|
||||
|
||||
</head>
|
||||
@ -48,6 +78,7 @@
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<h2>Server Options</h2>
|
||||
<button onclick="server.respond()">Server Respond</button>
|
||||
<br/>
|
||||
@ -62,12 +93,17 @@ Autorespond: <input id="autorespond" type="checkbox" onclick="toggleAutoRespond(
|
||||
</div>
|
||||
|
||||
<script>
|
||||
this.server.respondWith("GET", "/demo", 'demo response...');
|
||||
let requestCount = 0;
|
||||
this.server.respondWith("GET", "/demo", function(xhr){
|
||||
let randomStr = (Math.random() + 1).toString(36).substring(7);
|
||||
xhr.respond(200, {}, "Request #" + requestCount++ + " : " + randomStr)
|
||||
});
|
||||
</script>
|
||||
|
||||
<button>First</button>
|
||||
<input hx-get="/demo" hx-target="next output" hx-trigger="keyup changed" hx-on-before-request="alert('foo')"/>
|
||||
<output>--</output>
|
||||
<button hx-get="/demo"
|
||||
hx-target="next h1"
|
||||
hx-swap="innerHTML transition:true">Issue Request</button>
|
||||
<h1 id="h1">--</h1>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -35,6 +35,12 @@ The `div` will issue a request to `/example` and append the returned content aft
|
||||
|
||||
The `hx-swap` attributes supports modifiers for changing the behavior of the swap. They are outlined below.
|
||||
|
||||
#### Transition: `transition`
|
||||
|
||||
If you want to use the new (View Transitions)[https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API] API
|
||||
when a swap occurs, you can use the `transition:true` option for your swap. You can also enable this feature globally by
|
||||
setting the `htmx.config.globalViewTransitions` config setting to `true`.
|
||||
|
||||
#### Timing: `swap` & `settle`
|
||||
|
||||
You can modify the amount of time that htmx will wait after receiving a response to swap the content
|
||||
|
17
www/docs.md
17
www/docs.md
@ -417,6 +417,22 @@ The following extensions are available for morph-style swaps:
|
||||
* [Idiomorph](https://github.com/bigskysoftware/idiomorph#htmx) - A newer morphing algorithm developed by us, the creators
|
||||
of htmx. Idiomorph will be available out of the box in htmx 2.0.
|
||||
|
||||
#### <a name="view-transitions"></a> [View Transitions](#view-transitions)
|
||||
|
||||
The new, experimental [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API)
|
||||
gives developers a way to create an animated transition between different DOM states. It is still in active development
|
||||
and is not available in all browsers, but htmx provides a way to work with this new API that falls back to the non-transition
|
||||
mechanism if the API is not available in a given browser.
|
||||
|
||||
You can experiment with this new API using the following approaches:
|
||||
|
||||
* Set the `htmx.config.globalViewTransitions` config variable to `true` to use transitions for all swaps
|
||||
* Use the `transition:true` option in the `hx-swap` attribute
|
||||
* If an element swap is going to be transitioned due to either of the above configurations, you may catch the
|
||||
`htmx:beforeTransition` event and call `preventDefault()` on it to cancel the transition.
|
||||
|
||||
View Transitions can be configured using CSS, as outlined in [the Chrome documentation for the feature](https://developer.chrome.com/docs/web-platform/view-transitions/#simple-customization).
|
||||
|
||||
### <a name="synchronization"></a> [Synchronization](#synchronization)
|
||||
|
||||
Often you want to coordinate the requests between two elements. For example, you may want a request from one element
|
||||
@ -1402,6 +1418,7 @@ listed below:
|
||||
| `htmx.config.timeout` | defaults to 0 in milliseconds |
|
||||
| `htmx.config.defaultFocusScroll` | if the focused element should be scrolled into view, defaults to false and can be overridden using the [focus-scroll](/attributes/hx-swap/#focus-scroll) swap modifier. |
|
||||
| `htmx.config.getCacheBusterParam` | defaults to false, if set to true htmx will include a cache-busting parameter in `GET` requests to avoid caching partial responses by the browser |
|
||||
| `htmx.config.globalViewTransitions` | if set to `true`, htmx will use the [View Transition](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API) API when swapping in new content. |
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -134,6 +134,20 @@ the documentation on [configuring swapping](/docs#modifying_swapping_behavior_wi
|
||||
* `detail.shouldSwap` - if the content will be swapped (defaults to `false` for non-200 response codes)
|
||||
* `detail.target` - the target of the swap
|
||||
|
||||
### <a name="htmx:beforeTransition"></a> Event - [`htmx:beforeTransition`](#htmx:beforeTransition)
|
||||
|
||||
This event is triggered before a [View Transition](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API)
|
||||
wrapped swap occurs. If the event is cancelled, the View Transition will not occur and the normal swapping logic will
|
||||
happen instead.
|
||||
|
||||
##### Details
|
||||
|
||||
* `detail.elt` - the element that dispatched the request
|
||||
* `detail.xhr` - the `XMLHttpRequest`
|
||||
* `detail.requestConfig` - the configuration of the AJAX request
|
||||
* `detail.shouldSwap` - if the content will be swapped (defaults to `false` for non-200 response codes)
|
||||
* `detail.target` - the target of the swap
|
||||
|
||||
### <a name="htmx:configRequest"></a> Event - [`htmx:configRequest`](#htmx:configRequest)
|
||||
|
||||
This event is triggered after htmx has collected parameters for inclusion in the request. It can be
|
||||
|
Loading…
x
Reference in New Issue
Block a user