Skip to content

Commit 6598eb3

Browse files
feat: support f-partial on buttons (freshframework#1867)
1 parent 776a721 commit 6598eb3

5 files changed

Lines changed: 239 additions & 154 deletions

File tree

src/runtime/entrypoints/main.ts

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -556,14 +556,15 @@ function _walkInner(
556556

557557
const partialErrorMessage = `Unable to process partial response.`;
558558

559-
async function fetchPartials(url: URL, realUrl: URL, init?: RequestInit) {
559+
async function fetchPartials(url: URL, init?: RequestInit) {
560560
url.searchParams.set(PARTIAL_SEARCH_PARAM, "true");
561561
const res = await fetch(url, init);
562562
await applyPartials(res);
563+
}
563564

564-
// Update links
565+
function updateLinks(url: URL) {
565566
document.querySelectorAll("a").forEach((link) => {
566-
const match = matchesUrl(realUrl.pathname, link.href);
567+
const match = matchesUrl(url.pathname, link.href);
567568

568569
if (match === UrlMatchKind.Current) {
569570
link.setAttribute(DATA_CURRENT, "true");
@@ -884,6 +885,8 @@ if (!history.state) {
884885
document.addEventListener("click", async (e) => {
885886
let el = e.target;
886887
if (el && el instanceof HTMLElement) {
888+
const originalEl = el;
889+
887890
// Check if we clicked inside an anchor link
888891
if (el.nodeName !== "A") {
889892
el = el.closest("a");
@@ -947,13 +950,39 @@ document.addEventListener("click", async (e) => {
947950
partial ? partial : nextUrl.href,
948951
location.origin,
949952
);
950-
await fetchPartials(partialUrl, nextUrl);
953+
await fetchPartials(partialUrl);
954+
updateLinks(nextUrl);
951955
scrollTo({ left: 0, top: 0, behavior: "instant" });
952956
} finally {
953957
if (indicator !== undefined) {
954958
indicator.value = false;
955959
}
956960
}
961+
} else {
962+
let button: HTMLButtonElement | HTMLElement | null = originalEl;
963+
// Check if we clicked on a button
964+
if (button.nodeName !== "A") {
965+
button = button.closest("button");
966+
}
967+
968+
if (button !== null && button instanceof HTMLButtonElement) {
969+
const partial = button.getAttribute(PARTIAL_ATTR);
970+
971+
// Check if the user opted out of client side navigation.
972+
if (
973+
partial === null ||
974+
!checkClientNavEnabled() ||
975+
button.closest(`[${CLIENT_NAV_ATTR}="true"]`) === null
976+
) {
977+
return;
978+
}
979+
980+
const partialUrl = new URL(
981+
partial,
982+
location.origin,
983+
);
984+
await fetchPartials(partialUrl);
985+
}
957986
}
958987
}
959988
});
@@ -986,7 +1015,8 @@ addEventListener("popstate", async (e) => {
9861015

9871016
const url = new URL(location.href, location.origin);
9881017
try {
989-
await fetchPartials(url, url);
1018+
await fetchPartials(url);
1019+
updateLinks(url);
9901020
scrollTo({
9911021
left: state.scrollX ?? 0,
9921022
top: state.scrollY ?? 0,
@@ -1013,7 +1043,7 @@ document.addEventListener("submit", async (e) => {
10131043
e.preventDefault();
10141044

10151045
const url = new URL(partial, location.origin);
1016-
await fetchPartials(url, new URL(location.href));
1046+
await fetchPartials(url);
10171047
}
10181048
}
10191049
});

0 commit comments

Comments
 (0)