Rich, declarative, custom events are awesome. Don't know what i'm talking about? Read on...
Meaningless Events Are Lame
Events like 'click' and 'keyup' are meaningless to the models and logic of most applications, but i bet you still register listeners for them in your application's code. This is lame.
Declarative Application Events Are Awesome!
Add trigger.js to your page, then simply declare what 'click' means in your markup:
When the user "clicks" it, a 'save' event is automatically created and dispatched on the element. Your application never needs to listen for a click event again.
Most people can get by with just declaring the meaning of clicks, but you can easily add other native events as additional triggers:
Dependent Events Are Hard
Sometimes a single "click" serves as a trigger for a sequence of application actions.
The simpler apps out there just conflate the actions into one
More advanced developers might register multiple listeners for the same event and
event.stopImmediatePropogation(); when you need to break the sequence.
But both approaches (and most varieties of them) are fundamentally hacks to workaround
you wanting a single brower event to start a sequence of application events.
There is a better way...
Declaring Event Sequences Is Awesome!
This will trigger the "validate" and "save" events in sequence.
Your list of events can be as long as you like. Any event handler can just call
event.stopSequence() to stop the rest of the specific, declared sequence.
Then, if you like, you can call
event.resumeSequence() to restart it where you left off.
And of course, check on the state of things with
What About Asynchronous Handlers?!
Once you are used to chaining events into nice declarative sequences,
you will likely come upon a situation where one of the handlers needs to do something
asynchronous (e.g. validate something on the server) before the subsequent events are
triggered. To keep things event-y, you do a manual
trigger('save'); call at
the end of the success callback for your async business. But this means your nice
<button click="validate save">Save</button> element becomes a
Not A Problem, Friend.
It's easy, get yourself a promise in that
validate event handler and set it
on the event (e.g.
event.stopSequence(promise);). This stops the event sequence
and automatically resumes it again once the promise is fulfilled. Now you
can have your straightforward
click="validate save" button back!
Simplistic Events Are Not Simple
Once you've earned your "Application Events" achievement, you may realize you are only declaring events as disconnected verbs or nouns, or maybe awkward verbNouns. Your listeners have to glean information from the context or target element to decipher the full meaning of the event. Not to mention that this stuff can easily land you in "use comments to explain" territory. Sometimes that simplicity is good, but sometimes it is a real problem.
Grammatically Rich Events Are Simply Awesome!
click="category:type" -> event.category
When you need to distinguish your player's "move" event from that of a different feature,
prefix your event with a category (subject/noun):
Any app-wide 'move' listener can read it from the
click="type['constant']" -> event.constants
To include contextual constants (object/noun) for your event, do:
The constant gets the JSON.parse() treatment (after some quote massaging) and
is set at
event.constants (always in an array, thus the brackets);
click="type#tag" -> event.tags
Finally, you can add simple tags (adjectives/adverbs) to your events, each prefixed by '#':
click="move#up#left" and listen for these at
event.tags and each
(the individual tags are always given a value of
NOTE: If you have a reason to use combinations of all three (probably rare),
then you must put them in this order:
Think of it as subject, verb, object, adjectives and you probably won't forget how it goes.
But HTML Validation?!
You probably understand why HTML validation is considered harmful, but your pointy-haired boss still labors under the naive impression that it is a best practice.
Ok, fine, you can have your 'data-' prefix
But Old IE?!?
You aren't ready to abandon the poor saps still using ancient versions of IE. Sure, Google stopped supporting them, but you aren't Google.
Just use jQuery (of course) and this tiny extension:
<!--[if lt IE 9]><script src="../src/trigger.old.js"></script><![endif]-->
Another Small Extension
If you see yourself manually using trigger instead of always letting browser events
serve as triggers and also happen to be fond of jQuery, jquery.trigger.js
allows you to do
$('#foo').trigger('foo:squish#gooey'); instead of
Short jQuery Version - For Those Who Don't Need All The Features
Mini-Example, Just For Fun
var game = document;game;game;
- Clicks are ignored if their target was a user-editable field (e.g. textarea) that did not have a click attribute itself, but was a child of an element that did have one.
- Enter keyups (keyCode:13) are treated as clicks if their target lacks a "native response"
to such events (e.g. in a textarea, it adds a new line, or on a link, it causes a click).
The exception being if such an element has a
key-enterattribute declared on it.
- When a click is used by trigger.js, it will automatically prevent the original event's default behavior, except in the case of radio buttons and checkboxes. The assumption is that the default behavior is replaced by the declared event sequence.
This extension hook provides you the opportunity to change event types, with some particular aid for tweaking events that have a 'which' or 'keyCode' important to you. Here's an example:
Note: trigger.js already listens for
click events. For other special events,
like keydown or dblclick, remember to do
<html trigger-add="keydown"> or the like.
TODO: add more advanced details...
- 2010-04-02 v0.1 (internal)
- 2012-09-13 v0.3 (internal)
- 2013-05-03 v0.9.0 (public) - First GitHub release
- 2013-05-16 v1.0.0 (public) - tests and feature completeness
- 2013-05-21 v1.1.0 (public) - declarative configuration