Skip to content

TomokiMiyauci/get-event-listeners

Folders and files

NameName
Last commit message
Last commit date

Latest commit

d2287ac · Aug 10, 2023

History

22 Commits
Aug 7, 2023
Aug 6, 2023
Aug 6, 2023
Aug 7, 2023
Aug 7, 2023
Aug 10, 2023
Aug 10, 2023
Aug 10, 2023
Aug 10, 2023
Aug 10, 2023
Aug 10, 2023
Aug 10, 2023
Aug 10, 2023
Aug 10, 2023
Aug 10, 2023
Aug 10, 2023
Aug 10, 2023

Repository files navigation

get-event-listeners

Ponyfill for getEventListeners.

Install

deno.land:

import * as mod from "https://deno.land/x/get_event_listeners/mod.ts";

npm:

npm i @miyauci/get-event-listeners

Usage

updateEventListener function replaces addEventListener and removeEventListener in EventTarget.prototype with a proxy.

You can refer to the currently registered event listeners with return value.

import { updateEventListener } from "https://deno.land/x/get_event_listeners/mod.ts";
import { assertEquals } from "https://deno.land/std/testing/asserts.ts";

const getEventListeners = updateEventListener();

declare const target: EventTarget;
declare const handleClick: () => void;
target.addEventListener("click", handleClick);

assertEquals(getEventListeners(target), {
  click: [{
    type: "click",
    listener: handleClick,
    useCapture: false,
    once: false,
    passive: false,
  }],
});

Pure context

The updateEventListener has a side effect instead of being immediately available.

We provide a pure context builder with no side effects.

import { createContext } from "https://deno.land/x/get_event_listeners/mod.ts";
import {
  afterEach,
  beforeEach,
  describe,
} from "https://deno.land/std/testing/bdd.ts";

const { addEventListener, removeEventListener } = EventTarget.prototype;
const context = createContext({ addEventListener, removeEventListener });

describe("event listener monitoring", () => {
  beforeEach(() => {
    EventTarget.prototype.addEventListener = context.addEventListener;
    EventTarget.prototype.removeEventListener = context.removeEventListener;
  });

  afterEach(() => {
    EventTarget.prototype.addEventListener = addEventListener;
    EventTarget.prototype.removeEventListener = removeEventListener;
  });
});

Event listener equality

Event listeners are managed by WeakMap(called registry) throughout the realm.

Equivalence checks for event listener are performed, equivalent to addEventListener and removeEventListener.

  • addEventListener Add an event listener to the registry only if one of [type, listener, useCapture] is different from the existing one
  • removeEventListener Remove the event listener from the registry only if [type, listener, useCapture] match

Like addEventListener, you can be sure that duplicate listeners will not be registered in the registry either.

import { updateEventListener } from "https://deno.land/x/get_event_listeners/mod.ts";
import { assertEquals } from "https://deno.land/std/testing/asserts.ts";

const getEventListeners = updateEventListener();

declare const target: EventTarget;
declare const handleClick: () => void;
const expected = {
  click: [{
    type: "click",
    listener: handleClick,
    useCapture: false,
    once: false,
    passive: false,
  }, {
    type: "click",
    listener: handleClick,
    useCapture: true,
    once: false,
    passive: false,
  }],
};

target.addEventListener("click", handleClick);
target.addEventListener("click", handleClick, true);

assertEquals(getEventListeners(target), expected);

target.addEventListener("click", handleClick);
target.addEventListener("click", handleClick, true);
target.addEventListener("click", handleClick, { capture: true });
target.addEventListener("click", handleClick, { once: true });
target.addEventListener("click", handleClick, { passive: true });

assertEquals(getEventListeners(target), expected);

Compatibility

getEventListeners is based on Chrome Console Utilities API.

Safari provides similar functionality, but there is no type property on the return value of EventListener.

The DOM has also proposed adding a similar API to EventTarget.

API

See deno doc for all APIs.

Contributing

See contributing.

License

MIT © 2023 Tomoki Miyauchi