Skip to content

Commit fc0e333

Browse files
committed
feat(core events): Support once-events in add_event_listener.
Add support for once-events in add_event_listener and unregister them when called from the event_listener_map.
1 parent bd95995 commit fc0e333

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

src/core/events.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// Event listener registration for easy-to-remove event listeners.
44
// once Safari supports the ``signal`` option for addEventListener we can abort
55
// event handlers by calling AbortController.abort().
6-
const event_listener_map = {};
6+
export const event_listener_map = {};
77

88
/**
99
* Add an event listener to a DOM element under a unique id.
@@ -22,11 +22,21 @@ const add_event_listener = (el, event_type, id, cb, opts = {}) => {
2222
}
2323
remove_event_listener(el, id); // do not register one listener twice.
2424

25+
// Create event_listener_map entry if not existent.
2526
if (!event_listener_map[el]) {
2627
event_listener_map[el] = {};
2728
}
28-
event_listener_map[el][id] = [event_type, cb, opts.capture ? opts : undefined]; // prettier-ignore
29-
el.addEventListener(event_type, cb, opts);
29+
let _cb = cb;
30+
if (opts?.once === true) {
31+
// For `once` events, also remove the entry from the event_listener_map.
32+
_cb = (e) => {
33+
delete event_listener_map[el][id];
34+
cb(e);
35+
};
36+
}
37+
// Only `capture` option is necessary for `removeEventListener`.
38+
event_listener_map[el][id] = [event_type, _cb, opts.capture ? opts : undefined];
39+
el.addEventListener(event_type, _cb, opts);
3040
};
3141

3242
/**

src/core/events.test.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,21 @@ describe("core.events tests", () => {
5050
done();
5151
});
5252

53+
it("Supports once-events and unregisters them from the event_listener_map", async () => {
54+
const event_listener_map = (await import("./events")).event_listener_map;
55+
const el = document.createElement("div");
56+
57+
// register the once-event handler
58+
events.add_event_listener(el, "test", "test_once_event", () => {}, {
59+
once: true,
60+
});
61+
62+
expect(event_listener_map[el].test_once_event).toBeDefined();
63+
el.dispatchEvent(new Event("test"));
64+
65+
expect(event_listener_map[el].test_once_event).not.toBeDefined();
66+
});
67+
5368
it("Awaits an event to happen", async () => {
5469
const el = document.createElement("div");
5570

0 commit comments

Comments
 (0)