Skip to content

Commit 4906587

Browse files
authored
Fix website listings stacking update handlers on hash change (#15214)
Register each listing's update handler once Pages with several listings attached another list.on("updated") handler to every listing on each URL hash change, so a single update reran the same work several times. Each listing's inline script called the handler on DOMContentLoaded and again from its own hashchange listener. Wiring now runs once per listing id, and one hashchange listener in quarto-listing.js only applies the hash. - Wire each listing once, keyed by its id - Move hash handling into applyListingHash() - Replace the per-listing hashchange listeners with a single one - Pin hash, pagination, and update-handler behavior with tests The hashchange listener dates from #1139, and back/forward between categories still depends on it. Found while reviewing #9469. Fixes #15206
1 parent aad85b2 commit 4906587

12 files changed

Lines changed: 276 additions & 24 deletions

File tree

‎news/changelog-1.11.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ All changes included in 1.11:
142142
- ([#15091](https://github.com/quarto-dev/quarto-cli/pull/15091)): Fix page-level `bread-crumbs`, `back-to-top-navigation`, `page-navigation`, `margin-header` and `margin-footer` options not being validated or offered for completion in editors. A page value of the wrong type now fails to render with an error instead of being accepted silently.
143143
- ([#15091](https://github.com/quarto-dev/quarto-cli/pull/15091)): Fix `open-graph: false` or `twitter-card: false` in page front matter or `_metadata.yml` not disabling Open Graph or Twitter Card metadata for that page when the website enables it.
144144
- ([#15114](https://github.com/quarto-dev/quarto-cli/pull/15114)): Fix a website category containing backticks showing broken text in the page title block, and a category containing a backslash, such as a Windows path, failing the render or losing its backslashes.
145+
- ([#15206](https://github.com/quarto-dev/quarto-cli/issues/15206)): Fix website listings attaching another update handler on every URL hash change, and an extra one per additional listing on the same page.
145146

146147
## Lua API
147148

‎src/project/types/website/listing/website-listing-template.ts‎

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -575,12 +575,6 @@ export function templateJsScript(
575575
window['quarto-listing-loaded']();
576576
}
577577
});
578-
579-
window.addEventListener('hashchange',() => {
580-
if (window['quarto-listing-loaded']) {
581-
window['quarto-listing-loaded']();
582-
}
583-
})
584578
`;
585579
return jsScript;
586580
}

‎src/resources/projects/website/listing/quarto-listing.js‎

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,41 @@ window.quartoListingCategory = (category) => {
1010
}
1111
};
1212

13-
window["quarto-listing-loaded"] = () => {
14-
// Process any existing hash
13+
const wiredListings = new Set();
14+
15+
// Apply the category and per-listing page stored in the URL hash
16+
function applyListingHash() {
1517
const hash = getHash();
18+
if (!hash || !window["quarto-listings"]) {
19+
return;
20+
}
1621

17-
if (hash) {
18-
// If there is a category, switch to that
19-
if (hash.category) {
20-
// category hash are URI encoded so we need to decode it before processing
21-
// so that we can match it with the category element processed in JS
22-
activateCategory(decodeURIComponent(hash.category));
23-
}
24-
// Paginate a specific listing
25-
const listingIds = Object.keys(window["quarto-listings"]);
26-
for (const listingId of listingIds) {
27-
const page = hash[getListingPageKey(listingId)];
28-
if (page) {
29-
showPage(listingId, page);
30-
}
22+
// If there is a category, switch to that
23+
if (hash.category) {
24+
// category hash are URI encoded so we need to decode it before processing
25+
// so that we can match it with the category element processed in JS
26+
activateCategory(decodeURIComponent(hash.category));
27+
}
28+
// Paginate a specific listing
29+
for (const listingId of Object.keys(window["quarto-listings"])) {
30+
const page = hash[getListingPageKey(listingId)];
31+
if (page) {
32+
showPage(listingId, page);
3133
}
3234
}
35+
}
36+
37+
window["quarto-listing-loaded"] = () => {
38+
// Process any existing hash
39+
applyListingHash();
40+
41+
// Each listing calls this once its List is created, so wire each one once
42+
for (const listingId of Object.keys(window["quarto-listings"])) {
43+
if (wiredListings.has(listingId)) {
44+
continue;
45+
}
46+
wiredListings.add(listingId);
3347

34-
const listingIds = Object.keys(window["quarto-listings"]);
35-
for (const listingId of listingIds) {
3648
// The actual list
3749
const list = window["quarto-listings"][listingId];
3850

@@ -56,6 +68,8 @@ window["quarto-listing-loaded"] = () => {
5668
}
5769
};
5870

71+
window.addEventListener("hashchange", applyListingHash);
72+
5973
window.document.addEventListener("DOMContentLoaded", function (_event) {
6074
// Attach click handlers to categories
6175
const categoryEls = window.document.querySelectorAll(
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/.quarto/
2+
**/*.quarto_ipynb
3+
/_site/
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
project:
2+
type: website
3+
4+
website:
5+
title: "Listing update handlers"
6+
7+
format: html
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
title: "Two paginated listings"
3+
listing:
4+
- id: first-listing
5+
contents: posts
6+
type: default
7+
sort: "title asc"
8+
page-size: 1
9+
categories: true
10+
filter-ui: true
11+
- id: second-listing
12+
contents: posts
13+
type: default
14+
sort: "title asc"
15+
page-size: 1
16+
---
17+
18+
::: {#first-listing}
19+
:::
20+
21+
::: {#second-listing}
22+
:::
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
title: "Post 1"
3+
categories: [cat1]
4+
image: thumb.png
5+
---
6+
7+
Post 1 content.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
title: "Post 2"
3+
categories: [cat2]
4+
image: thumb.png
5+
---
6+
7+
Post 2 content.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
title: "Post 3"
3+
categories: [cat3]
4+
image: thumb.png
5+
---
6+
7+
Post 3 content.
70 Bytes
Loading

0 commit comments

Comments
 (0)