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

backbone-courier

v4.0.1

Published

Easily bubble events up your view hierarchy in your Backbone.js applications.

Downloads

204

Readme

Backbone.Courier

A tiny library that bubble events ("messages") up your backbone.js view hierarchy.

How it works

Instead of using view.trigger(), use view.spawn( messageName, [data] ) to spawn a message.

this.spawn( "selected", this.model );

The message is triggered, just like a normal backbone event, and in addition, it will automatically bubble up you view hierarchy. The view's parent can then "handle" the message and / or pass it to the parent's own parent, and so on. The DOM tree is used to determine the view hierarchy.

Here is an example of a view that both spawns a message to its ancestors, and handles a message from its children.

MyViewClass = Backbone.View.extend( {
	initialize : function() {
		Backbone.Courier.add( this );  // add courier functionality to this view
	}

	events : {
		"click div.close-box" : "_closeBoxClicked"
	},

	// "handle" the "selected" message from a child view.
	onMessages : {
		"selected" : "_onChildSelected"
	}

	_onChildSelected : function( data, source, messageName ) {
		alert( "My child view just spawned the 'selected' message." );

		// the three arguments to a message handler are:
		// 1) any application defined data that has been supplied:
		console.log( data ); // outputs the second argument to `spawn`

		// 2) the child view object that spawned or passed this message
		assert( source instanceof Backbone.View );

		// 3) the name of the message (i.e. first argument to `spawn`)
		assert( messageName === "selected" );
	}
	
	// spawn a message that can be handled by our own parent
	_closeBoxClicked : function() {
		this.spawn( 'closeBoxClicked' );
	}
}

Methods and Property reference

Public API index


Backbone.Courier.add( view )

Adds courier methods and behavior to view. To add courier functionality to all of your views, just wrap Backbone.View.initialize:

var oldInitialize = Backbone.View.prototype.initialize;
Backbone.View.prototype.initialize = function() {
	Backbone.Courier.add( this );
	return oldInitialize.apply( this, arguments );
};

view.spawn( messageName, [data] )

The spawn method generates a new message and passes it to the view's "parent", i.e. the closest ancestor view in the DOM tree. (It also calls view.trigger( messageName, data ) so that you can listen to the message as you would a normal Backbone event.) The parent view can "handle" this message, taking some action upon its receipt, by including an entry for this message in its onMessages hash, or it can pass this message to its own parent, using its passMessages property. In this manner the message may bubble up the view hierarchy, as determined (by default) by the DOM tree.

messageName is the name of the message being spawned. The name is used in the onMessages and passMessages properties of ancestor views to handle or pass the message further up the view hierarchy, respectively.

data is application defined data that will be available to this view's ancestors when handling or passing this message.

Round trip messages

If messageName ends in !, the message is considered a "round trip message". Round trip messages are special in that they return values. That is, the spawn() method will return the value returned by the first (and only) method that handles the message. Using round trip messages, views can obtain dynamic information about their environment that, because it is dynamic, can not be passed in through configuration options. Round trip messages are special in that they will continue to be passed up the hierarchy until they are handled - regardless of the value of each intermediate view's passMessages property. If they are not handled, spawn() returns undefined.

view.onMessages

The onMessages hash is the means by which a parent view can take action on, or "handle", messages received from its children. Entries in the onMessages hash have the format:

"messageName source" : callback

Example entries in the onMessages hash:

onMessages : {
	"focused" : function( data, source ) {
		// handle the "focused" message
		alert( "child view focused" );
		console.log( source ); // the child view that spawned or passed this message
	},

	// when the "selected" message from the resourcesCollectionView child view
	// is received, call the _onResourceSelected method on this view
	"selected resourcesCollectionView" : "_onResourceSelected",

	"giveMeInfo!" : function() {
		// handle the "giveMeInfo!" round trip message. return contents
		// of `value` to the view that spawned the message,
		// as the return value of the view.spawn() method
		var value = this._calculateDynamicValue();
		return value;
	}
},

_onResourceSelected : function( data ) {
	// handle the selected message from the resourcesCollectionView child view
}

...

view.passMessages

The passMessages property is used to pass messages received from a child view further up the view hierarchy, to potentially be handled by a more distant ancestor. If the property is false which is the default, no messages are passed through the view. If the proerty is true, all (unhandled) messages are passed through the view. If the property is an array, only messages with the names it contains will be passed through. If / when the message is eventually handled further up the hierarchy, the source of the message will be the view from which it was originally spawned.

...


## Internal view methods that may be overridden

The following methods may be overridden to customize Backbone.Courier for your environment. To override one of the methods, attach your own version of the method to your view objects either before or after calling Backbone.Courier.add().

### view._getParentView()

`view._getParentView()` is an internal method that returns a view's "parent view". You may supply your own version of this method on your view objects (which will override the default implementation) if you want to provide a custom means to determine a view's parent. The default implementation determines a view's parent by its position in the DOM tree, scanning the tree for the closest parent that has a Backbone view in $( el ).data( "view" ). This data value is set on each view's DOM element automatically by Backbone.Courier.

> Note: The default implementation of '_getParentView' depends on jQuery's or Zepto's `$.parent()` and `$.data()` methods, which is the only dependency on a DOM library or tree in Backbone.Courier.

### view._getChildViewNamed( childViewName )

`view._getChildViewNamed( childViewName )` is an internal method that is used to resolve the child view names optionally supplied in the `source` part of the `onMessages` hash. You may supply your own version of this method on your view objects in order to store child views in a location other than the default `view.subviews[ childViewName ]`.

## Encapsulated Views

Although Backbone.Courier is a simple library with a very small footprint, its use significantly improves encapsulation in the view layer. Encapsulation makes modules easy to conceptualize, maintain and test. Backbone views that are encapsulated, and Backbone applications built from encapsulated views, have these same characteristics. But what do encapsulated views look like and how does courier help? Here's our vision:

* Views *never have any explicit dependencies on their surroundings or their environment*. That is, they do not have any explicit dependencies on or references to their ancestors or their siblings.
* When a view needs to interact with its parent or an ancestor, it does so (*without* explicit dependencies) by spawning a message that bubbles up the view hierarchy.
* When views pass messages from their children to their ancestors, they modify those messages in order to make them appropriate for the new, larger context and hide private concerns.
* Views only call methods on their *immediate* children. Their grandchildren can be interacted with only by calling methods on their children, which in turn call methods on their grandchildren, etc.
* Global variables and / or event aggregators are not used.

> NOTE: You can use Backbone.Courier with [Backbone.Subviews](https://github.com/rotundasoftware/backbone.subviews) and
> [Cartero](https://github.com/rotundasoftware/cartero) / [Parcelify](https://github.com/rotundasoftware/parcelify) for a completely modularized backbone.js experience.

## Dependencies

* Backbone.js (tested with v0.9.9 and later, untested with earlier versions)
* jQuery or Zepto. You can eliminate this dependency by overriding `view._getParentView()` and providing an alternate means to determine view hierarchy that does not rely on the `$.parent()` and `$.data()` functions.

## Change log

#### v4.0.0
* BREAKING: The old `passMessages` hash is no longer a hash. It is now either a boolean or an array of the message names that should be passed through the view. Also, the `source` of the message will now remain the same when it is passed. That is to say, when the message is eventually handed, its `source` will be the view that originally spawned it, instead of the view that most recently passed it.

#### v3.0.0
* BREAKING: Round trip messages will no longer thrown an exception if they are not handled. Instead, the `spawn()` method will simply return `undefined`.

#### v1.0.0

* BREAKING: Changed signature of `callback` portion of `onMessages` hash from `function( message )` to `function( data, source, messageName )`. Sorry, this is a big breaking change existing projects will need to be changed to work with this new signature. However, it is the right thing to do. If you don't want to change your existing projects, just keep using v0.6.1.
* Removed the ability to supply a function as the value of an entry in the `passMessages` hash.

#### v0.6.1

* Small bug fix that could cause errors of the form `Cannot read property 'data' of undefined`.

#### v0.6.0

* BREAKING: Removed `spawnMessages` hash. Use version v0.5.x if you want this functionality back.
* Now `view.spawn( data )` will call backbone's native `view.trigger( data )` automatically.
* Added UMD wrapper.