Skip to content

Commit bc4c34f

Browse files
committed
feat(pat-inject): Throw an event before history updates.
Throw an event before the history is updated and the URL bar changes and pass the original AJAX event along with it. This allows external code to do some updates, like changing data-base-url and data-view-url on the body, using the body information from the response for that. This is a use-case in Plone and allows JavaScript code to get information on the current context.
1 parent d078143 commit bc4c34f

File tree

3 files changed

+84
-0
lines changed

3 files changed

+84
-0
lines changed

src/pat/inject/documentation.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,5 +387,6 @@ pat-inject fires several JavaScript events which bubble up the DOM tree:
387387
| `pat-inject-content-loaded` | jQuery | images within injected content | true | Triggered on images within the injected content when those images are loaded. |
388388
| `pat-inject-missingSource` | jQuery | trigger which caused the injection | true | Triggered when no to-be-injected source could be found. |
389389
| `pat-inject-missingTarget` | jQuery | trigger which caused the injection | true | Triggered when no target could be found. |
390+
| `pat-inject-before-history-update` | JavaScript | document | true | Trigger just before the history is update, if `history: record` is set. |
390391

391392
Please note: `jQuery.trigger` events can be catched with jQuery only while JavaScript `dispatchEvent` events can be catched with bare JavaScript `addEventListener` and `jQuery.on`.

src/pat/inject/inject.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,10 @@ const inject = {
535535
// Base: update/add/remove as needed
536536
this._update_head(source_base, target_base, true);
537537

538+
document.dispatchEvent(
539+
new Event("pat-inject-before-history-update", { detail: { ajax_event: ev } })
540+
);
541+
538542
// At last position - other patterns can react on already changed title,
539543
// canonical or base.
540544
let url = cfg.url;

src/pat/inject/inject.test.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2780,6 +2780,85 @@ describe("pat-inject", function () {
27802780
expect(base).toBeTruthy();
27812781
expect(base.getAttribute("href")).toBe("/new/");
27822782
});
2783+
2784+
it("9.4.5 - Dispatches pat-inject-before-history-update event after head modifications but before history.pushState", async function () {
2785+
// Mock history.pushState to track when it's called
2786+
const original_push_state = history.pushState;
2787+
let push_state_called = false;
2788+
let event_dispatched = false;
2789+
let head_modified_when_event_fired = false;
2790+
2791+
history.pushState = function (...args) {
2792+
push_state_called = true;
2793+
return original_push_state.apply(this, args);
2794+
};
2795+
2796+
// Set up event listener to track when the event is dispatched
2797+
const event_handler = function (event) {
2798+
event_dispatched = true;
2799+
// Check if the head title has already been updated when the event fires
2800+
const title = document.head.querySelector("title");
2801+
head_modified_when_event_fired =
2802+
title && title.textContent.trim() === "new page";
2803+
// Ensure history.pushState hasn't been called yet
2804+
expect(push_state_called).toBe(false);
2805+
// Check that event is fired on document
2806+
expect(event.target).toBe(document);
2807+
expect(event.type).toBe("pat-inject-before-history-update");
2808+
};
2809+
document.addEventListener(
2810+
"pat-inject-before-history-update",
2811+
event_handler
2812+
);
2813+
2814+
document.head.innerHTML = `
2815+
<title>old title</title>
2816+
`;
2817+
document.body.innerHTML = `
2818+
<a class="pat-inject"
2819+
href="test.html"
2820+
data-pat-inject="
2821+
source: body;
2822+
target: body;
2823+
history: record;
2824+
">link</a>
2825+
`;
2826+
2827+
answer(`
2828+
<html>
2829+
<head>
2830+
<title>new page</title>
2831+
</head>
2832+
<body>
2833+
New content
2834+
</body>
2835+
</html>
2836+
`);
2837+
2838+
const inject = document.querySelector(".pat-inject");
2839+
2840+
pattern.init($(inject));
2841+
await utils.timeout(1);
2842+
2843+
inject.click();
2844+
await utils.timeout(1);
2845+
2846+
// Cleanup
2847+
document.removeEventListener(
2848+
"pat-inject-before-history-update",
2849+
event_handler
2850+
);
2851+
history.pushState = original_push_state;
2852+
2853+
// Verify the event was dispatched
2854+
expect(event_dispatched).toBe(true);
2855+
// Verify the head was modified before the event was fired
2856+
expect(head_modified_when_event_fired).toBe(true);
2857+
// Verify history.pushState was eventually called
2858+
expect(push_state_called).toBe(true);
2859+
// Verify the content was injected
2860+
expect(document.body.textContent.trim()).toBe("New content");
2861+
});
27832862
});
27842863

27852864
describe("9.5 - support multiple source element matches.", function () {

0 commit comments

Comments
 (0)