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

ember-on-helper

v0.1.0

Published

{{on eventTarget eventName someAction}} template helper

Downloads

33,660

Readme

ember-on-helper

Build Status npm version Download Total Ember Observer Score Ember Versions ember-cli Versions code style: prettier dependencies devDependencies

An {{on}} template helper complimentary to the RFC #471 "{{on}} modifier".

Installation

ember install ember-on-helper

Compatibility

  • Ember.js v2.18 or above
  • ember-cli v2.13 or above

But why?

You would use the {{on}} modifier to register event listeners on elements that are in the realm of your current template. But sometimes you need to register event listeners on elements or even on generic EventTargets that are outside of the control of your template, e.g. document or window.

⚠️👉 WARNING: Do not overuse this helper. If you want to bind to an element that is controlled by Glimmer, but maybe just not by the current template, do not reach for a manual document.querySelector(). Instead, think about your current template and state setup and try to use a true "Data Down, Actions Up" pattern or use a shared Service as a message bus.

Usage

Pretty much exactly the same as the {{on}} modifier, except for that the {{on}} helper expects one more positional parameter upfront: the evenTarget.

{{on eventTarget eventName eventListener}}

As with the {{on}} modifier, you can also pass optional event options as named parameters:

{{on eventTarget eventName eventListener capture=bool once=bool passive=bool}}

Simple Example

Click anywhere in the browser window, fam.

{{on this.document "click" this.onDocumentClick}}
import Component from '@glimmer/component';
import { action } from '@ember/object';

export default class TomstersWitnessComponent extends Component {
  document = document;

  @action
  onDocumentClick(event: MouseEvent) {
    console.log(
      'Do you have a minute to talk about our Lord and Savior, Ember.js?'
    );
  }
}

This is essentially equivalent to:

didInsertElement() {
  super.didInsertElement();

  document.addEventListener('click', this.onDocumentClick);
}

In addition to the above {{on}} will properly tear down the event listener, when the helper is removed from the DOM. It will also re-register the event listener, if any of the passed parameters change.

The @action decorator is used to bind the onDocumentClick method to the component instance. This is not strictly required here, since we do not access this, but in order to not break with established patterns, we do it anyway.

Listening to Events on window or document

You will often want to use the {{on}} helper to listen to events which are emitted on window or document. Because providing access to these globals in the template as shown in [Simple Example][#simple-example] is quite cumbersome, {{on}} brings two friends to the party:

  • {{on-document eventName eventListener}}
  • {{on-window eventName eventListener}}

They work exactly the same way as {{on}} and also accept event options.

Listening to Multiple Events

You can use the {{on}} helper multiple times in the same element, even for the same event.

{{on this.someElement "click" this.onClick}}
{{on this.someElement "click" this.anotherOnClick}}
{{on this.someElement "mousemove" this.onMouseMove}}

Event Options

All named parameters will be passed through to addEventListener as the third parameter, the options hash.

{{on-document "scroll" this.onScroll passive=true}}

This is essentially equivalent to:

didInsertElement() {
  super.didInsertElement();

  document.addEventListener('scroll', this.onScroll, { passive: true });
}

once

To fire an event listener only once, you can pass the once option:

{{on-window "click" this.clickOnlyTheFirstTime once=true}}
{{on-window "click" this.clickEveryTime}}

clickOnlyTheFirstTime will only be fired the first time the page is clicked. clickEveryTime is fired every time the page is clicked, including the first time.

capture

To listen for an event during the capture phase already, use the capture option:

{{on-document "click" this.triggeredFirst capture=true}}

<button {{on "click" this.triggeredLast}}>
  Click me baby, one more time!
</button>

passive

If true, you promise to not call event.preventDefault(). This allows the browser to optimize the processing of this event and not block the UI thread. This prevent scroll jank.

If you still call event.preventDefault(), an assertion will be raised.

{{on-document "scroll" this.trackScrollPosition passive=true}}>

Internet Explorer 11 Support

Internet Explorer 11 has a buggy and incomplete implementation of addEventListener: It does not accept an options parameter and sometimes even throws a cryptic error when passing options.

This is why this addon ships a tiny ponyfill for addEventLisener that is used internally to emulate the once, capture and passive option. This means that all currently known options are polyfilled, so that you can rely on them in your logic.

Currying / Partial Application

If you want to curry the function call / partially apply arguments, you can do so using the {{fn}} helper:

{{#each this.videos as |video|}}
  {{on video.element "play" (fn this.onPlay video)}}
  {{on video.element "pause" (fn this.onPause video)}}
{{/each}}
import Component from '@ember/component';
import { action } from '@ember-decorators/object';

interface Video {
  element: HTMLVideoElement;
  title: string;
}

export default class UserListComponent extends Component {
  videos: Video[];

  @action
  onPlay(video: Video, event: MouseEvent) {
    console.log(`Started playing '${video.title}'.`);
  }

  @action
  onPlay(video: Video, event: MouseEvent) {
    console.log(`Paused '${video.title}'.`);
  }
}

preventDefault / stopPropagation / stopImmediatePropagation

The old {{action}} modifier used to allow easily calling event.preventDefault() like so:

<a href="/" {{action this.someAction preventDefault=true}}>Click me</a>

You also could easily call event.stopPropagation() to avoid bubbling like so:

<a href="/" {{action this.someAction bubbles=false}}>Click me</a>

You can still do this using ember-event-helpers:

<a href="/" {{on "click" (prevent-default this.someAction)}}>Click me</a>
<a href="/" {{on "click" (stop-propagation this.someAction)}}>Click me</a>

Attribution

This addon is a straight copy of ember-on-modifier, the polyfill for the {{on}} modifier.