npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@xo-union/event-target-shim

v5.0.1

Published

An implementation of WHATWG EventTarget interface.

Downloads

6,913

Readme

event-target-shim

npm version Downloads/month Build Status Coverage Status Dependency Status

An implementation of WHATWG EventTarget interface, plus few extensions.

  • This provides EventTarget constructor that can inherit for your custom object.
  • This provides an utility that defines properties of attribute listeners (e.g. obj.onclick).
import {EventTarget, defineEventAttribute} from "event-target-shim"

class Foo extends EventTarget {
    // ...
}

// Define `foo.onhello` property.
defineEventAttribute(Foo.prototype, "hello")

// Use
const foo = new Foo()
foo.addEventListener("hello", e => console.log("hello", e))
foo.onhello = e => console.log("onhello:", e)
foo.dispatchEvent(new CustomEvent("hello"))

💿 Installation

Use npm to install then use a bundler.

npm install event-target-shim

Or download from dist directory.

📖 Usage

import {EventTarget, defineEventAttribute} from "event-target-shim"
// or
const {EventTarget, defineEventAttribute} = require("event-target-shim")

// or UMD version defines a global variable:
const {EventTarget, defineEventAttribute} = window.EventTargetShim

EventTarget

https://dom.spec.whatwg.org/#interface-eventtarget

eventTarget.addEventListener(type, callback, options)

Register an event listener.

  • type is a string. This is the event name to register.
  • callback is a function. This is the event listener to register.
  • options is a boolean or an object { capture?: boolean, passive?: boolean, once?: boolean }. If this is a boolean, it's same meaning as { capture: options }.
    • capture is the flag to register the event listener for capture phase.
    • passive is the flag to ignore event.preventDefault() method in the event listener.
    • once is the flag to remove the event listener automatically after the first call.

eventTarget.removeEventListener(type, callback, options)

Unregister an event listener.

  • type is a string. This is the event name to unregister.
  • callback is a function. This is the event listener to unregister.
  • options is a boolean or an object { capture?: boolean }. If this is a boolean, it's same meaning as { capture: options }.
    • capture is the flag to register the event listener for capture phase.

eventTarget.dispatchEvent(event)

Dispatch an event.

  • event is a Event object or an object { type: string, [key: string]: any }. The latter is non-standard but useful. In both cases, listeners receive the event as implementing Event interface.

defineEventAttribute(proto, type)

Define an event attribute (e.g. onclick) to proto. This is non-standard.

  • proto is an object (assuming it's a prototype object). This function defines a getter/setter pair for the event attribute.
  • type is a string. This is the event name to define.

For example:

class AbortSignal extends EventTarget {
    constructor() {
        this.aborted = false
    }
}
// Define `onabort` property.
defineEventAttribute(AbortSignal.prototype, "abort")

EventTarget(types)

Define a custom EventTarget class with event attributes. This is non-standard.

  • types is a string or an array of strings. This is the event name to define.

For example:

// This has `onabort` property.
class AbortSignal extends EventTarget("abort") {
    constructor() {
        this.aborted = false
    }
}

📚 Examples

ES2015 and later

https://jsfiddle.net/636vea92/

const {EventTarget, defineEventAttribute} = EventTargetShim

// Define a derived class.
class Foo extends EventTarget {
    // ...
}

// Define `foo.onhello` property.
defineEventAttribute(Foo.prototype, "hello")

// Register event listeners.
const foo = new Foo()
foo.addEventListener("hello", (e) => {
    console.log("hello", e)
})
foo.onhello = (e) => {
    console.log("onhello", e)
}

// Dispatching events
foo.dispatchEvent(new CustomEvent("hello", { detail: "detail" }))

Typescript

import { EventTarget, defineEventAttribute } from "event-target-shim";

// Define events
type FooEvents = {
    hello: CustomEvent
}
type FooEventAttributes = {
    onhello: CustomEvent
}

// Define a derived class.
class Foo extends EventTarget<FooEvents, FooEventAttributes> {
    // ...
}
// Define `foo.onhello` property's implementation.
defineEventAttribute(Foo.prototype, "hello")

// Register event listeners.
const foo = new Foo()
foo.addEventListener("hello", (e) => {
    console.log("hello", e.detail)
})
foo.onhello = (e) => {
    console.log("onhello", e.detail)
}

// Dispatching events
foo.dispatchEvent(new CustomEvent("hello", { detail: "detail" }))

Unfortunately, both FooEvents and FooEventAttributes are needed because TypeScript doesn't allow the mutation of string literal types. If TypeScript allowed us to compute "onhello" from "hello" in types, FooEventAttributes will be optional.

This EventTarget type is compatible with EventTarget interface of lib.dom.d.ts.

To disallow unknown events

By default, methods such as addEventListener accept unknown events. You can disallow unknown events by the third type parameter "strict".

type FooEvents = {
    hello: CustomEvent
}
class Foo extends EventTarget<FooEvents, {}, "strict"> {
    // ...
}

// OK because `hello` is defined in FooEvents.
foo.addEventListener("hello", (e) => {
})
// Error because `unknown` is not defined in FooEvents.
foo.addEventListener("unknown", (e) => {
})

However, if you use "strict" parameter, it loses compatibility with EventTarget interface of lib.dom.d.ts.

To infer the type of dispatchEvent() method

TypeScript cannot infer the event type of dispatchEvent() method properly from the argument in most cases. You can improve this behavior with the following steps:

  1. Use the third type parameter "strict". This prevents inferring to dispatchEvent<string>().
  2. Make the type property of event definitions stricter.
type FooEvents = {
    hello: CustomEvent & { type: "hello" }
    hey: Event & { type: "hey" }
}
class Foo extends EventTarget<FooEvents, {}, "strict"> {
    // ...
}

// Error because `detail` property is lacking.
foo.dispatchEvent({ type: "hello" })

ES5

https://jsfiddle.net/522zc9de/

// Define a derived class.
function Foo() {
    EventTarget.call(this)
}
Foo.prototype = Object.create(EventTarget.prototype, {
    constructor: { value: Foo, configurable: true, writable: true }
    // ...
})

// Define `foo.onhello` property.
defineEventAttribute(Foo.prototype, "hello")

// Register event listeners.
var foo = new Foo()
foo.addEventListener("hello", function(e) {
    console.log("hello", e)
})
foo.onhello = function(e) {
    console.log("onhello", e)
}

// Dispatching events
function isSupportEventConstrucor() { // IE does not support.
    try {
        new CusomEvent("hello")
        return true
    } catch (_err) {
        return false
    }
}
if (isSupportEventConstrucor()) {
    foo.dispatchEvent(new CustomEvent("hello", { detail: "detail" }))
} else {
    var e = document.createEvent("CustomEvent")
    e.initCustomEvent("hello", false, false, "detail")
    foo.dispatchEvent(e)
}

📰 Changelog

🍻 Contributing

Contributing is welcome ❤️

Please use GitHub issues/PRs.

Development tools

  • npm install installs dependencies for development.
  • npm test runs tests and measures code coverage.
  • npm run clean removes temporary files of tests.
  • npm run coverage opens code coverage of the previous test with your default browser.
  • npm run lint runs ESLint.
  • npm run build generates dist codes.
  • npm run watch runs tests on each file change.