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

seng-event

v2.0.2

Published

Provides Classes and utilities for dispatching and listening to events.

Downloads

5,600

Readme

Travis Coveralls npm npm

seng-event

Provides Classes and utilities for dispatching and listening to events.

Provides an EventDispatcher base class that adds the ability to dispatch events and attach handlers that should be called when such events are triggered. New event classes can be created by extending the AbstractEvent class provided in this module. This module also provides basic event classes BasicEvent and CommonEvent that are ready to be used with EventDispatcher.

seng-event also supports event capturing and bubbling phases, heavily inspired by existing event dispatching systems like the functionality described in the DOM Event W3 spec

Installation

yarn add seng-event

or

npm i -S seng-event

Basic usage

1. Extend the EventDispatcher class

By extending EventDispatcher, your class gains the ability to dispatch events using this.dispatchEvent(). Other code can listen to events by calling the addEventListener() method on your class. For more methods, see the generated API Docs

import EventDispatcher from 'seng-event';

class Dog extends EventDispatcher {
  ...
}

2. Create your own event class

Create an event class that defines the structure of the events you want to dispatch. This event class should extends the base class AbstractEvent. There are multiple ways of doing this:

Use the createEventClass() utiltiy

import { createEventClass } from 'seng-event';

class DogEvent extends createEventClass()('BARK','JUMP','RUN','WALK') {}

Manually extend AbstractEvent

import { AbstractEvent } from 'seng-event';

class DogEvent extends AbstractEvent {
   public static types = {
      BARK: 'BARK',
      JUMP: 'JUMP',
      RUN: 'RUN',
      WALK: 'WALK'
   };
   
   public clone():DogEvent {
       return new DogEvent(this.type);
   }
}

Note: we recommend the above convention of putting the available event types as a static member on the event. However, you are free to use any string as an event type.

3. Dispatch events

const dog = new Dog();
const runHandler = (event:DogEvent) => {
  console.log('Dog is running!');
}
dog.addEventListener(DogEvent.types.RUN, runHandler);

// dispatch an event (will execute runHandler and log 'Dog is running!')
dog.dispatchEvent(new DogEvent(DogEvent.types.RUN));  

Binding your EventDispatcher child class to certain event classes

If you define which events your EventDispatcher is expected to dispatch, the class will have better typings on methods like dispatchEvent and addEventListener:

class Dog extends EventDispatcher<DogEvent> {

You can use a union type to allow for multiple event classes:

class Dog extends EventDispatcher<DogEvent|SomeOtherEvent|AnotherEvent> {

Adding data to your events

It is common to attach some data to an event that can be read from the event handler. You can implement this manually if you extend AbstractEvent, but this can more easily be achieved with the createEventClass util:

interface DogEventData {
    mood: 'happy'|'sad';
}

class DogEvent extends createEventClass<DogEventData>()('BARK','JUMP','RUN','WALK') {}
// creating and dispatching events in the `Dog` class:
this.dispatchEvent(new DogEvent(DogEvent.types.JUMP, { mood: 'happy' }));
// accessing the data
dog.addEventListener(DogEvent.types.JUMP, event => {
  console.log(`Dog jumped in a ${event.mood} mood!`);
});

Cancellation, propagation and setTimestamp

The cancellation, bubbling and timestamp functionality of this libary are heavily inspired by the DOM Event W3 spec. These options can be enabled by passing true to the createEventClass util or AbstractEvent constructor:

class DogEvent extends createEventClass<DogEventData>(
  true, // bubbles
  true, // cancelable
  true // setTimestamp
)('BARK','JUMP','RUN','WALK') {}
class DogEvent extends AbstractEvent {
   constructor(type: string) {
       super(
         type,
         true, // bubbles
         true, // cancelable
         true // setTimestamp
       );
   }
}

Cancellation

Setting cancelable to true allows preventDefault to be called on the event. Checking if preventDefault() has been called is up to the implementer that calls dispatchEvent():

const event = new DogEvent(DogEvent.types.WALK, { mood: 'happy' });
this.dispatchEvent(event);
if (!event.defaultPrevented) {
    // do the default action here
}

Bubbling

Setting bubbling to true enables event propagation for the event if the event is dispatched on an EventDispatcher instance with a parent. See this page for a general guide on how event bubbling works.

class CustomElement extends EventDispatcher<ElementEvent> {
  public name: string;
  constructor(name: string, parent: CustomElement|null = null) {
      super(parent);
      
      this.name = name;
  }
  ...
}

const elementA = new CustomElement('A');
const elementB = new CustomElement('B', elementA);
const elementC = new CustomElement('C', elementB);

elementA.addEventListener(ElementEvent.types.CLICK, (event) => {
    console.log(`The element ${event.target.name} has been clicked!`);
});

elementC.dispatchEvent(new ElementEvent(ElementEvent.types.CLICK)); // logs "The element C has been clicked!"

This library also supports a capturing phase. You can listen to events in the capturing phase by setting the useCapture parameter to true in the addEventListener method:

elementA.addEventListener(ElementEvent.types.CLICK, (event) => console.log('Capture listener on A'), true);
elementA.addEventListener(ElementEvent.types.CLICK, (event) => console.log('Bubbling listener on A'));
elementB.addEventListener(ElementEvent.types.CLICK, (event) => console.log('Capture listener on B'), true);
elementB.addEventListener(ElementEvent.types.CLICK, (event) => console.log('Bubbling listener on B'));
elementC.dispatchEvent(new ElementEvent(ElementEvent.types.CLICK));
// logs in the following order:
// Capture listener on A
// Capture listener on B
// Bubbling listener on B
// Bubbling listener on A

setTimestamp

Setting setTimestamp to true will cause a timeStamp property to be set on the event which is a UNIX timestamp of the time the event was dispatched.

Isomorphic event classes

An isomorphic event class can have different data and options for each event type. It can be created using the createIsomorphicEventClass util:

interface DogEventData {
    mood: 'happy'|'sad';
}
interface DogMoveEventData extends DogEventData {
    speed: number;
}

class DogEvent extends createIsomorphicEventClass<
  DogEventData, DogEventData, DogMoveEventData, DogMoveEventData
>(
  {}, {}, {}, { cancelable: true }
)(
  'BARK','JUMP','RUN','WALK'
) {}

In the above example, a RUN and a WALK event now have a speed property on their event data, whereas the other events do not. In addition, all WALK events are cancelable.

// OK
this.dispatchEvent(new DogEvent(DogEvent.types.JUMP, { mood: 'happy' }));
this.dispatchEvent(new DogEvent(DogEvent.types.BARK, { mood: 'sad' }));
this.dispatchEvent(new DogEvent(DogEvent.types.WALK, { mood: 'sad', speed: 0 }));
// NOT OK (will give a compiler error)
this.dispatchEvent(new DogEvent(DogEvent.types.JUMP, { mood: 'happy', speed: 10 }));
this.dispatchEvent(new DogEvent(DogEvent.types.RUN, { mood: 'happy' }));
dog.addEventListener(DogEvent.types.JUMP, event => {
  console.log(typeof event.data.speed); // logs undefined
});
dog.addEventListener(DogEvent.types.WALK, event => {
  console.log(typeof event.data.speed); // logs "number"
  event.preventDefault(); // possible because 'WALK' is cancelable
});

API documentation

View the full generated documentation here.

Building

In order to build seng-event, ensure that you have Git and Node.js installed.

Clone a copy of the repo:

git clone https://github.com/mediamonks/seng-event.git

Change to the seng-event directory:

cd seng-event

Install dev dependencies:

yarn

Use one of the following main scripts:

yarn build            # build this project
yarn dev              # run compilers in watch mode, both for babel and typescript
yarn test             # run the unit tests incl coverage
yarn test:dev         # run the unit tests in watch mode
yarn lint             # run eslint and tslint on this project
yarn doc              # generate typedoc documentation

When installing this module, it adds a pre-commit hook, that runs lint and prettier commands before committing, so you can be sure that everything checks out.

Contribute

View CONTRIBUTING.md

Changelog

View CHANGELOG.md

Authors

View AUTHORS.md

LICENSE

MIT © MediaMonks