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

dry-observer

v0.2.2

Published

A utility to setup DRY event listeners.

Downloads

5

Readme

dry-observer

Dryly bind and unbind event listeners and encourage consistent, pattern-based naming of handlers/callbacks.

Build Status

# Observe a Model by passing a hash…
@observe model,
  'song:change'   : @onSongChange
  'volume:change' : @onVolumeChange
  'focus'         : @onFocus

# …or a String or Array.
# Observation will camelCase and prefix your events.
@observe model, 'song:change volume:change focus'

# Stop observing and dereference your model…
@stopObserving model

# …or stop observing /everything/
@stopObserving()

# …or remove a specific handler and cleanup.
@removeObserver model, 'song:change', @onSongChange

Problem

If you're working a lot with Backbone (or other EventEmitter-based APIs), you may have written or reviewed code that's similar to this:

# app/assets/javascripts/views/tasks/detail.js.coffee
class TaskDetail extends Backbone.View
  initialize: ->
    @model.on 'change:closed',    @handleUpdatable
    @model.on 'focus',            @handleFocus
    @model.on 'resetAssignee',    @resetAssignee
    @model.on 'positionUpdated',  @updatePosition
    # etc

  remove: ->
    @model.off 'change:closed',   @handleUpdatable
    @model.off 'resetAssignee',   @resetAssignee
    @model.off 'positionUpdated', @updatePosition
    super

There a number of problems with this code:

  • Events aren't named or formatted uniformly.
  • Handlers aren't consistently named, and may or may not rely on arguments passed by #trigger or #emit.
  • Repetitive calls to #on and #off on different objects adds unDRY cruft to your codebase and…
  • It's easy to forget to bind or unbind events, or update the names of your handlers as you go.

Solution

Observation helps you solve each of these problems by allowing you to centralize both binding and unbinding to events, and by encouraging consistent handler naming.

# app/assets/javascripts/views/tasks/detail.js.coffee
#
class TaskDetail extends App.View
  initialize: ->
    # `#observe` automatically calls `#on` for you, optionally intuiting
    # proper handler names and checking to ensure they exist.
    #
    @observe @model, 'change:closed focus position:updated assignee:reset'

To fully leverage the usefullness of Observation, create a base subclass of Backbone.View you can use to ensure that event listeners always get cleaned up upon view removal.

# app/assets/javascripts/views/base.js.coffee
#
class App.View extends Backbone.View
  # …
  remove: ->
    # Removes all listeners and references to objects observed by a
    # call to `#observe`
    @stopObserving()
    super

# Add Observers to our View base class.
_.extend App.View::, Observers

# app/assets/javascripts/controllers/task_controller.js.coffee
#
# Elsewhere in your code, you decide to remove your TaskDetail view,
# calling the standard Backbone.View#remove() method, perhaps along
# with navigating elsewhere in your app.

detailView.remove()

Contributions

Patches and bug reports are welcome. Just send a pull request or file an issue. Project Changelog.

License