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-user-activity

v8.0.1

Published

Ember Addon for tracking user activity & idling

Downloads

30,807

Readme

Ember User Activity

Netlify Status Build Status Ember Observer Score Code Climate

This addon provides services for detecting user activity & idling across the entire application.

Check out the Demo!

We adhere to the Ember Community Guidelines for our Code of Conduct.

Compatibility

  • Ember.js v4.8 or above
  • Ember CLI v4.8 or above
  • Node.js v18 or above

Installation

ember install ember-user-activity

Usage

User Activity Service

This service fires events from global window listeners. These listeners trigger on capture, meaning they are not affected by event cancellation.

These window events are enabled by default:

  • keydown - Fires when a key is pressed
  • mousedown - Fires when a mouse is clicked
  • scroll - Fires when the user scrolls
  • touchstart - Fires when a touch point is placed on the touch surface [Mobile-Friendly]
  • storage - Fires when any activity event is triggered on another tab of the same website. This avoids problems when a user opens up serveral tabs to the same application.
  • ~~mousemove - Fires when the user moves the mouse~~ Removed as of v0.2.0

A custom event, userActive is fired for ALL enabled events.

To catch these events, simply inject the service and subscribe to the events you care about:

import Component from '@glimmer/component';
import { service } from '@ember/service';

// any file where services can be injected
export default class MyComponent extends Component {
  @service userActivity;

  setupListeners() {
    this.userActivity.on('userActive', this, this.activeHandler);
  }

  activeHandler(event) {
    // do stuff
  }
}

Each event handler will receive the standard DOM event object (ex: mousemove).

Unsubscribe from any event by calling off:

this.userActivity.off('userActive', this, this.activeHandler);

Note: While our event dispatch system mirrors Ember.Evented, it does not include the one method. Only on, off, and trigger have been implemented. If you feel one is necessary for you, we're happy to accept PRs!

Event Configuration

If you would like to listen to a different set of events, extend the service in your app:

// app/services/user-activity.js
import UserActivityService from 'ember-user-activity/services/user-activity';

export default class UserActivity extends UserActivityService {
  defaultEvents = ['keypress', 'mouseenter', 'mousemove'];
}

Additionally, you can enable/disable events after the service has been initialized.

this.userActivity.enableEvent('keyup');
this.userActivity.disableEvent('mousedown');

Event names must be from the DOM Event list. Custom events are not currently supported. If you enable an event name that was not set up by default, a new listener will be created automatically.

You can find out if an event is currently enabled:

this.userActivity.isEnabled('foo'); // false
this.userActivity.isEnabled('keydown'); // true

Performance Configuration

Each individual event is throttled by 100ms for performance reasons, to avoid clogging apps with a firehose of activity events. The length of the throttling can be configured by setting EVENT_THROTTLE on the activity service.

// app/services/user-activity.js
import UserActivityService from 'ember-user-activity/services/user-activity';

export default class UserActivity extends UserActivityService {
  EVENT_THROTTLE = 200; // 200 ms
}

Setting EVENT_THROTTLE to 0 will enable the full firehose of events. This may cause performance issues in your application if non-trivial amounts of code are being executed for each event being fired.

User Idle Service

This service tracks user activity to decide when a user has gone idle by not interacting with the page for a set amount of time.

import Component from '@glimmer/component';
import { service } from '@ember/service';
import { readOnly } from '@ember/object/computed'

export default class MyComponent extends Component {
  @service userIdle;

  @readOnly('userIdle.isIdle')
  isIdle;
}

The default timeout is set for 10 minutes but can be overridden by extending the service:

// app/services/user-idle.js
import UserIdleService from 'ember-user-activity/services/user-idle';

export default class UserIdle extends UserIdleService {
  IDLE_TIMEOUT = 300000 // 5 minutes
}

By default, the idle service listens to the userActive event, but it can be configured to listen to a custom set of events from the user-activity service:

// app/services/user-idle.js
import UserIdleService from 'ember-user-activity/services/user-idle';

export default class UserIdle extends UserIdleService {
  activeEvents = ['mousedown', 'keydown'];
}

Note that the userActive event is a superset of all events fired from user-activity, so in most cases you won't need to change this.

The idle service has a idleChanged event when isIdle gets changed.

import Component from '@glimmer/component';
import { service } from '@ember/service';

export default class MyComponent extends Component {
  @service userIdle;

  constructor() {
    this.userIdle.on('idleChanged', (isIdle) => {
      // isIdle is true if idle. False otherwise.
    });
  }
}

Scroll Activity Service

This service tracks scrolling within the application by periodically checking (via requestAnimationFrame) for changes in scroll position for the various scrollable elements in the page. By default, it only checks document, but the Scroll Activity Mixin provides an easy way to register your components as well. The User Activity Service subscribes to these scrolling events by default, so you do not need to do anything to use this service for global scroll events if you are already injecting the user-activity service.

Any elements can be subscribed to this service:

this.scrollActivity.subscribe(this, element);

subscribe requires at least two parameters:

  • target - Usually this, target just needs to be a unique identifier/object that can be used to unsubscribe from the service
  • element - The scrollable element (can be a DOM or jQuery element - jQuery not required!)

Two optional parameters may follow:

  • callback - A callback to execute when scrolling has been detected in the element
  • highPriority - A boolean (default true) specifying this subscriber should eagerly check scroll positions on each animation frame. When false, it will instead use an approximation of idle checking on the UI thread to avoid performing measurements at sensitive times for other work (like rendering).

Conversely, elements can also be unsubscribed:

this.scrollActivity.unsubscribe(this);

unsubscribe only requires the target parameter that was initially used to subscribe.

Cleanup

Please remember that subscribing to events can cause memory leaks if they are not properly cleaned up. Make sure to remove any listeners before destroying their parent objects.

// app/components/foo-bar.js
export default class FooBar extends Component {
  willDestroy() {
    this.userActivity.off('keydown', this, this.keydownHandler);
  }
}

Using in an Addon

Building your own addon to extend Ember User Activity? No problem!

// my-addon/addon/services/user-idle.js
import UserIdleService from 'ember-user-activity/services/user-idle';

export default class UserIdle extends UserIdleService {
  IDLE_TIMEOUT = 3000; // 3 minutes
}

Contributing

See the Contributing guide for details.

License

This project is licensed under the MIT License.