Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Rich, declarative[, custom] event handling

License

MIT, MIT licenses found

Licenses found

MIT
LICENSE
MIT
LICENSE-MIT
NotificationsYou must be signed in to change notification settings

esha/Eventi

Repository files navigation

Powerful application events and event handling, made easy.

Getting Started

Download thefull,minified, orserver versions.Build Status
Bower:bower install eventi
NPM:npm install eventi
Component:component install esha/Eventi

Eventi API

Eventi.fire([target, ]eventi[, data,...])

Creates and dispatches the specified event(s) on the specified target(s), attaching any specified data.

ArgumentsRequiredType(s)DefaultDescription
targetNoObject,Arrayglobal/windowA single target or array of them.
eventiYesString,Event,ArrayOne or more space-delimited Eventi definitions, an Event instance, or an array of either (in which case youmust specify a target argument).
dataNoAny number of arguments that will be put in an Array and attached to all created events as thedata property.

*When passing events in an array, youmust specify a target argument.

Any attached data will be fed to the event listeners as additional arguments after the event itself and any data registered along with the listener itself.

Eventi.fire(user,'account:close',accountId);

Eventi.on([target, ]eventi, fn[, data,...])

Registers the specified function as an event listener for the specified event(s) on the specified target(s).

ArgumentsRequiredType(s)DefaultDescription
targetNoObject,Arrayglobal/windowA single target or array of them.
eventiYesString,ArrayOne or more space-delimited Eventi definitions or an array of them (in which case youmust specify a target argument).
fnYesFunctionThe function to be called when a matching event hits the target(s).
dataNo*Any number of arguments that will be passed directly to the listener function as arguments (after the event argument).

The function argument will be called with the target as its context, the received event as the first argument, and data arguments registered with the listener as the next arguments, and any data arguments attached to the event itself after those.

Eventi.on(user,'account:open',function(e){console.log('Event: type='+e.type+' category='+e.category,this/* will be user */);});

Eventi.on([targets, ]{ eventi:fn,... })

Overloading ofon() for convenient registration of multiple listeners at once. Iterates over the object argument, registering key/value pairs as eventi/fn pairs.

Eventi.on(user,{'account:open',function(e){console.log('Event: type='+e.type+' category='+e.category,this/* will be user */);},'account:close',function(e,accountId){console.log('User: '+this.id+' is closing account '+accountId);}});

eventi="eventi ..."

Registers event listeners on the element that search between an Event's target and the listening element for an element with a handler attribute (e.g.data-click="...") telling the listener how to handle the event.

Attributes | Required | Content | Description--------- | -------- | ------- | ------- | -----------eventi, data-eventi | For all events exceptclick | Space-delimited Eventi definitions | Defines listeners for an element.{alias}, data-{alias} | No | Element function, global function, Eventi definition | Either a reference to the function to be called, an Eventi definition to be fired on the element, or nothing, in which case the alias is used as the content.

<divid="admin"data-eventi="/beforeunload=>save keyup[delete]<.account>=>delete"><ulclass="accounts"><liclass="account"tabindex="0"delete="account:close">Savings</li>        ...</ul><buttonclick="account:open">New Account</button></div>

Eventi.off([targets, ][eventi, ][fn])

Unregisters event listeners that match the specified event(s) and/or function on the specified target(s), or the global/window object, if none is specified.

ArgumentsRequiredType(s)DefaultDescription
targetNoObject,Arrayglobal/windowA single target or array of them.
eventiNoString,ArrayOne or more space-delimited Eventi definitions (or portions thereof) or an array of them (in which case you must specify a target argument)
fnNoFunctionThe specific listener function to be removed.
Eventi.off(user,'account:');

Eventi.alias([context, ]eventi,...)

Defines aliases for the events specified. It creates sub-functions foron(),off(), andfire() under the alias (or simple type if no alias is defined).

ArgumentsRequiredTypeDefaultDescription
contextNoObjectEventiAn object that has been run through Eventi.fy() whose methods you want the aliases set for.
eventiYesStringOne or more event space-delimited Eventi definitions.
Eventi.alias('account:request#freeze=>hold');Eventi.on.hold(user,function(e,admin){console.log(admin.id+' is requesting freeze for '+user.id+' accounts');});//...Eventi.fire.hold(user,admin);

Eventi.fy(target)

Convenience tool that simply defineson(),off(), andfire(), making the specified target object the context and target for those functions.

ArgumentsRequiredTypeDefaultDescription
contextYesObjectA target object you would like to call fire/on/off upon directly.
Eventi.fy(user);user.on('account:open',function(e){console.log('Open new account for '+this/* will be user */);});
Eventi.fy(Element.prototype);// lets you call Eventi functions on all DOM elements

Eventi Syntax

Core - Defining What's What

Type

Example definition:open

This is the central, "action" portion in an Eventi definition. It isnot optional in most definitions, with the exception of calls tooff(). It is what you have left after you strip off all the other event and handler properties described below here. It is an Event instance'stype property. This should typically be a simple verb, in present or past tense.

vare=newEventi('open');console.log(e.type);// outputs 'open'

Category:

Example definition:account:open

This is the "subject" option in an Eventi definition. The category always precedes the type and is delimited from it by a:. It is an Eventi instance'scategory property. This should typically be a simple noun, and represent the subject or owner of a set of events. It is good practice to provide a category for your events unless you specifically mean them to be broadly applied.

vare=Eventi.fire('account:open');console.log(e.category);// outputs 'account'

#Tags

Example definition:move#up#left

These are the "adverb" or "adjective" portions of Eventi definitions. They always follow the type and are delimited from it and each other by#. When creating an Event, they are set together in an array on the instance as thetags property and each individual tag is set on the instance as a property with a value oftrue. Use these to distinguish related sub-types of events or provide simple annotations for the subject or object of an event.

Eventi.on('open#new',function(e){if(e.unverified){console.log(e.tags.join(' & '));// outputs 'new & unverified'}}).fire('open#new#unverified');

(Detail)

Example definition:account:label(["verified","gold"])

This is the "object" portion of an Eventi definition. It follows the type and is delimited by( and). The contents may be either JSON (which will get parsed), a reference to a global value (which will be resolved), or an arbitrary string. The result is an instance'sdetail property. Use this to declaratively attach contextual information for an event at the moment it is created.

window.user={name:"jdoe123"};vare=Eventi.fire('like(user.name)');console.log(e.detail);// outputs 'jdoe123'

Browser - Environment Awareness

<.Delegate>

Example definition:cancel<.transaction>

This specifies a selector for event delegation and is delimited by< and>. It instructs a listener to only react to events happening within the bounds of elements matching the specified selector and to use the matching element as the context for the handling function.

Eventi.on('change<[type=checkbox]>',function(e){console.log(this.type);// always outputs 'checkbox'});

[Key]

Example definition:keyup[delete]

This specifies a key or combination thereof, by either keyCode or description, and is delimited by[ and]. It instructs a listener to only react when the event has the appropriate keyCode/ctrlKey/metaKey/shiftKey/altKey properties. Particular keyCodes may be specified explicitly (e.g.keydown[33]), but many have been given English or symbolic equivalents for the sake of readable code (e.g.keypress[z]). These are stored in theEventi._.codes object and are keyup-based values, sokeydown andkeypress definitions shouldbe wary of those outside ASCII. The other key-related event properties are set simply by giving them- as a suffix (e.g.[shift-13] ->e.shiftKey = true,[meta-] ->e.metaKey = true, etc).

The [Key] syntax is also special in that it will providekeyup as the type for event listeners (foron()only) that have a [Key] specified, but no type. Typically, event listeners with no type are never executed.

Eventi.on(field,'[shift-enter]',function(e){console.log(e.shiftKey,e.keyCode);// outputs 'true 13'});

@Location

Example definition:keypress[escape]@/edit

This specifies a url pattern that is matched against the currentwindow.location to filter event listener execution.

There are three types of@ location values:

@/vanilla#string - Will be directly matched against the URL string retrieved fromwindow.location.
@?mini={template} - Turns the sections in braces into wildcard matches (breaking on\,?, and#) whose values are gathered into a key/value object, passed as the 2nd argument to the event handler.
@`reg[ular]+Exp?` - For more complicated matching, use a regular expression. Use ` to delimit it. Handlers will receive the full match as the 2nd argument (after the event itself) and matching groups as subsequent arguments. Any handler or event data args will follow the location matching arguments.

Like [Key], @Location enables shorthand definitions by setting 'location' as the type for event listeners (foron()only) that have a location property, but no type property.

Eventi.on('save@#file={filename}',function(e,vals,folder){console.log('Saved '+vals.filename+' in '+folder);// outputs 'Saved image.png in /pics'});window.location.hash='file=image.png';Eventi.fire('save','/pics');
location@Location

Eventi also provides a unifiedlocation event that is dispatched on thewindow whenever the current location changes, whether viahashchange andpopstate events or calls tohistory.pushState (which gets its ownpushstate event as well). When registering a listener for alocation event, the location is promptly tested (as if alocation event was fired), allowing immediate execution of handlers for currently matching locations. Also, when alocation type event is dispatched (e.g.fire('location@/path')), the @Location will be used to updatewindow.location viahistory.pushState.

// assume URL is http://esha.github.io/ to startvars='';Eventi.on('location',function(e){s+=' '+e.location;});window.location.hash='hash';history.pushState(null,'push it','?push');history.go(-2);// popstateconsole.log(s);// outputs ' / /#hash /?push /#hash /'
Eventi.on('@/login',function(e,match){// will listen for 'location' typeconsole.log(e.type,match);// outputs 'location login'});Eventi.fire('location@/login');

@Location's mini-templates can work in reverse when updating the location via event. Just pass a key/value object back as the first data argument (either at listener registration or event firing).

Eventi.fire('location@?page={page}',{page:2});window.location.search==='?page=2';// true

Just to spell it out, the sum of these flexible and easy location features is a powerful event-based application router.

Control - For Special Handling

_NoBubbles

Example definition:_hide

This simply tells the dispatching code not to let an event propogate beyond the immediate target. Include a_ in the control characters at the start of an event definition to set thebubbles property to false.

Eventi.on('test',function(e){console.log('Element events will never get here if they do not bubble.');});Eventi.fire(document.getElementById('hideme'),'_test');

/Global

Example definition:/login

This registers the listener on the global/window object but executes handler functions in the context for which they are registered. Include a/ in the control characters at the start of an event definition to assign the listener globally.

varbuttons=document.querySelector('button,[type=submit]');Eventi.on(buttons,'/ajaxStart',function(e){this.disabled=true;});

^Singleton

Example definition:^ready

Including^ in an event definition's control characters identifies it as a "singleton". The simplest way to explain these is that they are the event-equivalent of jQuery's ready() function. Once a singleton event is dispatched or received, it is remembered so that registered listeners execute no more than once and listeners registered after a singleton event is dispatched will be immediately executed with the remembered event. It's a once-for-all kind of deal. Events that go throughfire() marked as singletons are automatically remembered for every target hit. When registering a listener for a singleton event that has not yet been fired, any matching event (marked singleton or not) will be remembered on the listener's target alone, for subsequent registrations. And yes, Eventi automatically watches forDOMContentLoaded and fires a^ready event on the document element.

Eventi.on({'^ready':function(){loadAsync('globalResource').then(function(resource){Eventi.fire('^resource:loaded',resource);});},'^resource:loaded':function(e,resource){// use resource here}});

$End

Example definition:login$1

Not all event listeners are meant to last forever. You may declare a listener's end when registering it by appending a$ and a condition to the event definition. The condition may be either a number (indicating the number of executions allowed), a reference to a value (either a property of the context or global/window), or a reference to a function that will return such a value. In the case of a value, you may also prefix it with! to reverse the condition. The "end declaration" follows all features of a definition except an alias. The most common is, of course,$1 for single-use listeners.

Eventi.on(player,'death$!player.livesLeft',player.respawn);
Eventi.on('load$1',Plugins.init);

!Important

Example definition:!location

A! control character in the front of an event definition is only relevant when you try tooff() it. Listeners defined as "important" may only be unregistered by a fully-matching definition given tooff(), including the!. This exists mostly to protect "internal" listeners (both Eventi's own and extensions) from being errantly unregistered.

Eventi.on('!demo',function(){console.log('still here!');});Eventi.off('demo');Eventi.fire('demo');// will output 'still here!'

=>Alias

Example definition:account:notify#SMS(balance)=>textme

Aliases are used by eitheralias() ordata-eventi definitions to provide a simple alias for safely and conveniently referencing event definitions (particularly complicated ones). These arestrongly recommended for any complex definitions that are repeated in your JavaScript. And, of course, fordata-eventi declarations, they are unavoidable.

Eventi.alias('/user:logout=>shutdown');Eventi.on.shutdown(function(){// look ma, no typos!});

Multiplicity - Beyond Definition Boundaries

The following syntax options are uber-syntax for working with multiple,separate definitions. No syntax features can be shared across definitions conjoined by spaces, commas, or plus symbols.

"Multiple Events"

Example definition:keyup[enter] blur

Allows you to dispatch, register, unregister, or alias multiple event definitions in the same call.

Eventi.on(editor,'keyup[ctrl-s] blur submit',function(){Eventi.fire('service:send local:save');});

"Event,Sequences"

Example definition:validate,save

Allows you to dispatch or listen for a connected, ordered sequence of events. This is another feature adapted fromtrigger (read this!). The concepts are the same, only the delimiter (now,) and the API given to sequenced events have changed:

event.index - The index of this Event in the sequence.
event.previousEvent - The preceding Event instance (if any).
event.sequence - The array of Eventi definitions in the sequence.
event.pauseSequence([promise]) - Pauses the firing of the sequence. If a Promise (or other "then-able" object) is given as argument, it will automatically resume upon successful resolution of the promise. This makes async event sequences very straightforward!
event.isSequencePaused() - Returns a Boolean indicating if the sequence has been paused.
event.resumeSequence([index]) - Resumes a paused sequence at either the specified index or the next index in the sequence.

Eventi.on('validate',function(e){varpromise=asyncValidate($(this).closest('form'));e.pauseSequence(promise);});
<form>...<buttonclick="validate,save,location@/home">Save and Quit</button></form>

Unliketrigger, Eventi also allows you to register listeners for event sequences as well. Such sequences can be fired as sequences (as above) or separately. You may also specify a time in milliseconds as the first data argument, in order to restrict the timeframe for sequence completion.

Eventi.on(editor,'keyup[a],keyup[s],keyup[d],keyup[f]',function(){console.log('Fake typing!');},500);

"Combo+Events"

Example definition:scroll+click

Allows you to listen for an unordered group of related events before executing the handler function. This is exactly like registering a listener for a sequence of events, except that the order in which the events are received is ignored (or irrelevant).

Eventi.on(editor,'click+click+click',function(){Eventi.fire(this,'tripleclick');},200);

And yes, you can mix combos and sequences. When doing so, sequences events will be sub-events of combos, not vice versa.

Release History

  • 2014-02-11v0.5.0 (alpha)
  • 2014-04-03v1.0.0 (beta)
  • 2014-04-04v1.0.1 (beta - IE fixes)
  • 2014-04-09v1.0.2 (beta - toString and location fix)
  • 2014-04-17v1.1.0 (beta - restructure artifacts, small improvements)
  • 2014-04-21v1.2.0 (beta - docs, space-delimited alias arguments, artifact changes, optionaldata- prefixes, combo fix)
  • 2014-04-22v1.2.1 (beta - docs, shorthand type for [key] and @location)
  • 2014-04-24v1.3.0 (beta - server fixes, nodeunit tests, dual Eventi ctor)
  • 2014-04-29v1.3.1 (beta - jquery integration aid)
  • 2014-08-15v1.3.2 (beta - swap alias/delegate parser order)
  • 2014-08-18v1.3.3 (beta - fix click/enter handling in declare)
  • 2014-08-19v1.3.4 (beta - properly handle form elements as targets)
  • 2014-10-15v1.3.5 (beta - location event fixes)
  • 2014-10-20v1.3.6 (beta - location event fix, use sourcemap friendly main file for bower package)
  • 2014-10-20v1.3.7 (beta - add main entry to package.json)

[8]ページ先頭

©2009-2025 Movatter.jp