Comparing version 0.7.1 to 1.0.0
{ | ||
"name": "eventi", | ||
"version": "0.7.1", | ||
"version": "1.0.0", | ||
"homepage": "https://github.com/nbubna/Eventi", | ||
@@ -5,0 +5,0 @@ "bugs": "https://github.com/nbubna/nbubna/issues", |
{ | ||
"name": "eventi", | ||
"repo": "nbubna/Eventi", | ||
"version": "0.7.1", | ||
"version": "1.0.0", | ||
"keywords": [ | ||
@@ -6,0 +6,0 @@ "event", |
@@ -1,2 +0,2 @@ | ||
/*! Eventi - v0.7.1 - 2014-03-13 | ||
/*! Eventi - v1.0.0 - 2014-04-03 | ||
* https://github.com/nbubna/Eventi | ||
@@ -22,2 +22,3 @@ * Copyright (c) 2014 ESHA Research; Licensed MIT */ | ||
}; | ||
if (!global.Event){ global.Event = global.CustomEvent; } | ||
} | ||
@@ -31,8 +32,8 @@ | ||
copy: function(a, b, p) { | ||
if (a){ for (p in a){ if (a.hasOwnProperty(p)){ b[p] = a[p]; }}} | ||
if (typeof a === "object"){ for (p in a){ if (a.hasOwnProperty(p)){ b[p] = a[p]; }}} | ||
}, | ||
async: global.setImmediate || function async(fn){ return setTimeout(fn, 0); }, | ||
resolveRE: /^([\w\$]+)?((\.[\w\$]+)|\[(\d+|'(\\'|[^'])+'|"(\\"|[^"])+")\])*$/, | ||
resolve: function(reference, context) { | ||
if (_.resolveRE.test(reference)) { | ||
resolve: function(reference, context, tested) { | ||
if (tested || _.resolveRE.test(reference)) { | ||
context = context || global; | ||
@@ -47,6 +48,6 @@ try { | ||
var props = { text: type+'' }; | ||
type = _.parse(props.text, props); | ||
type = _.parse(props.text, props, props); | ||
_.copy(copyThese, props); | ||
if (!('bubbles' in props)) { | ||
props.bubbles = true;// must bubble by default | ||
props.bubbles = true;// we bubble by default around here | ||
} | ||
@@ -64,53 +65,48 @@ | ||
prop: function(prop){ return prop; },// only an extension hook | ||
parse: function(type, props) { | ||
_.properties.forEach(function(property) { | ||
parse: function(type, event, handler) { | ||
_.parsers.forEach(function(property) { | ||
type = type.replace(property[0], function() { | ||
return property[1].apply(props, arguments) || ''; | ||
var args = _.slice(arguments, 1); | ||
args.unshift(event, handler); | ||
return property[1].apply(event, args) || ''; | ||
}); | ||
}); | ||
return type ? props.type = type : type; | ||
return type ? event.type = type : type; | ||
}, | ||
properties: [ | ||
[/^_/, function nobubble() { | ||
this.bubbles = false; | ||
parsers: [ | ||
[/^(\W*)_/, function(event, handler, other) { | ||
event.bubbles = false; | ||
return other; | ||
}], | ||
[/^\!/, function protect() {// | ||
this._protect = true; | ||
}], | ||
[/\((.*)\)/, function detail(m, val) { | ||
[/\((.*)\)/, function(event, handler, val) { | ||
try { | ||
this.detail = _.resolve(val) || JSON.parse(val); | ||
event.detail = _.resolve(val) || JSON.parse(val); | ||
} catch (e) { | ||
this.detail = val; | ||
event.detail = val; | ||
} | ||
}], | ||
[/#(\w+)/g, function tags(m, tag) { | ||
(this.tags||(this.tags=[])).push(tag); | ||
this[tag] = true; | ||
[/#(\w+)/g, function(event, handler, tag) { | ||
(event.tags||(event.tags=[])).push(tag); | ||
event[tag] = true; | ||
}], | ||
[/^(\w+):/, function category(m, cat) {// | ||
this.category = cat; | ||
[/^(\w+):/, function(event, handler, cat) {// | ||
event.category = cat; | ||
}] | ||
], | ||
splitRE: / (?![^\(\)]*\))+/g, | ||
wrap: function(name, expect, index) { | ||
index = index || 1; | ||
var wrapper = function wrapper(target) { | ||
wrap: function(name, dataIndex) { | ||
return function wrapper(target) { | ||
var args = _.slice(arguments); | ||
// ensure target param precedes event text | ||
if (!target || typeof target === "string") { | ||
target = !this || this === Eventi ? _.global : this; | ||
args.unshift(target); | ||
if (!target || typeof target === "string" || target instanceof global.Event) {// ensure target | ||
args.unshift(target = !this || this === Eventi ? _.global : this); | ||
} | ||
// ensure array of event text inputs | ||
args[index] = args[index] ? (args[index]+'').split(_.splitRE) : ['']; | ||
// gather ...data the old way | ||
if (args.length > expect) { | ||
args[expect] = args.slice(expect); | ||
args = args.slice(0, expect+1); | ||
if (args.length > dataIndex) {// gather ...data the old way | ||
args[dataIndex] = args.slice(dataIndex); | ||
args = args.slice(0, dataIndex+1); | ||
} | ||
// call fn for each target | ||
if (!args[1] || typeof args[1] === "string") { | ||
args[1] = _.split.ter(args[1]); | ||
} | ||
var fn = _[name], ret; | ||
if ('length' in target && target !== _.global) { | ||
if ('length' in target && target !== _.global) {// apply to each target | ||
for (var i=0,m=target.length; i<m; i++) { | ||
@@ -122,8 +118,45 @@ ret = fn.apply(args[0] = target[i], args); | ||
} | ||
// be fluent | ||
return ret === undefined ? this : ret; | ||
return ret === undefined ? this : ret;// be fluent | ||
}; | ||
wrapper.index = index; | ||
return wrapper; | ||
} | ||
}, | ||
split: { | ||
guard: { '(':')' }, | ||
ter: function(texts, delims) { | ||
var parts = [], | ||
text = '', | ||
guard; | ||
if (texts) { | ||
delims = _.slice(arguments, 1); | ||
delims.unshift(' '); | ||
for (var i=0,m=texts.length; i<m; i++) { | ||
var c = texts.charAt(i); | ||
if (!guard && delims.indexOf(c) >= 0) { | ||
if (text) { | ||
parts.push(text); | ||
} | ||
text = ''; | ||
} else { | ||
text += c; | ||
if (guard) { | ||
if (guard === c) { | ||
if (text.charAt(text.length-2) === '\\') { | ||
text = text.replace("\\"+c, c); | ||
} else { | ||
guard = null; | ||
} | ||
} | ||
} else { | ||
guard = _.split.guard[c]; | ||
} | ||
} | ||
} | ||
if (text) { | ||
parts.push(text); | ||
} | ||
} else { | ||
parts.push(''); | ||
} | ||
return parts; | ||
} | ||
} | ||
}; | ||
@@ -141,13 +174,13 @@ Eventi._ = _; | ||
_.fire = function(target, events, props, data) { | ||
if (typeof props === "object" && !(props instanceof Event) && | ||
('bubbles' in props || 'detail' in props || 'cancelable' in props)) { | ||
props.data = data; | ||
} else { | ||
if (props !== undefined) { | ||
data = data ? data.unshift(props) && data : [props]; | ||
} | ||
props = { data: data }; | ||
_.parsers.unshift([/^(\W*)\//, function(event, handler, other) { | ||
handler.global = true; | ||
return other; | ||
}]); | ||
_.fire = function(target, events, data) { | ||
if (events instanceof Event) { | ||
events.data = data; | ||
_.dispatch(target, events); | ||
return events; | ||
} | ||
return _.fireAll(target, events, props); | ||
return _.fireAll(target, events, {data:data}); | ||
}; | ||
@@ -163,2 +196,3 @@ _.fireAll = function(target, events, props) { | ||
_.dispatch = function(target, event, objectBubbling) { | ||
if (event.global){ target = _.global; } | ||
(target.dispatchEvent || target[_key] || _.noop).call(target, event); | ||
@@ -169,30 +203,36 @@ if (target.parentObject && event.bubbles && !event.propagationStopped) { | ||
// icky test/call, but lighter than wrapping or firing internal event | ||
if (!objectBubbling && event._singleton) { | ||
if (!objectBubbling && event.singleton) { | ||
_.singleton(target, event); | ||
} | ||
}; | ||
Eventi.fire = _.wrap('fire', 3); | ||
_.on = function(target, events, selector, fn, data) { | ||
// adjust for absence of selector | ||
if (typeof selector === "function") { | ||
Eventi.fire = _.wrap('fire', 2); | ||
_.parsers.unshift([/^(\W*)\!/, function(e, handler, other) {// | ||
handler.important = true; | ||
return other; | ||
}]); | ||
_.on = function(target, events, fn, data) { | ||
if (!Array.isArray(events)) { | ||
if (fn !== undefined) { | ||
data = data ? data.unshift(fn) && data : [fn]; | ||
} | ||
fn = selector; selector = null; | ||
for (var event in events) { | ||
_.handler(target, event, events[event], data); | ||
} | ||
} else { | ||
for (var i=0,m=events.length; i<m; i++) { | ||
_.handler(target, events[i], fn, data); | ||
} | ||
} | ||
for (var i=0,m=events.length; i<m; i++) { | ||
_.handler(target, events[i], selector, fn, data); | ||
} | ||
}; | ||
_.handler = function(target, text, selector, fn, data) { | ||
//TODO: consider moving selector into match, so we can specifically off delegates | ||
var handler = { target:target, selector:selector, fn:fn, data:data, text:text, match:{} }; | ||
_.parse(text, handler.match); | ||
delete handler.match.tags;// superfluous for matching | ||
_.handler = function(target, text, fn, data) { | ||
var handler = { target:target, fn:fn, data:data, text:text, event:{} }; | ||
_.parse(text, handler.event, handler); | ||
delete handler.event.tags;// superfluous for handlers | ||
if (target !== _) {// ignore internal events | ||
Eventi.fire(_, 'handler#new', handler); | ||
Eventi.fire(_, 'on:handler', handler); | ||
} | ||
// allow handler#new listeners to change these things | ||
// allow on:handler listeners to change these things | ||
if (handler.fn !== _.noop) { | ||
_.handlers(handler.target, handler.match.type).push(handler); | ||
target = handler.global === true ? _.global : handler.target; | ||
_.handlers(target, handler.event.type).push(handler); | ||
} | ||
@@ -228,53 +268,68 @@ return handler; | ||
}; | ||
_.handle = function(event, handlers) { | ||
for (var i=0, handler, target; i<handlers.length; i++) { | ||
if (_.matches(event, (handler = handlers[i]).match)) { | ||
if (target = _.target(handler, event.target)) { | ||
_.execute(target, event, handler); | ||
if (event.immediatePropagationStopped){ break; } | ||
} | ||
for (var i=0, handler; i<handlers.length; i++) { | ||
if (_.matches(event, (handler = handlers[i]).event)) { | ||
_.execute(event, handler); | ||
if (event.immediatePropagationStopped){ break; } | ||
} | ||
} | ||
}; | ||
_.execute = function(target, event, handler) { | ||
var args = [event]; | ||
_.execute = function(event, handler) { | ||
var args = [event], | ||
fn = handler.fn, | ||
call = { target: handler.target, args:args }; | ||
if (event.data){ args.push.apply(args, event.data); } | ||
if (handler.data){ args.push.apply(args, handler.data); } | ||
try { | ||
handler.fn.apply(target, args); | ||
} catch (e) { | ||
_.async(function(){ throw e; }); | ||
if (handler.filters) { | ||
for (var i=0,m=handler.filters.length; i<m && call.target; i++) { | ||
handler.filters[i].call(call, event, handler); | ||
} | ||
} | ||
if (call.target) { | ||
try { | ||
fn.apply(call.target, call.args); | ||
} catch (e) { | ||
_.async(function(){ throw e; }); | ||
} | ||
if (handler.end && handler.end.apply(call.target, call.args)) { | ||
_.unhandle(handler); | ||
} | ||
} | ||
}; | ||
_.filter = function(handler, fn) { | ||
handler.filters = handler.filters || []; | ||
handler.filters.push(fn); | ||
}; | ||
_.unhandle = function noop(handler){ handler.fn = _.noop; }; | ||
_.matches = function(event, match, strict) { | ||
_.matches = function(event, match) { | ||
for (var key in match) { | ||
if (match[key] !== event[key] && (strict || key.charAt(0) !== '_')) { | ||
if (match[key] !== event[key]) { | ||
return false; | ||
} | ||
} | ||
if (strict) { | ||
for (key in event) { | ||
if (key.charAt(0) === '_' && event[key] !== match[key]) { | ||
return false; | ||
} | ||
} | ||
} | ||
return true; | ||
}; | ||
_.target = function(handler, target) { | ||
return handler.selector ? _.closest(target, handler.selector) : handler.target; | ||
}; | ||
_.closest = function(el, selector) { | ||
while (el && el.matches) { | ||
if (el.matches(selector)) { | ||
return el; | ||
} | ||
el = el.parentNode; | ||
Eventi.on = _.wrap('on', 3); | ||
_.split.guard['<'] = '>'; | ||
_.parsers.unshift([/<(.+)>/, function(event, handler, selector) { | ||
handler.selector = selector; | ||
if (_.delegate && event !== handler) { | ||
_.filter(handler, _.delegate); | ||
} | ||
}; | ||
}]); | ||
if (global.Element) { | ||
_.delegate = function delegate(event, handler) { | ||
this.target = _.closest(event.target, handler.selector); | ||
}; | ||
_.closest = function(el, selector) { | ||
while (el && el.matches) { | ||
if (el.matches(selector)) { | ||
return el; | ||
} | ||
el = el.parentNode; | ||
} | ||
}; | ||
var Ep = Element.prototype, | ||
@@ -287,4 +342,9 @@ aS = 'atchesSelector'; | ||
Eventi.on = _.wrap('on', 4); | ||
_.parsers.unshift([/=>(\w+)$/, function(event, handler, alias) { | ||
handler.alias = alias; | ||
if (handler !== event) { | ||
handler.data = handler.data || []; | ||
handler.data.push(alias); | ||
} | ||
}]); | ||
if (document) { | ||
@@ -294,6 +354,10 @@ _.init = function init() { | ||
for (var i=0,m=nodes.length; i<m; i++) { | ||
var node = nodes[i], | ||
mapping = node.getAttribute('data-eventi'); | ||
if (mapping) { | ||
_.declare(mapping, node); | ||
var target = nodes[i], | ||
mapping = target.getAttribute('data-eventi'); | ||
if (mapping !== target.eventi) { | ||
if (_.off && target.eventi) { | ||
Eventi.off(target, target.eventi, _.declared); | ||
} | ||
target.eventi = mapping; | ||
_.declare(target, mapping); | ||
} | ||
@@ -305,41 +369,35 @@ } | ||
}; | ||
_.declare = function(mapping, mapper) {// register listener | ||
var types = mapping.split(_.splitRE); | ||
for (var i=0,m=types.length; i<m; i++) { | ||
var type = types[i], | ||
eq = type.lastIndexOf('='), | ||
alias = eq > 0 ? type.substring(eq+1) : undefined, | ||
global = type.charAt(0) === '/', | ||
context = global ? _.global : mapper; | ||
mapper = mapper || document; | ||
if (alias){ type = type.substring(0, eq); } | ||
if (global){ type = type.substring(1); } | ||
Eventi.on(context, type, _.mapped, mapper, alias); | ||
_.declare = function(target, mapping) {// register listener | ||
var texts = _.split.ter(mapping); | ||
for (var i=0,m=texts.length; i<m; i++) { | ||
Eventi.on(target, texts[i], _.declared); | ||
} | ||
}; | ||
_.mapped = function(e, mapper, alias) {// lookup handlers | ||
var type = alias || e.type, | ||
nodes = _.declarers(mapper, type, this !== _.global && e.target); | ||
_.declared = function(e, alias) {// lookup handlers | ||
alias = typeof alias === "string" ? alias : e.type; | ||
var nodes = _.declarers(this, alias, e.target); | ||
for (var i=0,m=nodes.length; i<m; i++) { | ||
_.declared(nodes[i], type, e); | ||
_.respond(nodes[i], alias, e); | ||
} | ||
}; | ||
_.declarers = function(mapper, type, target) { | ||
var query = '['+type+']'; | ||
if (target) { | ||
// gather matching parents up to the mapper | ||
var nodes = []; | ||
while (target && target.matches && target !== mapper.parentNode) { | ||
if (target.matches(query)) { | ||
nodes.push(target); | ||
} | ||
target = target.parentNode; | ||
_.declarers = function(target, alias, node) { | ||
var query = '['+alias+']', | ||
// gather matching parents up to the target | ||
nodes = [], | ||
descendant = false; | ||
while (node && node.matches) { | ||
if (node.matches(query)) { | ||
nodes.push(node); | ||
} | ||
return nodes; | ||
if (node === target) { | ||
descendant = true; | ||
break; | ||
} | ||
node = node.parentNode; | ||
} | ||
// gather all declarations within the mapper | ||
return mapper.querySelectorAll(query); | ||
// if node isn't a descendant of target, handler must be global | ||
return descendant ? nodes : target.querySelectorAll(query); | ||
}; | ||
_.declared = function(node, type, e) {// execute handler | ||
var response = node.getAttribute(type); | ||
_.respond = function(node, alias, e) {// execute handler | ||
var response = node.getAttribute(alias); | ||
if (response) { | ||
@@ -355,6 +413,7 @@ var fn = _.resolve(response, node) || _.resolve(response); | ||
_.check = function(e) { | ||
var click = (e.type === 'click' && _.click(e.target)) || | ||
(e.keyCode === 13 && _.click(e.target, true)); | ||
var click = e.target.getAttribute && | ||
((e.type === 'click' && _.click(e.target)) || | ||
(e.keyCode === 13 && _.click(e.target, true))); | ||
if (click) { | ||
_.mapped(e, document.documentElement, 'click'); | ||
_.declared.call(document.documentElement, e, 'click'); | ||
if (click === 'noDefault' && !_.allowDefault(e.target)) { | ||
@@ -394,3 +453,9 @@ e.preventDefault(); | ||
// add singleton to _.parse's supported event properties | ||
_.properties.unshift([/^\^/, function singleton(){ this._singleton = true; }]); | ||
_.parsers.unshift([/^(\W*)\^/, function(event, handler, other) { | ||
handler.singleton = true; | ||
if (event !== handler) { | ||
_.filter(handler, _.before); | ||
} | ||
return other; | ||
}]); | ||
@@ -413,14 +478,12 @@ // _.fire's _.dispatch will call this when appropriate | ||
}; | ||
_.before = function singleton(event, handler) { | ||
_.unhandle(handler); | ||
handler.fn = _.noop;// tell _.handler not to keep this | ||
if (!event[_skey]) {// remember this non-singleton as singleton for handler's sake | ||
_.remember(this.target, event); | ||
} | ||
}; | ||
Eventi.on(_, 'handler#new', function singleton(e, handler) { | ||
if (handler.match._singleton) { | ||
var fn = handler._fn = handler.fn; | ||
handler.fn = function singleton(e) { | ||
_.unhandle(handler); | ||
if (!e[_skey]) {// remember this non-singleton as singleton for handler's sake | ||
_.remember(handler.target, e); | ||
} | ||
fn.apply(this, arguments); | ||
}; | ||
Eventi.on(_, 'on:handler', function singleton(e, handler) { | ||
if (handler.singleton) { | ||
// search target's saved singletons, execute handler upon match | ||
@@ -430,9 +493,5 @@ var saved = handler.target[_skey]||[]; | ||
var event = saved[i]; | ||
if (_.matches(event, handler.match)) { | ||
var target = _.target(handler, event.target); | ||
if (target) { | ||
_.execute(target, event, handler); | ||
handler.fn = _.noop;// tell _.handler not to keep this | ||
break; | ||
} | ||
if (_.matches(event, handler.event)) { | ||
_.execute(event, handler); | ||
break; | ||
} | ||
@@ -445,17 +504,16 @@ } | ||
Eventi.on('DOMContentLoaded', function ready(e) { | ||
_.fire(document.documentElement, ['^ready'], undefined, [e]); | ||
Eventi.fire(document.documentElement, '^ready', e); | ||
}); | ||
} | ||
// add key syntax to _.parse's supported event properties | ||
_.keyRE = /\[([a-z-0-9,\.\/\[\`\\\]\']+)\]/; | ||
_.properties.push([_.keyRE, function parseKey(m, name) { | ||
var dash, key; | ||
while ((dash = name.indexOf('-')) > 0) { | ||
key = name.substring(0, dash); | ||
name = name.substring(dash+1); | ||
this[(_.special[key]||key)+'Key'] = true; | ||
_.split.guard['['] = ']'; | ||
_.parsers.push([/\[([^ ]+)\]/, function(event, handler, key) {//' | ||
var dash; | ||
while ((dash = key.indexOf('-')) > 0) { | ||
event[key.substring(0, dash)+'Key'] = true; | ||
key = key.substring(dash+1); | ||
} | ||
this.keyCode = _.codes[name] || parseInt(name, 10) || 0; | ||
if (key) { | ||
event.keyCode = _.codes[key] || parseInt(key, 10) || key; | ||
} | ||
}]); | ||
_.special = { command: 'meta', apple: 'meta' }; | ||
_.codes = { | ||
@@ -465,3 +523,3 @@ backspace:8, tab:9, enter:13, shift:16, ctrl:17, alt:18, capsLock:20, escape:27, start:91, command:224, | ||
multiply:106, plus:107, minus:109, point:110, divide:111, numLock:144,// numpad controls | ||
',':188, '.':190, '/':191, '`':192, '[':219, '\\':220, ']':221, '\'':222, space:32// symbols | ||
';':186, '=':187, ',':188, '-':189, '.':190, '/':191, '`':192, '[':219, '\\':220, ']':221, '\'':222, space:32// symbols | ||
}; | ||
@@ -473,91 +531,100 @@ for (var n=0; n<10; n++){ _.codes['num'+n] = 96+n; }// numpad numbers | ||
}); | ||
var h = global.history, | ||
l = global.location; | ||
_.pushState = h.pushState; | ||
h.pushState = function() { | ||
var ret = _.pushState.apply(this, arguments); | ||
_.dispatch(_.global, new Eventi('pushstate', {uri:arguments[2]})); | ||
return ret; | ||
}; | ||
Eventi.on('!popstate !hashchange !pushstate', _.at = function(e, uri) { | ||
uri = uri || decodeURI(l.pathname + l.search + l.hash); | ||
if (uri !== _.uri) { | ||
_.dispatch(_.global, new Eventi('location', { | ||
oldURI: _.uri, | ||
uri: _.uri = uri, | ||
srcEvent: e | ||
})); | ||
_.split.guard['@'] = '@'; | ||
_.parsers.unshift([/@([^@]+)(@|$)/, function(event, handler, uri) { | ||
handler.location = uri; | ||
if (_.location && event !== handler) { | ||
_.locationHandler(uri, handler); | ||
} | ||
return uri; | ||
}) | ||
.on('!location', function setUri(e, uri, fill) { | ||
if (typeof uri === "string") { | ||
var keys = _.keys(uri); | ||
if (keys) { | ||
uri = keys.reduce(function(s, key) { | ||
return s.replace(new RegExp('\\{'+key+'\\}',"g"), | ||
fill[key] || global.location[key] || ''); | ||
}, uri); | ||
}]); | ||
if (global.history && global.location) { | ||
var current; | ||
_.pushState = history.pushState; | ||
history.pushState = function() { | ||
var ret = _.pushState.apply(this, arguments); | ||
_.dispatch(_.global, new CustomEvent('pushstate')); | ||
return ret; | ||
}; | ||
_.location = function(e, uri) { | ||
uri = uri || decodeURI(location.pathname + location.search + location.hash); | ||
if (uri !== current) { | ||
_.dispatch(_.global, new Eventi('location', { | ||
oldLocation: current, | ||
location: current = uri, | ||
srcEvent: e | ||
})); | ||
} | ||
e.uri = uri; | ||
if (uri !== _.uri) { | ||
h.pushState(null,null, encodeURI(uri)); | ||
return current; | ||
}; | ||
_.setLocation = function(e, uri, fill) { | ||
if (typeof uri !== "string") { | ||
fill = uri; | ||
uri = e.location; | ||
} | ||
} else if (!e.uri) { | ||
e.uri = _.uri; | ||
} | ||
}) | ||
.on(_, 'handler#new', function location(e, handler) { | ||
if (handler.match.type === "location") { | ||
// always listen on window, but save given target to use as context | ||
handler._target = handler.target; | ||
handler.target = _.global; | ||
if (handler.selector) { | ||
// overloading on.js' selector argument with uri template/regex | ||
var re = handler.selector; | ||
delete handler.selector; | ||
if (typeof re === "string") { | ||
re = re.replace(/([.*+?^=!:$(|\[\/\\])/g, "\\$1"); | ||
if (handler.keys = _.keys(re)) { | ||
re = re.replace(/\{\w+\}/g, "([^\/?#]+)"); | ||
} else { | ||
re.replace(/\{/g, '\\{'); | ||
} | ||
re = new RegExp(re); | ||
if (uri) { | ||
var keys = _.keys(uri); | ||
if (keys) { | ||
uri = keys.reduce(function(s, key) { | ||
return s.replace(new RegExp('\\{'+key+'\\}',"g"), | ||
fill[key] || location[key] || ''); | ||
}, uri); | ||
} | ||
handler.regexp = re; | ||
if (uri !== current) { | ||
history.pushState(null, null, encodeURI(uri)); | ||
} | ||
} | ||
}; | ||
_.keys = function(tmpl) { | ||
var keys = tmpl.match(/\{\w+\}/g); | ||
return keys && keys.map(function(key) { | ||
return key.substring(1, key.length-1); | ||
}); | ||
}; | ||
_.locationHandler = function(uri, handler) { | ||
var re = uri; | ||
if (uri.charAt(0) === '`') { | ||
re = re.substring(1, re.length-1); | ||
} else { | ||
handler.regexp = /.+/; | ||
re = re.replace(/([.*+?^=!:$(|\[\/\\])/g, "\\$1");// escape uri/regexp conflicts | ||
if (handler.keys = _.keys(re)) { | ||
re = re.replace(/\{\w+\}/g, "([^\/?#]+)"); | ||
} else { | ||
re.replace(/\{/g, '\\{'); | ||
} | ||
} | ||
handler._fn = handler.fn; | ||
handler.fn = function(e){ _.location(e.uri, handler, arguments); }; | ||
// try for current uri match immediately | ||
_.execute(null, new Eventi('location',{uri:_.uri||_.at()}), handler); | ||
} | ||
}); | ||
_.keys = function(tmpl) { | ||
var keys = tmpl.match(/\{\w+\}/g); | ||
return keys && keys.map(function(key) { | ||
return key.substring(1, key.length-1); | ||
handler.uriRE = new RegExp(re); | ||
_.filter(handler, _.locationFilter); | ||
}; | ||
_.locationFilter = function(event, handler) { | ||
var matches = (event.uri || current).match(handler.uriRE); | ||
if (matches) { | ||
this.args.splice.apply(this.args, [1,0].concat(matches)); | ||
if (handler.keys) { | ||
// put key/match object in place of full match | ||
this.args[1] = handler.keys.reduce(function(o, key) { | ||
o[key] = matches.shift(); | ||
return o; | ||
}, { match: matches.shift() }); | ||
} | ||
} else { | ||
this.target = undefined; | ||
} | ||
}; | ||
Eventi.on('!popstate !hashchange !pushstate', _.location) | ||
.on('!location', _.setLocation) | ||
.on(_, 'on:handler', function location(e, handler) { | ||
if (handler.event.type === 'location') { | ||
// force global | ||
handler.global = true; | ||
// try for current uri match immediately | ||
if (!current) { | ||
_.location(); | ||
} | ||
_.execute(new Eventi('location',{location:current, srcEvent:e}), handler); | ||
} | ||
}); | ||
}; | ||
_.location = function(uri, handler, args) { | ||
var matches = (uri||_.uri).match(handler.regexp); | ||
if (matches) { | ||
args = _.slice(args); | ||
args.splice.apply(args, [1,0].concat(matches)); | ||
if (handler.keys) { | ||
// put key/match object in place of full match | ||
args[1] = handler.keys.reduce(function(o, key) { | ||
o[key] = matches.shift(); | ||
return o; | ||
}, { match: matches.shift() }); | ||
} | ||
handler._fn.apply(handler._target, args); | ||
} | ||
}; | ||
_.version = "0.7.1"; | ||
} | ||
_.version = "1.0.0"; | ||
var sP = (Event && Event.prototype.stopPropagation) || _.noop, | ||
sIP = (Event && Event.prototype.stopImmediatePropagation) || _.noop; | ||
var sP = (global.Event && Event.prototype.stopPropagation) || _.noop, | ||
sIP = (global.Event && Event.prototype.stopImmediatePropagation) || _.noop; | ||
CustomEvent.prototype.stopPropagation = function() { | ||
@@ -564,0 +631,0 @@ this.propagationStopped = true; |
@@ -1,4 +0,4 @@ | ||
/*! Eventi - v0.7.1 - 2014-03-13 | ||
/*! Eventi - v1.0.0 - 2014-04-03 | ||
* https://github.com/nbubna/Eventi | ||
* Copyright (c) 2014 ESHA Research; Licensed MIT */ | ||
!function(global,document){"use strict";function Eventi(){return _.create.apply(this,arguments)}global.CustomEvent||(global.CustomEvent=document?function(a,b){b=b||{};var c=document.createEvent("CustomEvent");return c.initCustomEvent(a,!!b.bubbles,!!b.cancelable,b.detail),c}:function(a,b){b=b||{},this.type=a,this.bubbles=!!b.bubbles,this.detail=b.detail,this.timestamp=Date.now()});var _={global:new Function("return this")(),noop:function(){},slice:function(a,b){return Array.prototype.slice.call(a,b)},copy:function(a,b,c){if(a)for(c in a)a.hasOwnProperty(c)&&(b[c]=a[c])},async:global.setImmediate||function(a){return setTimeout(a,0)},resolveRE:/^([\w\$]+)?((\.[\w\$]+)|\[(\d+|'(\\'|[^'])+'|"(\\"|[^"])+")\])*$/,resolve:function(reference,context){if(_.resolveRE.test(reference)){context=context||global;try{return eval("context"+("["!==reference.charAt(0)?"."+reference:reference))}catch(e){}}},create:function(a,b){var c={text:a+""};a=_.parse(c.text,c),_.copy(b,c),"bubbles"in c||(c.bubbles=!0);var d=new CustomEvent(a,c);for(var e in c)_.skip.indexOf(e)<0&&(d[_.prop(e)]=c[e]);return d},skip:"bubbles cancelable detail type".split(" "),prop:function(a){return a},parse:function(a,b){return _.properties.forEach(function(c){a=a.replace(c[0],function(){return c[1].apply(b,arguments)||""})}),a?b.type=a:a},properties:[[/^_/,function(){this.bubbles=!1}],[/^\!/,function(){this._protect=!0}],[/\((.*)\)/,function(a,b){try{this.detail=_.resolve(b)||JSON.parse(b)}catch(c){this.detail=b}}],[/#(\w+)/g,function(a,b){(this.tags||(this.tags=[])).push(b),this[b]=!0}],[/^(\w+):/,function(a,b){this.category=b}]],splitRE:/ (?![^\(\)]*\))+/g,wrap:function(a,b,c){c=c||1;var d=function(d){var e=_.slice(arguments);d&&"string"!=typeof d||(d=this&&this!==Eventi?this:_.global,e.unshift(d)),e[c]=e[c]?(e[c]+"").split(_.splitRE):[""],e.length>b&&(e[b]=e.slice(b),e=e.slice(0,b+1));var f,g=_[a];if("length"in d&&d!==_.global)for(var h=0,i=d.length;i>h;h++)f=g.apply(e[0]=d[h],e);else f=g.apply(d,e);return void 0===f?this:f};return d.index=c,d}};Eventi._=_,(Eventi.fy=function(a){for(var b in Eventi){var c=Eventi[b];"function"!=typeof c||c.utility||Object.defineProperty(a,b,{value:c,writable:!0,configurable:!0})}return a}).utility=!0,_.fire=function(a,b,c,d){return"object"!=typeof c||c instanceof Event||!("bubbles"in c||"detail"in c||"cancelable"in c)?(void 0!==c&&(d=d?d.unshift(c)&&d:[c]),c={data:d}):c.data=d,_.fireAll(a,b,c)},_.fireAll=function(a,b,c){for(var d,e=0;e<b.length;e++)d=_.create(b[e],c),_.dispatch(a,d);return d},_.dispatch=function(a,b,c){(a.dispatchEvent||a[_key]||_.noop).call(a,b),a.parentObject&&b.bubbles&&!b.propagationStopped&&_.dispatch(a.parentObject,b,!0),!c&&b._singleton&&_.singleton(a,b)},Eventi.fire=_.wrap("fire",3),_.on=function(a,b,c,d,e){"function"==typeof c&&(void 0!==d&&(e=e?e.unshift(d)&&e:[d]),d=c,c=null);for(var f=0,g=b.length;g>f;f++)_.handler(a,b[f],c,d,e)},_.handler=function(a,b,c,d,e){var f={target:a,selector:c,fn:d,data:e,text:b,match:{}};return _.parse(b,f.match),delete f.match.tags,a!==_&&Eventi.fire(_,"handler#new",f),f.fn!==_.noop&&_.handlers(f.target,f.match.type).push(f),f},_.handlers=function(a,b){var c=_.listener(a),d=c.s[b];return d||(d=c.s[b]=[],a.addEventListener&&a.addEventListener(b,c)),d};var _key=_._key="_eventi"+Date.now();if(_.listener=function(a){var b=a[_key];return b||(b=function(a){var c=b.s[a.type];c&&_.handle(a,c)},b.s={},Object.defineProperty(a,_key,{value:b,writeable:!1,configurable:!0})),b},_.handle=function(a,b){for(var c,d,e=0;e<b.length&&!(_.matches(a,(c=b[e]).match)&&(d=_.target(c,a.target))&&(_.execute(d,a,c),a.immediatePropagationStopped));e++);},_.execute=function(a,b,c){var d=[b];b.data&&d.push.apply(d,b.data),c.data&&d.push.apply(d,c.data);try{c.fn.apply(a,d)}catch(e){_.async(function(){throw e})}},_.unhandle=function(a){a.fn=_.noop},_.matches=function(a,b,c){for(var d in b)if(b[d]!==a[d]&&(c||"_"!==d.charAt(0)))return!1;if(c)for(d in a)if("_"===d.charAt(0)&&a[d]!==b[d])return!1;return!0},_.target=function(a,b){return a.selector?_.closest(b,a.selector):a.target},_.closest=function(a,b){for(;a&&a.matches;){if(a.matches(b))return a;a=a.parentNode}},global.Element){var Ep=Element.prototype,aS="atchesSelector";Ep.matches||Object.defineProperty(Ep,"matches",{value:Ep["webkitM"+aS]||Ep["mozM"+aS]||Ep["msM"+aS]})}Eventi.on=_.wrap("on",4),document&&(_.init=function(){for(var a=document.querySelectorAll("[data-eventi]"),b=0,c=a.length;c>b;b++){var d=a[b],e=d.getAttribute("data-eventi");e&&_.declare(e,d)}(a.length||document.querySelectorAll("[click]").length)&&Eventi.on("click keyup",_.check)},_.declare=function(a,b){for(var c=a.split(_.splitRE),d=0,e=c.length;e>d;d++){var f=c[d],g=f.lastIndexOf("="),h=g>0?f.substring(g+1):void 0,i="/"===f.charAt(0),j=i?_.global:b;b=b||document,h&&(f=f.substring(0,g)),i&&(f=f.substring(1)),Eventi.on(j,f,_.mapped,b,h)}},_.mapped=function(a,b,c){for(var d=c||a.type,e=_.declarers(b,d,this!==_.global&&a.target),f=0,g=e.length;g>f;f++)_.declared(e[f],d,a)},_.declarers=function(a,b,c){var d="["+b+"]";if(c){for(var e=[];c&&c.matches&&c!==a.parentNode;)c.matches(d)&&e.push(c),c=c.parentNode;return e}return a.querySelectorAll(d)},_.declared=function(a,b,c){var d=a.getAttribute(b);if(d){var e=_.resolve(d,a)||_.resolve(d);"function"==typeof e?e.call(a,c):Eventi.fire(a,d,c)}},_.check=function(a){var b="click"===a.type&&_.click(a.target)||13===a.keyCode&&_.click(a.target,!0);b&&(_.mapped(a,document.documentElement,"click"),"noDefault"!==b||_.allowDefault(a.target)||a.preventDefault())},_.allowDefault=function(a){return"radio"===a.type||"checkbox"===a.type},_.click=function(a,b){var c=a.getAttribute("click");if(c&&"false"!==c)return"noDefault";if(!a.isContentEditable){var d=a.nodeName.toLowerCase();return"textarea"!==d&&("select"!==d||b)&&(b?!("a"===d&&a.getAttribute("href")||"button"===d||"input"===d&&_.buttonRE.test(a.type)):"input"!==d||_.buttonRE.test(a.type))}},_.buttonRE=/^(submit|button|reset)$/,Eventi.on("DOMContentLoaded",_.init)),_.properties.unshift([/^\^/,function(){this._singleton=!0}]),_.singleton=function(a,b){_.remember(a,b),b.bubbles&&!b.propagationStopped&&a!==_.global&&_.singleton(a.parentNode||a.parentObject||_.global,b)};var _skey=_._skey="^"+_key;_.remember=function(a,b){var c=a[_skey]||[];c.length||Object.defineProperty(a,_skey,{value:c,configurable:!0}),b[_skey]=!0,c.push(b)},Eventi.on(_,"handler#new",function(a,b){if(b.match._singleton){var c=b._fn=b.fn;b.fn=function(a){_.unhandle(b),a[_skey]||_.remember(b.target,a),c.apply(this,arguments)};for(var d=b.target[_skey]||[],e=0,f=d.length;f>e;e++){var g=d[e];if(_.matches(g,b.match)){var h=_.target(b,g.target);if(h){_.execute(h,g,b),b.fn=_.noop;break}}}}}),document&&Eventi.on("DOMContentLoaded",function(a){_.fire(document.documentElement,["^ready"],void 0,[a])}),_.keyRE=/\[([a-z-0-9,\.\/\[\`\\\]\']+)\]/,_.properties.push([_.keyRE,function(a,b){for(var c,d;(c=b.indexOf("-"))>0;)d=b.substring(0,c),b=b.substring(c+1),this[(_.special[d]||d)+"Key"]=!0;this.keyCode=_.codes[b]||parseInt(b,10)||0}]),_.special={command:"meta",apple:"meta"},_.codes={backspace:8,tab:9,enter:13,shift:16,ctrl:17,alt:18,capsLock:20,escape:27,start:91,command:224,pageUp:33,pageDown:34,end:35,home:36,left:37,up:38,right:39,down:40,insert:45,"delete":46,multiply:106,plus:107,minus:109,point:110,divide:111,numLock:144,",":188,".":190,"/":191,"`":192,"[":219,"\\":220,"]":221,"'":222,space:32};for(var n=0;10>n;n++)_.codes["num"+n]=96+n;for(var f=1;13>f;f++)_.codes["f"+f]=111+f;"abcdefghijklmnopqrstuvwxyz 0123456789".split("").forEach(function(a){_.codes[a]=a.toUpperCase().charCodeAt(0)});var h=global.history,l=global.location;_.pushState=h.pushState,h.pushState=function(){var a=_.pushState.apply(this,arguments);return _.dispatch(_.global,new Eventi("pushstate",{uri:arguments[2]})),a},Eventi.on("!popstate !hashchange !pushstate",_.at=function(a,b){return b=b||decodeURI(l.pathname+l.search+l.hash),b!==_.uri&&_.dispatch(_.global,new Eventi("location",{oldURI:_.uri,uri:_.uri=b,srcEvent:a})),b}).on("!location",function(a,b,c){if("string"==typeof b){var d=_.keys(b);d&&(b=d.reduce(function(a,b){return a.replace(new RegExp("\\{"+b+"\\}","g"),c[b]||global.location[b]||"")},b)),a.uri=b,b!==_.uri&&h.pushState(null,null,encodeURI(b))}else a.uri||(a.uri=_.uri)}).on(_,"handler#new",function(a,b){if("location"===b.match.type){if(b._target=b.target,b.target=_.global,b.selector){var c=b.selector;delete b.selector,"string"==typeof c&&(c=c.replace(/([.*+?^=!:$(|\[\/\\])/g,"\\$1"),(b.keys=_.keys(c))?c=c.replace(/\{\w+\}/g,"([^/?#]+)"):c.replace(/\{/g,"\\{"),c=new RegExp(c)),b.regexp=c}else b.regexp=/.+/;b._fn=b.fn,b.fn=function(a){_.location(a.uri,b,arguments)},_.execute(null,new Eventi("location",{uri:_.uri||_.at()}),b)}}),_.keys=function(a){var b=a.match(/\{\w+\}/g);return b&&b.map(function(a){return a.substring(1,a.length-1)})},_.location=function(a,b,c){var d=(a||_.uri).match(b.regexp);d&&(c=_.slice(c),c.splice.apply(c,[1,0].concat(d)),b.keys&&(c[1]=b.keys.reduce(function(a,b){return a[b]=d.shift(),a},{match:d.shift()})),b._fn.apply(b._target,c))},_.version="0.7.1";var sP=Event&&Event.prototype.stopPropagation||_.noop,sIP=Event&&Event.prototype.stopImmediatePropagation||_.noop;CustomEvent.prototype.stopPropagation=function(){this.propagationStopped=!0,sP.call(this)},CustomEvent.prototype.stopImmediatePropagation=function(){this.immediatePropagationStopped=!0,sIP.call(this)};var define=global.define||_.noop;define((global.exports||global).Eventi=Eventi)}(this,this.document); | ||
!function(global,document){"use strict";function Eventi(){return _.create.apply(this,arguments)}global.CustomEvent||(global.CustomEvent=document?function(a,b){b=b||{};var c=document.createEvent("CustomEvent");return c.initCustomEvent(a,!!b.bubbles,!!b.cancelable,b.detail),c}:function(a,b){b=b||{},this.type=a,this.bubbles=!!b.bubbles,this.detail=b.detail,this.timestamp=Date.now()},global.Event||(global.Event=global.CustomEvent));var _={global:new Function("return this")(),noop:function(){},slice:function(a,b){return Array.prototype.slice.call(a,b)},copy:function(a,b,c){if("object"==typeof a)for(c in a)a.hasOwnProperty(c)&&(b[c]=a[c])},async:global.setImmediate||function(a){return setTimeout(a,0)},resolveRE:/^([\w\$]+)?((\.[\w\$]+)|\[(\d+|'(\\'|[^'])+'|"(\\"|[^"])+")\])*$/,resolve:function(reference,context,tested){if(tested||_.resolveRE.test(reference)){context=context||global;try{return eval("context"+("["!==reference.charAt(0)?"."+reference:reference))}catch(e){}}},create:function(a,b){var c={text:a+""};a=_.parse(c.text,c,c),_.copy(b,c),"bubbles"in c||(c.bubbles=!0);var d=new CustomEvent(a,c);for(var e in c)_.skip.indexOf(e)<0&&(d[_.prop(e)]=c[e]);return d},skip:"bubbles cancelable detail type".split(" "),prop:function(a){return a},parse:function(a,b,c){return _.parsers.forEach(function(d){a=a.replace(d[0],function(){var a=_.slice(arguments,1);return a.unshift(b,c),d[1].apply(b,a)||""})}),a?b.type=a:a},parsers:[[/^(\W*)_/,function(a,b,c){return a.bubbles=!1,c}],[/\((.*)\)/,function(a,b,c){try{a.detail=_.resolve(c)||JSON.parse(c)}catch(d){a.detail=c}}],[/#(\w+)/g,function(a,b,c){(a.tags||(a.tags=[])).push(c),a[c]=!0}],[/^(\w+):/,function(a,b,c){a.category=c}]],wrap:function(a,b){return function(c){var d=_.slice(arguments);(!c||"string"==typeof c||c instanceof global.Event)&&d.unshift(c=this&&this!==Eventi?this:_.global),d.length>b&&(d[b]=d.slice(b),d=d.slice(0,b+1)),d[1]&&"string"!=typeof d[1]||(d[1]=_.split.ter(d[1]));var e,f=_[a];if("length"in c&&c!==_.global)for(var g=0,h=c.length;h>g;g++)e=f.apply(d[0]=c[g],d);else e=f.apply(c,d);return void 0===e?this:e}},split:{guard:{"(":")"},ter:function(a,b){var c,d=[],e="";if(a){b=_.slice(arguments,1),b.unshift(" ");for(var f=0,g=a.length;g>f;f++){var h=a.charAt(f);!c&&b.indexOf(h)>=0?(e&&d.push(e),e=""):(e+=h,c?c===h&&("\\"===e.charAt(e.length-2)?e=e.replace("\\"+h,h):c=null):c=_.split.guard[h])}e&&d.push(e)}else d.push("");return d}}};Eventi._=_,(Eventi.fy=function(a){for(var b in Eventi){var c=Eventi[b];"function"!=typeof c||c.utility||Object.defineProperty(a,b,{value:c,writable:!0,configurable:!0})}return a}).utility=!0,_.parsers.unshift([/^(\W*)\//,function(a,b,c){return b.global=!0,c}]),_.fire=function(a,b,c){return b instanceof Event?(b.data=c,_.dispatch(a,b),b):_.fireAll(a,b,{data:c})},_.fireAll=function(a,b,c){for(var d,e=0;e<b.length;e++)d=_.create(b[e],c),_.dispatch(a,d);return d},_.dispatch=function(a,b,c){b.global&&(a=_.global),(a.dispatchEvent||a[_key]||_.noop).call(a,b),a.parentObject&&b.bubbles&&!b.propagationStopped&&_.dispatch(a.parentObject,b,!0),!c&&b.singleton&&_.singleton(a,b)},Eventi.fire=_.wrap("fire",2),_.parsers.unshift([/^(\W*)\!/,function(a,b,c){return b.important=!0,c}]),_.on=function(a,b,c,d){if(Array.isArray(b))for(var e=0,f=b.length;f>e;e++)_.handler(a,b[e],c,d);else{void 0!==c&&(d=d?d.unshift(c)&&d:[c]);for(var g in b)_.handler(a,g,b[g],d)}},_.handler=function(a,b,c,d){var e={target:a,fn:c,data:d,text:b,event:{}};return _.parse(b,e.event,e),delete e.event.tags,a!==_&&Eventi.fire(_,"on:handler",e),e.fn!==_.noop&&(a=e.global===!0?_.global:e.target,_.handlers(a,e.event.type).push(e)),e},_.handlers=function(a,b){var c=_.listener(a),d=c.s[b];return d||(d=c.s[b]=[],a.addEventListener&&a.addEventListener(b,c)),d};var _key=_._key="_eventi"+Date.now();if(_.listener=function(a){var b=a[_key];return b||(b=function(a){var c=b.s[a.type];c&&_.handle(a,c)},b.s={},Object.defineProperty(a,_key,{value:b,writeable:!1,configurable:!0})),b},_.handle=function(a,b){for(var c,d=0;d<b.length&&(!_.matches(a,(c=b[d]).event)||(_.execute(a,c),!a.immediatePropagationStopped));d++);},_.execute=function(a,b){var c=[a],d=b.fn,e={target:b.target,args:c};if(a.data&&c.push.apply(c,a.data),b.data&&c.push.apply(c,b.data),b.filters)for(var f=0,g=b.filters.length;g>f&&e.target;f++)b.filters[f].call(e,a,b);if(e.target){try{d.apply(e.target,e.args)}catch(h){_.async(function(){throw h})}b.end&&b.end.apply(e.target,e.args)&&_.unhandle(b)}},_.filter=function(a,b){a.filters=a.filters||[],a.filters.push(b)},_.unhandle=function(a){a.fn=_.noop},_.matches=function(a,b){for(var c in b)if(b[c]!==a[c])return!1;return!0},Eventi.on=_.wrap("on",3),_.split.guard["<"]=">",_.parsers.unshift([/<(.+)>/,function(a,b,c){b.selector=c,_.delegate&&a!==b&&_.filter(b,_.delegate)}]),global.Element){_.delegate=function(a,b){this.target=_.closest(a.target,b.selector)},_.closest=function(a,b){for(;a&&a.matches;){if(a.matches(b))return a;a=a.parentNode}};var Ep=Element.prototype,aS="atchesSelector";Ep.matches||Object.defineProperty(Ep,"matches",{value:Ep["webkitM"+aS]||Ep["mozM"+aS]||Ep["msM"+aS]})}_.parsers.unshift([/=>(\w+)$/,function(a,b,c){b.alias=c,b!==a&&(b.data=b.data||[],b.data.push(c))}]),document&&(_.init=function(){for(var a=document.querySelectorAll("[data-eventi]"),b=0,c=a.length;c>b;b++){var d=a[b],e=d.getAttribute("data-eventi");e!==d.eventi&&(_.off&&d.eventi&&Eventi.off(d,d.eventi,_.declared),d.eventi=e,_.declare(d,e))}(a.length||document.querySelectorAll("[click]").length)&&Eventi.on("click keyup",_.check)},_.declare=function(a,b){for(var c=_.split.ter(b),d=0,e=c.length;e>d;d++)Eventi.on(a,c[d],_.declared)},_.declared=function(a,b){b="string"==typeof b?b:a.type;for(var c=_.declarers(this,b,a.target),d=0,e=c.length;e>d;d++)_.respond(c[d],b,a)},_.declarers=function(a,b,c){for(var d="["+b+"]",e=[],f=!1;c&&c.matches;){if(c.matches(d)&&e.push(c),c===a){f=!0;break}c=c.parentNode}return f?e:a.querySelectorAll(d)},_.respond=function(a,b,c){var d=a.getAttribute(b);if(d){var e=_.resolve(d,a)||_.resolve(d);"function"==typeof e?e.call(a,c):Eventi.fire(a,d,c)}},_.check=function(a){var b=a.target.getAttribute&&("click"===a.type&&_.click(a.target)||13===a.keyCode&&_.click(a.target,!0));b&&(_.declared.call(document.documentElement,a,"click"),"noDefault"!==b||_.allowDefault(a.target)||a.preventDefault())},_.allowDefault=function(a){return"radio"===a.type||"checkbox"===a.type},_.click=function(a,b){var c=a.getAttribute("click");if(c&&"false"!==c)return"noDefault";if(!a.isContentEditable){var d=a.nodeName.toLowerCase();return"textarea"!==d&&("select"!==d||b)&&(b?!("a"===d&&a.getAttribute("href")||"button"===d||"input"===d&&_.buttonRE.test(a.type)):"input"!==d||_.buttonRE.test(a.type))}},_.buttonRE=/^(submit|button|reset)$/,Eventi.on("DOMContentLoaded",_.init)),_.parsers.unshift([/^(\W*)\^/,function(a,b,c){return b.singleton=!0,a!==b&&_.filter(b,_.before),c}]),_.singleton=function(a,b){_.remember(a,b),b.bubbles&&!b.propagationStopped&&a!==_.global&&_.singleton(a.parentNode||a.parentObject||_.global,b)};var _skey=_._skey="^"+_key;_.remember=function(a,b){var c=a[_skey]||[];c.length||Object.defineProperty(a,_skey,{value:c,configurable:!0}),b[_skey]=!0,c.push(b)},_.before=function(a,b){_.unhandle(b),b.fn=_.noop,a[_skey]||_.remember(this.target,a)},Eventi.on(_,"on:handler",function(a,b){if(b.singleton)for(var c=b.target[_skey]||[],d=0,e=c.length;e>d;d++){var f=c[d];if(_.matches(f,b.event)){_.execute(f,b);break}}}),document&&Eventi.on("DOMContentLoaded",function(a){Eventi.fire(document.documentElement,"^ready",a)}),_.split.guard["["]="]",_.parsers.push([/\[([^ ]+)\]/,function(a,b,c){for(var d;(d=c.indexOf("-"))>0;)a[c.substring(0,d)+"Key"]=!0,c=c.substring(d+1);c&&(a.keyCode=_.codes[c]||parseInt(c,10)||c)}]),_.codes={backspace:8,tab:9,enter:13,shift:16,ctrl:17,alt:18,capsLock:20,escape:27,start:91,command:224,pageUp:33,pageDown:34,end:35,home:36,left:37,up:38,right:39,down:40,insert:45,"delete":46,multiply:106,plus:107,minus:109,point:110,divide:111,numLock:144,";":186,"=":187,",":188,"-":189,".":190,"/":191,"`":192,"[":219,"\\":220,"]":221,"'":222,space:32};for(var n=0;10>n;n++)_.codes["num"+n]=96+n;for(var f=1;13>f;f++)_.codes["f"+f]=111+f;if("abcdefghijklmnopqrstuvwxyz 0123456789".split("").forEach(function(a){_.codes[a]=a.toUpperCase().charCodeAt(0)}),_.split.guard["@"]="@",_.parsers.unshift([/@([^@]+)(@|$)/,function(a,b,c){b.location=c,_.location&&a!==b&&_.locationHandler(c,b)}]),global.history&&global.location){var current;_.pushState=history.pushState,history.pushState=function(){var a=_.pushState.apply(this,arguments);return _.dispatch(_.global,new CustomEvent("pushstate")),a},_.location=function(a,b){return b=b||decodeURI(location.pathname+location.search+location.hash),b!==current&&_.dispatch(_.global,new Eventi("location",{oldLocation:current,location:current=b,srcEvent:a})),current},_.setLocation=function(a,b,c){if("string"!=typeof b&&(c=b,b=a.location),b){var d=_.keys(b);d&&(b=d.reduce(function(a,b){return a.replace(new RegExp("\\{"+b+"\\}","g"),c[b]||location[b]||"")},b)),b!==current&&history.pushState(null,null,encodeURI(b))}},_.keys=function(a){var b=a.match(/\{\w+\}/g);return b&&b.map(function(a){return a.substring(1,a.length-1)})},_.locationHandler=function(a,b){var c=a;"`"===a.charAt(0)?c=c.substring(1,c.length-1):(c=c.replace(/([.*+?^=!:$(|\[\/\\])/g,"\\$1"),(b.keys=_.keys(c))?c=c.replace(/\{\w+\}/g,"([^/?#]+)"):c.replace(/\{/g,"\\{")),b.uriRE=new RegExp(c),_.filter(b,_.locationFilter)},_.locationFilter=function(a,b){var c=(a.uri||current).match(b.uriRE);c?(this.args.splice.apply(this.args,[1,0].concat(c)),b.keys&&(this.args[1]=b.keys.reduce(function(a,b){return a[b]=c.shift(),a},{match:c.shift()}))):this.target=void 0},Eventi.on("!popstate !hashchange !pushstate",_.location).on("!location",_.setLocation).on(_,"on:handler",function(a,b){"location"===b.event.type&&(b.global=!0,current||_.location(),_.execute(new Eventi("location",{location:current,srcEvent:a}),b))})}_.version="1.0.0";var sP=global.Event&&Event.prototype.stopPropagation||_.noop,sIP=global.Event&&Event.prototype.stopImmediatePropagation||_.noop;CustomEvent.prototype.stopPropagation=function(){this.propagationStopped=!0,sP.call(this)},CustomEvent.prototype.stopImmediatePropagation=function(){this.immediatePropagationStopped=!0,sIP.call(this)};var define=global.define||_.noop;define((global.exports||global).Eventi=Eventi)}(this,this.document); |
@@ -1,2 +0,2 @@ | ||
/*! Eventi - v0.7.1 - 2014-03-13 | ||
/*! Eventi - v1.0.0 - 2014-04-03 | ||
* https://github.com/nbubna/Eventi | ||
@@ -22,2 +22,3 @@ * Copyright (c) 2014 ESHA Research; Licensed MIT */ | ||
}; | ||
if (!global.Event){ global.Event = global.CustomEvent; } | ||
} | ||
@@ -31,8 +32,8 @@ | ||
copy: function(a, b, p) { | ||
if (a){ for (p in a){ if (a.hasOwnProperty(p)){ b[p] = a[p]; }}} | ||
if (typeof a === "object"){ for (p in a){ if (a.hasOwnProperty(p)){ b[p] = a[p]; }}} | ||
}, | ||
async: global.setImmediate || function async(fn){ return setTimeout(fn, 0); }, | ||
resolveRE: /^([\w\$]+)?((\.[\w\$]+)|\[(\d+|'(\\'|[^'])+'|"(\\"|[^"])+")\])*$/, | ||
resolve: function(reference, context) { | ||
if (_.resolveRE.test(reference)) { | ||
resolve: function(reference, context, tested) { | ||
if (tested || _.resolveRE.test(reference)) { | ||
context = context || global; | ||
@@ -47,6 +48,6 @@ try { | ||
var props = { text: type+'' }; | ||
type = _.parse(props.text, props); | ||
type = _.parse(props.text, props, props); | ||
_.copy(copyThese, props); | ||
if (!('bubbles' in props)) { | ||
props.bubbles = true;// must bubble by default | ||
props.bubbles = true;// we bubble by default around here | ||
} | ||
@@ -64,53 +65,48 @@ | ||
prop: function(prop){ return prop; },// only an extension hook | ||
parse: function(type, props) { | ||
_.properties.forEach(function(property) { | ||
parse: function(type, event, handler) { | ||
_.parsers.forEach(function(property) { | ||
type = type.replace(property[0], function() { | ||
return property[1].apply(props, arguments) || ''; | ||
var args = _.slice(arguments, 1); | ||
args.unshift(event, handler); | ||
return property[1].apply(event, args) || ''; | ||
}); | ||
}); | ||
return type ? props.type = type : type; | ||
return type ? event.type = type : type; | ||
}, | ||
properties: [ | ||
[/^_/, function nobubble() { | ||
this.bubbles = false; | ||
parsers: [ | ||
[/^(\W*)_/, function(event, handler, other) { | ||
event.bubbles = false; | ||
return other; | ||
}], | ||
[/^\!/, function protect() {// | ||
this._protect = true; | ||
}], | ||
[/\((.*)\)/, function detail(m, val) { | ||
[/\((.*)\)/, function(event, handler, val) { | ||
try { | ||
this.detail = _.resolve(val) || JSON.parse(val); | ||
event.detail = _.resolve(val) || JSON.parse(val); | ||
} catch (e) { | ||
this.detail = val; | ||
event.detail = val; | ||
} | ||
}], | ||
[/#(\w+)/g, function tags(m, tag) { | ||
(this.tags||(this.tags=[])).push(tag); | ||
this[tag] = true; | ||
[/#(\w+)/g, function(event, handler, tag) { | ||
(event.tags||(event.tags=[])).push(tag); | ||
event[tag] = true; | ||
}], | ||
[/^(\w+):/, function category(m, cat) {// | ||
this.category = cat; | ||
[/^(\w+):/, function(event, handler, cat) {// | ||
event.category = cat; | ||
}] | ||
], | ||
splitRE: / (?![^\(\)]*\))+/g, | ||
wrap: function(name, expect, index) { | ||
index = index || 1; | ||
var wrapper = function wrapper(target) { | ||
wrap: function(name, dataIndex) { | ||
return function wrapper(target) { | ||
var args = _.slice(arguments); | ||
// ensure target param precedes event text | ||
if (!target || typeof target === "string") { | ||
target = !this || this === Eventi ? _.global : this; | ||
args.unshift(target); | ||
if (!target || typeof target === "string" || target instanceof global.Event) {// ensure target | ||
args.unshift(target = !this || this === Eventi ? _.global : this); | ||
} | ||
// ensure array of event text inputs | ||
args[index] = args[index] ? (args[index]+'').split(_.splitRE) : ['']; | ||
// gather ...data the old way | ||
if (args.length > expect) { | ||
args[expect] = args.slice(expect); | ||
args = args.slice(0, expect+1); | ||
if (args.length > dataIndex) {// gather ...data the old way | ||
args[dataIndex] = args.slice(dataIndex); | ||
args = args.slice(0, dataIndex+1); | ||
} | ||
// call fn for each target | ||
if (!args[1] || typeof args[1] === "string") { | ||
args[1] = _.split.ter(args[1]); | ||
} | ||
var fn = _[name], ret; | ||
if ('length' in target && target !== _.global) { | ||
if ('length' in target && target !== _.global) {// apply to each target | ||
for (var i=0,m=target.length; i<m; i++) { | ||
@@ -122,8 +118,45 @@ ret = fn.apply(args[0] = target[i], args); | ||
} | ||
// be fluent | ||
return ret === undefined ? this : ret; | ||
return ret === undefined ? this : ret;// be fluent | ||
}; | ||
wrapper.index = index; | ||
return wrapper; | ||
} | ||
}, | ||
split: { | ||
guard: { '(':')' }, | ||
ter: function(texts, delims) { | ||
var parts = [], | ||
text = '', | ||
guard; | ||
if (texts) { | ||
delims = _.slice(arguments, 1); | ||
delims.unshift(' '); | ||
for (var i=0,m=texts.length; i<m; i++) { | ||
var c = texts.charAt(i); | ||
if (!guard && delims.indexOf(c) >= 0) { | ||
if (text) { | ||
parts.push(text); | ||
} | ||
text = ''; | ||
} else { | ||
text += c; | ||
if (guard) { | ||
if (guard === c) { | ||
if (text.charAt(text.length-2) === '\\') { | ||
text = text.replace("\\"+c, c); | ||
} else { | ||
guard = null; | ||
} | ||
} | ||
} else { | ||
guard = _.split.guard[c]; | ||
} | ||
} | ||
} | ||
if (text) { | ||
parts.push(text); | ||
} | ||
} else { | ||
parts.push(''); | ||
} | ||
return parts; | ||
} | ||
} | ||
}; | ||
@@ -141,13 +174,13 @@ Eventi._ = _; | ||
_.fire = function(target, events, props, data) { | ||
if (typeof props === "object" && !(props instanceof Event) && | ||
('bubbles' in props || 'detail' in props || 'cancelable' in props)) { | ||
props.data = data; | ||
} else { | ||
if (props !== undefined) { | ||
data = data ? data.unshift(props) && data : [props]; | ||
} | ||
props = { data: data }; | ||
_.parsers.unshift([/^(\W*)\//, function(event, handler, other) { | ||
handler.global = true; | ||
return other; | ||
}]); | ||
_.fire = function(target, events, data) { | ||
if (events instanceof Event) { | ||
events.data = data; | ||
_.dispatch(target, events); | ||
return events; | ||
} | ||
return _.fireAll(target, events, props); | ||
return _.fireAll(target, events, {data:data}); | ||
}; | ||
@@ -163,2 +196,3 @@ _.fireAll = function(target, events, props) { | ||
_.dispatch = function(target, event, objectBubbling) { | ||
if (event.global){ target = _.global; } | ||
(target.dispatchEvent || target[_key] || _.noop).call(target, event); | ||
@@ -169,30 +203,36 @@ if (target.parentObject && event.bubbles && !event.propagationStopped) { | ||
// icky test/call, but lighter than wrapping or firing internal event | ||
if (!objectBubbling && event._singleton) { | ||
if (!objectBubbling && event.singleton) { | ||
_.singleton(target, event); | ||
} | ||
}; | ||
Eventi.fire = _.wrap('fire', 3); | ||
_.on = function(target, events, selector, fn, data) { | ||
// adjust for absence of selector | ||
if (typeof selector === "function") { | ||
Eventi.fire = _.wrap('fire', 2); | ||
_.parsers.unshift([/^(\W*)\!/, function(e, handler, other) {// | ||
handler.important = true; | ||
return other; | ||
}]); | ||
_.on = function(target, events, fn, data) { | ||
if (!Array.isArray(events)) { | ||
if (fn !== undefined) { | ||
data = data ? data.unshift(fn) && data : [fn]; | ||
} | ||
fn = selector; selector = null; | ||
for (var event in events) { | ||
_.handler(target, event, events[event], data); | ||
} | ||
} else { | ||
for (var i=0,m=events.length; i<m; i++) { | ||
_.handler(target, events[i], fn, data); | ||
} | ||
} | ||
for (var i=0,m=events.length; i<m; i++) { | ||
_.handler(target, events[i], selector, fn, data); | ||
} | ||
}; | ||
_.handler = function(target, text, selector, fn, data) { | ||
//TODO: consider moving selector into match, so we can specifically off delegates | ||
var handler = { target:target, selector:selector, fn:fn, data:data, text:text, match:{} }; | ||
_.parse(text, handler.match); | ||
delete handler.match.tags;// superfluous for matching | ||
_.handler = function(target, text, fn, data) { | ||
var handler = { target:target, fn:fn, data:data, text:text, event:{} }; | ||
_.parse(text, handler.event, handler); | ||
delete handler.event.tags;// superfluous for handlers | ||
if (target !== _) {// ignore internal events | ||
Eventi.fire(_, 'handler#new', handler); | ||
Eventi.fire(_, 'on:handler', handler); | ||
} | ||
// allow handler#new listeners to change these things | ||
// allow on:handler listeners to change these things | ||
if (handler.fn !== _.noop) { | ||
_.handlers(handler.target, handler.match.type).push(handler); | ||
target = handler.global === true ? _.global : handler.target; | ||
_.handlers(target, handler.event.type).push(handler); | ||
} | ||
@@ -228,53 +268,68 @@ return handler; | ||
}; | ||
_.handle = function(event, handlers) { | ||
for (var i=0, handler, target; i<handlers.length; i++) { | ||
if (_.matches(event, (handler = handlers[i]).match)) { | ||
if (target = _.target(handler, event.target)) { | ||
_.execute(target, event, handler); | ||
if (event.immediatePropagationStopped){ break; } | ||
} | ||
for (var i=0, handler; i<handlers.length; i++) { | ||
if (_.matches(event, (handler = handlers[i]).event)) { | ||
_.execute(event, handler); | ||
if (event.immediatePropagationStopped){ break; } | ||
} | ||
} | ||
}; | ||
_.execute = function(target, event, handler) { | ||
var args = [event]; | ||
_.execute = function(event, handler) { | ||
var args = [event], | ||
fn = handler.fn, | ||
call = { target: handler.target, args:args }; | ||
if (event.data){ args.push.apply(args, event.data); } | ||
if (handler.data){ args.push.apply(args, handler.data); } | ||
try { | ||
handler.fn.apply(target, args); | ||
} catch (e) { | ||
_.async(function(){ throw e; }); | ||
if (handler.filters) { | ||
for (var i=0,m=handler.filters.length; i<m && call.target; i++) { | ||
handler.filters[i].call(call, event, handler); | ||
} | ||
} | ||
if (call.target) { | ||
try { | ||
fn.apply(call.target, call.args); | ||
} catch (e) { | ||
_.async(function(){ throw e; }); | ||
} | ||
if (handler.end && handler.end.apply(call.target, call.args)) { | ||
_.unhandle(handler); | ||
} | ||
} | ||
}; | ||
_.filter = function(handler, fn) { | ||
handler.filters = handler.filters || []; | ||
handler.filters.push(fn); | ||
}; | ||
_.unhandle = function noop(handler){ handler.fn = _.noop; }; | ||
_.matches = function(event, match, strict) { | ||
_.matches = function(event, match) { | ||
for (var key in match) { | ||
if (match[key] !== event[key] && (strict || key.charAt(0) !== '_')) { | ||
if (match[key] !== event[key]) { | ||
return false; | ||
} | ||
} | ||
if (strict) { | ||
for (key in event) { | ||
if (key.charAt(0) === '_' && event[key] !== match[key]) { | ||
return false; | ||
} | ||
} | ||
} | ||
return true; | ||
}; | ||
_.target = function(handler, target) { | ||
return handler.selector ? _.closest(target, handler.selector) : handler.target; | ||
}; | ||
_.closest = function(el, selector) { | ||
while (el && el.matches) { | ||
if (el.matches(selector)) { | ||
return el; | ||
} | ||
el = el.parentNode; | ||
Eventi.on = _.wrap('on', 3); | ||
_.split.guard['<'] = '>'; | ||
_.parsers.unshift([/<(.+)>/, function(event, handler, selector) { | ||
handler.selector = selector; | ||
if (_.delegate && event !== handler) { | ||
_.filter(handler, _.delegate); | ||
} | ||
}; | ||
}]); | ||
if (global.Element) { | ||
_.delegate = function delegate(event, handler) { | ||
this.target = _.closest(event.target, handler.selector); | ||
}; | ||
_.closest = function(el, selector) { | ||
while (el && el.matches) { | ||
if (el.matches(selector)) { | ||
return el; | ||
} | ||
el = el.parentNode; | ||
} | ||
}; | ||
var Ep = Element.prototype, | ||
@@ -287,4 +342,9 @@ aS = 'atchesSelector'; | ||
Eventi.on = _.wrap('on', 4); | ||
_.parsers.unshift([/=>(\w+)$/, function(event, handler, alias) { | ||
handler.alias = alias; | ||
if (handler !== event) { | ||
handler.data = handler.data || []; | ||
handler.data.push(alias); | ||
} | ||
}]); | ||
if (document) { | ||
@@ -294,6 +354,10 @@ _.init = function init() { | ||
for (var i=0,m=nodes.length; i<m; i++) { | ||
var node = nodes[i], | ||
mapping = node.getAttribute('data-eventi'); | ||
if (mapping) { | ||
_.declare(mapping, node); | ||
var target = nodes[i], | ||
mapping = target.getAttribute('data-eventi'); | ||
if (mapping !== target.eventi) { | ||
if (_.off && target.eventi) { | ||
Eventi.off(target, target.eventi, _.declared); | ||
} | ||
target.eventi = mapping; | ||
_.declare(target, mapping); | ||
} | ||
@@ -305,41 +369,35 @@ } | ||
}; | ||
_.declare = function(mapping, mapper) {// register listener | ||
var types = mapping.split(_.splitRE); | ||
for (var i=0,m=types.length; i<m; i++) { | ||
var type = types[i], | ||
eq = type.lastIndexOf('='), | ||
alias = eq > 0 ? type.substring(eq+1) : undefined, | ||
global = type.charAt(0) === '/', | ||
context = global ? _.global : mapper; | ||
mapper = mapper || document; | ||
if (alias){ type = type.substring(0, eq); } | ||
if (global){ type = type.substring(1); } | ||
Eventi.on(context, type, _.mapped, mapper, alias); | ||
_.declare = function(target, mapping) {// register listener | ||
var texts = _.split.ter(mapping); | ||
for (var i=0,m=texts.length; i<m; i++) { | ||
Eventi.on(target, texts[i], _.declared); | ||
} | ||
}; | ||
_.mapped = function(e, mapper, alias) {// lookup handlers | ||
var type = alias || e.type, | ||
nodes = _.declarers(mapper, type, this !== _.global && e.target); | ||
_.declared = function(e, alias) {// lookup handlers | ||
alias = typeof alias === "string" ? alias : e.type; | ||
var nodes = _.declarers(this, alias, e.target); | ||
for (var i=0,m=nodes.length; i<m; i++) { | ||
_.declared(nodes[i], type, e); | ||
_.respond(nodes[i], alias, e); | ||
} | ||
}; | ||
_.declarers = function(mapper, type, target) { | ||
var query = '['+type+']'; | ||
if (target) { | ||
// gather matching parents up to the mapper | ||
var nodes = []; | ||
while (target && target.matches && target !== mapper.parentNode) { | ||
if (target.matches(query)) { | ||
nodes.push(target); | ||
} | ||
target = target.parentNode; | ||
_.declarers = function(target, alias, node) { | ||
var query = '['+alias+']', | ||
// gather matching parents up to the target | ||
nodes = [], | ||
descendant = false; | ||
while (node && node.matches) { | ||
if (node.matches(query)) { | ||
nodes.push(node); | ||
} | ||
return nodes; | ||
if (node === target) { | ||
descendant = true; | ||
break; | ||
} | ||
node = node.parentNode; | ||
} | ||
// gather all declarations within the mapper | ||
return mapper.querySelectorAll(query); | ||
// if node isn't a descendant of target, handler must be global | ||
return descendant ? nodes : target.querySelectorAll(query); | ||
}; | ||
_.declared = function(node, type, e) {// execute handler | ||
var response = node.getAttribute(type); | ||
_.respond = function(node, alias, e) {// execute handler | ||
var response = node.getAttribute(alias); | ||
if (response) { | ||
@@ -355,6 +413,7 @@ var fn = _.resolve(response, node) || _.resolve(response); | ||
_.check = function(e) { | ||
var click = (e.type === 'click' && _.click(e.target)) || | ||
(e.keyCode === 13 && _.click(e.target, true)); | ||
var click = e.target.getAttribute && | ||
((e.type === 'click' && _.click(e.target)) || | ||
(e.keyCode === 13 && _.click(e.target, true))); | ||
if (click) { | ||
_.mapped(e, document.documentElement, 'click'); | ||
_.declared.call(document.documentElement, e, 'click'); | ||
if (click === 'noDefault' && !_.allowDefault(e.target)) { | ||
@@ -394,3 +453,9 @@ e.preventDefault(); | ||
// add singleton to _.parse's supported event properties | ||
_.properties.unshift([/^\^/, function singleton(){ this._singleton = true; }]); | ||
_.parsers.unshift([/^(\W*)\^/, function(event, handler, other) { | ||
handler.singleton = true; | ||
if (event !== handler) { | ||
_.filter(handler, _.before); | ||
} | ||
return other; | ||
}]); | ||
@@ -413,14 +478,12 @@ // _.fire's _.dispatch will call this when appropriate | ||
}; | ||
_.before = function singleton(event, handler) { | ||
_.unhandle(handler); | ||
handler.fn = _.noop;// tell _.handler not to keep this | ||
if (!event[_skey]) {// remember this non-singleton as singleton for handler's sake | ||
_.remember(this.target, event); | ||
} | ||
}; | ||
Eventi.on(_, 'handler#new', function singleton(e, handler) { | ||
if (handler.match._singleton) { | ||
var fn = handler._fn = handler.fn; | ||
handler.fn = function singleton(e) { | ||
_.unhandle(handler); | ||
if (!e[_skey]) {// remember this non-singleton as singleton for handler's sake | ||
_.remember(handler.target, e); | ||
} | ||
fn.apply(this, arguments); | ||
}; | ||
Eventi.on(_, 'on:handler', function singleton(e, handler) { | ||
if (handler.singleton) { | ||
// search target's saved singletons, execute handler upon match | ||
@@ -430,9 +493,5 @@ var saved = handler.target[_skey]||[]; | ||
var event = saved[i]; | ||
if (_.matches(event, handler.match)) { | ||
var target = _.target(handler, event.target); | ||
if (target) { | ||
_.execute(target, event, handler); | ||
handler.fn = _.noop;// tell _.handler not to keep this | ||
break; | ||
} | ||
if (_.matches(event, handler.event)) { | ||
_.execute(event, handler); | ||
break; | ||
} | ||
@@ -445,17 +504,16 @@ } | ||
Eventi.on('DOMContentLoaded', function ready(e) { | ||
_.fire(document.documentElement, ['^ready'], undefined, [e]); | ||
Eventi.fire(document.documentElement, '^ready', e); | ||
}); | ||
} | ||
// add key syntax to _.parse's supported event properties | ||
_.keyRE = /\[([a-z-0-9,\.\/\[\`\\\]\']+)\]/; | ||
_.properties.push([_.keyRE, function parseKey(m, name) { | ||
var dash, key; | ||
while ((dash = name.indexOf('-')) > 0) { | ||
key = name.substring(0, dash); | ||
name = name.substring(dash+1); | ||
this[(_.special[key]||key)+'Key'] = true; | ||
_.split.guard['['] = ']'; | ||
_.parsers.push([/\[([^ ]+)\]/, function(event, handler, key) {//' | ||
var dash; | ||
while ((dash = key.indexOf('-')) > 0) { | ||
event[key.substring(0, dash)+'Key'] = true; | ||
key = key.substring(dash+1); | ||
} | ||
this.keyCode = _.codes[name] || parseInt(name, 10) || 0; | ||
if (key) { | ||
event.keyCode = _.codes[key] || parseInt(key, 10) || key; | ||
} | ||
}]); | ||
_.special = { command: 'meta', apple: 'meta' }; | ||
_.codes = { | ||
@@ -465,3 +523,3 @@ backspace:8, tab:9, enter:13, shift:16, ctrl:17, alt:18, capsLock:20, escape:27, start:91, command:224, | ||
multiply:106, plus:107, minus:109, point:110, divide:111, numLock:144,// numpad controls | ||
',':188, '.':190, '/':191, '`':192, '[':219, '\\':220, ']':221, '\'':222, space:32// symbols | ||
';':186, '=':187, ',':188, '-':189, '.':190, '/':191, '`':192, '[':219, '\\':220, ']':221, '\'':222, space:32// symbols | ||
}; | ||
@@ -473,99 +531,113 @@ for (var n=0; n<10; n++){ _.codes['num'+n] = 96+n; }// numpad numbers | ||
}); | ||
var h = global.history, | ||
l = global.location; | ||
_.pushState = h.pushState; | ||
h.pushState = function() { | ||
var ret = _.pushState.apply(this, arguments); | ||
_.dispatch(_.global, new Eventi('pushstate', {uri:arguments[2]})); | ||
return ret; | ||
}; | ||
Eventi.on('!popstate !hashchange !pushstate', _.at = function(e, uri) { | ||
uri = uri || decodeURI(l.pathname + l.search + l.hash); | ||
if (uri !== _.uri) { | ||
_.dispatch(_.global, new Eventi('location', { | ||
oldURI: _.uri, | ||
uri: _.uri = uri, | ||
srcEvent: e | ||
})); | ||
_.split.guard['@'] = '@'; | ||
_.parsers.unshift([/@([^@]+)(@|$)/, function(event, handler, uri) { | ||
handler.location = uri; | ||
if (_.location && event !== handler) { | ||
_.locationHandler(uri, handler); | ||
} | ||
return uri; | ||
}) | ||
.on('!location', function setUri(e, uri, fill) { | ||
if (typeof uri === "string") { | ||
var keys = _.keys(uri); | ||
if (keys) { | ||
uri = keys.reduce(function(s, key) { | ||
return s.replace(new RegExp('\\{'+key+'\\}',"g"), | ||
fill[key] || global.location[key] || ''); | ||
}, uri); | ||
}]); | ||
if (global.history && global.location) { | ||
var current; | ||
_.pushState = history.pushState; | ||
history.pushState = function() { | ||
var ret = _.pushState.apply(this, arguments); | ||
_.dispatch(_.global, new CustomEvent('pushstate')); | ||
return ret; | ||
}; | ||
_.location = function(e, uri) { | ||
uri = uri || decodeURI(location.pathname + location.search + location.hash); | ||
if (uri !== current) { | ||
_.dispatch(_.global, new Eventi('location', { | ||
oldLocation: current, | ||
location: current = uri, | ||
srcEvent: e | ||
})); | ||
} | ||
e.uri = uri; | ||
if (uri !== _.uri) { | ||
h.pushState(null,null, encodeURI(uri)); | ||
return current; | ||
}; | ||
_.setLocation = function(e, uri, fill) { | ||
if (typeof uri !== "string") { | ||
fill = uri; | ||
uri = e.location; | ||
} | ||
} else if (!e.uri) { | ||
e.uri = _.uri; | ||
} | ||
}) | ||
.on(_, 'handler#new', function location(e, handler) { | ||
if (handler.match.type === "location") { | ||
// always listen on window, but save given target to use as context | ||
handler._target = handler.target; | ||
handler.target = _.global; | ||
if (handler.selector) { | ||
// overloading on.js' selector argument with uri template/regex | ||
var re = handler.selector; | ||
delete handler.selector; | ||
if (typeof re === "string") { | ||
re = re.replace(/([.*+?^=!:$(|\[\/\\])/g, "\\$1"); | ||
if (handler.keys = _.keys(re)) { | ||
re = re.replace(/\{\w+\}/g, "([^\/?#]+)"); | ||
} else { | ||
re.replace(/\{/g, '\\{'); | ||
} | ||
re = new RegExp(re); | ||
if (uri) { | ||
var keys = _.keys(uri); | ||
if (keys) { | ||
uri = keys.reduce(function(s, key) { | ||
return s.replace(new RegExp('\\{'+key+'\\}',"g"), | ||
fill[key] || location[key] || ''); | ||
}, uri); | ||
} | ||
handler.regexp = re; | ||
if (uri !== current) { | ||
history.pushState(null, null, encodeURI(uri)); | ||
} | ||
} | ||
}; | ||
_.keys = function(tmpl) { | ||
var keys = tmpl.match(/\{\w+\}/g); | ||
return keys && keys.map(function(key) { | ||
return key.substring(1, key.length-1); | ||
}); | ||
}; | ||
_.locationHandler = function(uri, handler) { | ||
var re = uri; | ||
if (uri.charAt(0) === '`') { | ||
re = re.substring(1, re.length-1); | ||
} else { | ||
handler.regexp = /.+/; | ||
re = re.replace(/([.*+?^=!:$(|\[\/\\])/g, "\\$1");// escape uri/regexp conflicts | ||
if (handler.keys = _.keys(re)) { | ||
re = re.replace(/\{\w+\}/g, "([^\/?#]+)"); | ||
} else { | ||
re.replace(/\{/g, '\\{'); | ||
} | ||
} | ||
handler._fn = handler.fn; | ||
handler.fn = function(e){ _.location(e.uri, handler, arguments); }; | ||
// try for current uri match immediately | ||
_.execute(null, new Eventi('location',{uri:_.uri||_.at()}), handler); | ||
} | ||
}); | ||
_.keys = function(tmpl) { | ||
var keys = tmpl.match(/\{\w+\}/g); | ||
return keys && keys.map(function(key) { | ||
return key.substring(1, key.length-1); | ||
handler.uriRE = new RegExp(re); | ||
_.filter(handler, _.locationFilter); | ||
}; | ||
_.locationFilter = function(event, handler) { | ||
var matches = (event.uri || current).match(handler.uriRE); | ||
if (matches) { | ||
this.args.splice.apply(this.args, [1,0].concat(matches)); | ||
if (handler.keys) { | ||
// put key/match object in place of full match | ||
this.args[1] = handler.keys.reduce(function(o, key) { | ||
o[key] = matches.shift(); | ||
return o; | ||
}, { match: matches.shift() }); | ||
} | ||
} else { | ||
this.target = undefined; | ||
} | ||
}; | ||
Eventi.on('!popstate !hashchange !pushstate', _.location) | ||
.on('!location', _.setLocation) | ||
.on(_, 'on:handler', function location(e, handler) { | ||
if (handler.event.type === 'location') { | ||
// force global | ||
handler.global = true; | ||
// try for current uri match immediately | ||
if (!current) { | ||
_.location(); | ||
} | ||
_.execute(new Eventi('location',{location:current, srcEvent:e}), handler); | ||
} | ||
}); | ||
}; | ||
_.location = function(uri, handler, args) { | ||
var matches = (uri||_.uri).match(handler.regexp); | ||
if (matches) { | ||
args = _.slice(args); | ||
args.splice.apply(args, [1,0].concat(matches)); | ||
if (handler.keys) { | ||
// put key/match object in place of full match | ||
args[1] = handler.keys.reduce(function(o, key) { | ||
o[key] = matches.shift(); | ||
return o; | ||
}, { match: matches.shift() }); | ||
} | ||
handler._fn.apply(handler._target, args); | ||
} | ||
}; | ||
} | ||
_.off = function(target, events, fn) { | ||
//TODO: support filtering by selector/location | ||
var listener = target[_key]; | ||
if (listener) { | ||
for (var i=0, m=events.length; i<m; i++) { | ||
var filter = { fn:fn, match:{} }, | ||
type = _.parse(events[i], filter.match); | ||
delete filter.match.tags;// superfluous for matching | ||
if (type) { | ||
_.clean(type, filter, listener, target); | ||
var filter = { event:{}, handler:{}, fn:fn, text:events[i] }; | ||
_.parse(events[i], filter.event, filter.handler); | ||
// delete superfluous properties | ||
delete filter.event.tags; | ||
delete filter.handler.filters; | ||
delete filter.handler.end; | ||
if (target !== _) { | ||
Eventi.fire(_, 'off:filter', filter); | ||
} | ||
if (filter.event.type) { | ||
_.clean(filter.event.type, filter, listener, target); | ||
} else { | ||
for (type in listener.s) { | ||
for (var type in listener.s) { | ||
_.clean(type, filter, listener, target); | ||
@@ -581,3 +653,3 @@ } | ||
_.unhandle = function off(handler) { | ||
_.off(handler.target, [handler.text], handler._fn||handler.fn); | ||
_.off(handler.target, [handler.text], handler.fn); | ||
}; | ||
@@ -592,3 +664,3 @@ _.empty = function(o){ for (var k in o){ return !k; } return true; }; | ||
if (target !== _) {// ignore internal events | ||
Eventi.fire(_, 'handler#off', cleaned); | ||
Eventi.fire(_, 'off:cleaned', cleaned); | ||
} | ||
@@ -607,46 +679,33 @@ m--; | ||
_.cleans = function(handler, filter) { | ||
return _.matches(handler.match, filter.match, true) && | ||
(!filter.fn || filter.fn === (handler._fn||handler.fn)); | ||
return _.matches(handler.event, filter.event) && | ||
_.matches(handler, filter.handler) && | ||
(!handler.important || (filter.handler.important && | ||
_.matches(filter.event, handler.event))) && | ||
(!filter.fn || filter.fn === handler.fn); | ||
}; | ||
Eventi.off = _.wrap('off', 3); | ||
_.until = function(target, condition, events, selector, fn, data) { | ||
// adjust for absence of selector | ||
if (typeof selector !== "string") { | ||
if (fn !== undefined) { | ||
data = data ? data.unshift(fn) && data : [fn]; | ||
} | ||
fn = selector; | ||
} | ||
for (var i=0,m=events.length; i<m; i++) { | ||
var handler = _.handler(target, events[i], selector, fn, data); | ||
_.untilAfter(handler, condition); | ||
} | ||
_.parsers.unshift([/\$(\!?\w+(\.\w+)*)/, function(event, handler, condition) { | ||
handler.endtest = condition; | ||
handler.end = _.endTest(condition); | ||
}]); | ||
_.endTest = function(condition) { | ||
var callsLeft = parseInt(condition, 10); | ||
if (callsLeft) { | ||
return function(){ return !--callsLeft; }; | ||
} | ||
var not = condition.charAt(0) === '!'; | ||
if (not){ condition = condition.substring(1); } | ||
if (condition && _.resolveRE.test(condition)) { | ||
return function endRef() { | ||
var value = _.resolve(condition, this, true); | ||
if (value === undefined) { | ||
value = _.resolve(condition, true); | ||
} | ||
if (typeof value === "function") { | ||
value = value.apply(this, arguments); | ||
} | ||
return not ? !value : value; | ||
}; | ||
} | ||
}; | ||
_.untilAfter = function(handler, condition) { | ||
var stop = _.untilFn(handler, condition), | ||
fn = handler._fn = handler.fn; | ||
handler.fn = function() { | ||
fn.apply(this, arguments); | ||
if (stop()){ _.unhandle(handler); } | ||
}; | ||
}; | ||
_.untilFn = function(handler, condition) { | ||
switch (typeof condition) { | ||
case "undefined": | ||
case "function": return condition; | ||
case "number": return function(){ return !--condition; }; | ||
case "string": | ||
var not = condition.charAt(0) === '!'; | ||
if (not){ condition = condition.substring(1); } | ||
return function until() { | ||
var value = _.resolve(condition, handler.target); | ||
if (value === undefined) { | ||
value = _.resolve(condition); | ||
} | ||
return not ? !value : value; | ||
}; | ||
} | ||
}; | ||
Eventi.until = _.wrap('until', 5, 2); | ||
_.comboRE = /\+|>/; | ||
// overwrite fire.js' _.fireAll to watch for combo events | ||
@@ -656,3 +715,3 @@ _.fireAll = function(target, events, props, _resumeIndex) { | ||
for (var i=0; i<events.length; i++) { | ||
sequence = props.sequence = events[i].split(_.comboRE); | ||
sequence = props.sequence = _.split.ter(events[i], '+', ','); | ||
for (var j=_resumeIndex||0; j < sequence.length && (!event||!event.isSequencePaused()); j++) { | ||
@@ -675,3 +734,3 @@ if (sequence[j]) { | ||
paused = false; | ||
_.fireAll(target, props.sequence, props, index||props.index); | ||
_.fireAll(target, [props.sequence.join(',')], props, index||props.index+1); | ||
} | ||
@@ -687,86 +746,112 @@ }; | ||
}; | ||
Eventi.on(_, 'handler#new', function comboHandler(e, handler) { | ||
_.combo = { | ||
event: function(text) { | ||
return _.combo[text] || (_.combo[text] = { | ||
category: 'combo', | ||
type: '_'+(++_.combo.count) | ||
}); | ||
}, | ||
split: function(text) { | ||
var parts = _.split.ter(text, '+'); | ||
if (parts.length > 1) { | ||
parts.ordered = false; | ||
} else { | ||
parts = _.split.ter(text, ','); | ||
if (parts.length > 1) { | ||
parts.ordered = true; | ||
} | ||
} | ||
return parts; | ||
}, | ||
count: 0, | ||
reset: function() { | ||
if (this.clear){ clearTimeout(this.clear); } | ||
this.unfired = this.texts.slice(); | ||
this.events = []; | ||
}, | ||
eventFn: function(index, e) { | ||
if (this.timeout && !this.clear) { | ||
this.clear = setTimeout(this.reset, this.timeout); | ||
} | ||
if (!this.ordered || index-1 === this.unfired.lastIndexOf('')) { | ||
this.unfired[index] = ''; | ||
this.events.push(e); | ||
if (!this.unfired.join('')) { | ||
var event = new Eventi('combo:'+this.event.type); | ||
event.events = this.events; | ||
event.text = this.text; | ||
_.dispatch(this.target, event); | ||
this.reset(); | ||
} | ||
} | ||
} | ||
}; | ||
Eventi.on(_, 'on:handler', function comboHandler(e, handler) { | ||
var text = handler.text, | ||
joint = text.match(_.comboRE); | ||
if (joint) { | ||
var types = text.split(joint[0]), | ||
fn = handler.comboFn = _.comboFn(joint[0]==='>', types, text); | ||
for (var i=0,m=types.length; i<m; i++) { | ||
// override full type with parsed, core type for comboFn's use | ||
types[i] = _.handler(handler.target, types[i], handler.selector, fn).type; | ||
} | ||
fn.reset(); | ||
texts = _.combo.split(text); | ||
if (texts.length > 1) { | ||
handler.event = _.combo.event(text); | ||
if (handler.data && typeof handler.data[0] === "number") { | ||
handler.timeout = handler.data.shift(); | ||
} | ||
delete handler.singleton; | ||
delete handler.selector; | ||
delete handler.location; | ||
delete handler.filters; | ||
delete handler.endtest; | ||
delete handler.end; | ||
// set up combo event handlers | ||
handler.texts = texts; | ||
handler.ordered = texts.ordered; | ||
handler.reset = _.combo.reset.bind(handler); | ||
handler.handlers = texts.map(function(text, index) { | ||
return _.handler(handler.target, text, _.combo.eventFn.bind(handler, index)); | ||
}); | ||
handler.reset(); | ||
} | ||
}).on(_, 'off:filter', function comboFilter(e, filter) { | ||
if (_.combo.split(filter.text).length > 1) { | ||
filter.event = _.combo.event(filter.text); | ||
} | ||
}).on(_, 'off:cleaned', function comboOff(e, handler) { | ||
if (handler.handlers) { | ||
handler.handlers.forEach(_.unhandle); | ||
} | ||
}); | ||
_.comboTimeout = 1000; | ||
_.comboFn = function(ordered, types, text) { | ||
var waitingFor, | ||
clear, | ||
reset = function() { | ||
if (clear){ clearTimeout(clear); } | ||
waitingFor = types.slice(); | ||
}, | ||
fn = function(e) { | ||
if (!clear){ clear = setTimeout(reset, _.comboTimeout); } | ||
var i = waitingFor.indexOf(e.type); | ||
if (ordered ? i === 0 : i >= 0) { | ||
waitingFor.splice(i, 1); | ||
if (!waitingFor.length) { | ||
_.fire(e.target, text); | ||
reset(); | ||
} | ||
} | ||
}; | ||
fn.reset = reset; | ||
return fn; | ||
}; | ||
// watch for handler.comboFn and remove sub-handlers | ||
Eventi.on(_, 'handler#off', function cleanedHandler(e, handler) { | ||
if (handler.comboFn) { | ||
_.off(handler.target, '', handler.comboFn); | ||
} | ||
}); | ||
// memoizes results | ||
_.types = function(type) { | ||
return _.types[type] || (_.types[type] = function types(target) { | ||
_.alias = function(alias, text, context) { | ||
return function aliased(target) { | ||
var args = _.slice(arguments), | ||
index = this.index || 1; | ||
if (typeof target !== "object" || !(target.dispatchEvent || target[_key])) { | ||
index--; | ||
} | ||
args.splice(index, 0, type); | ||
return this.apply(null, args); | ||
}); | ||
index = (typeof target !== "object" || !(target.dispatchEvent || target[_key])) ? 0 : 1; | ||
args.splice(index, 0, text); | ||
return this.apply(context, args); | ||
}; | ||
}; | ||
// a simple, more debugging-friendly bind | ||
_.bind = function(o, fn) { | ||
var bound = function bound(){ return fn.apply(o, arguments); }; | ||
bound.index = fn.index;// keep index for _.types to use | ||
return bound; | ||
}; | ||
(Eventi.types = function(o) { | ||
var types = _.slice(arguments); | ||
if (typeof o === "string") { | ||
o = Eventi; | ||
(Eventi.alias = function(context) { | ||
var texts = _.slice(arguments, 1), | ||
props; | ||
if (typeof context === "string") { | ||
texts.unshift(context); | ||
context = Eventi; | ||
} | ||
for (var p in Eventi) { | ||
var fn = o[p]; | ||
for (var prop in Eventi) { | ||
var fn = context[prop]; | ||
if (typeof fn === "function" && !fn.utility) { | ||
if (o !== Eventi && fn === Eventi[p]) { | ||
// use local copy of fn to bind context and avoid shared types | ||
fn = o[p] = _.bind(o, fn); | ||
if (context !== Eventi && fn === Eventi[prop]) { | ||
// prevent shared aliases for different Eventi-fied objects | ||
fn = context[prop] = fn.bind(context); | ||
} | ||
for (var i=0,m=types.length; i<m; i++) { | ||
var type = types[i]; | ||
fn[type] = _.types(type); | ||
for (var i=0,m=texts.length; i<m; i++) { | ||
props = {}; | ||
_.parse(texts[i], props, props); | ||
props.alias = props.alias || props.type; | ||
fn[props.alias] = _.alias(props.alias, texts[i], context); | ||
} | ||
} | ||
} | ||
return props; | ||
}).utility = true; | ||
_.version = "0.7.1"; | ||
_.version = "1.0.0"; | ||
var sP = (Event && Event.prototype.stopPropagation) || _.noop, | ||
sIP = (Event && Event.prototype.stopImmediatePropagation) || _.noop; | ||
var sP = (global.Event && Event.prototype.stopPropagation) || _.noop, | ||
sIP = (global.Event && Event.prototype.stopImmediatePropagation) || _.noop; | ||
CustomEvent.prototype.stopPropagation = function() { | ||
@@ -773,0 +858,0 @@ this.propagationStopped = true; |
@@ -1,4 +0,4 @@ | ||
/*! Eventi - v0.7.1 - 2014-03-13 | ||
/*! Eventi - v1.0.0 - 2014-04-03 | ||
* https://github.com/nbubna/Eventi | ||
* Copyright (c) 2014 ESHA Research; Licensed MIT */ | ||
!function(global,document){"use strict";function Eventi(){return _.create.apply(this,arguments)}global.CustomEvent||(global.CustomEvent=document?function(a,b){b=b||{};var c=document.createEvent("CustomEvent");return c.initCustomEvent(a,!!b.bubbles,!!b.cancelable,b.detail),c}:function(a,b){b=b||{},this.type=a,this.bubbles=!!b.bubbles,this.detail=b.detail,this.timestamp=Date.now()});var _={global:new Function("return this")(),noop:function(){},slice:function(a,b){return Array.prototype.slice.call(a,b)},copy:function(a,b,c){if(a)for(c in a)a.hasOwnProperty(c)&&(b[c]=a[c])},async:global.setImmediate||function(a){return setTimeout(a,0)},resolveRE:/^([\w\$]+)?((\.[\w\$]+)|\[(\d+|'(\\'|[^'])+'|"(\\"|[^"])+")\])*$/,resolve:function(reference,context){if(_.resolveRE.test(reference)){context=context||global;try{return eval("context"+("["!==reference.charAt(0)?"."+reference:reference))}catch(e){}}},create:function(a,b){var c={text:a+""};a=_.parse(c.text,c),_.copy(b,c),"bubbles"in c||(c.bubbles=!0);var d=new CustomEvent(a,c);for(var e in c)_.skip.indexOf(e)<0&&(d[_.prop(e)]=c[e]);return d},skip:"bubbles cancelable detail type".split(" "),prop:function(a){return a},parse:function(a,b){return _.properties.forEach(function(c){a=a.replace(c[0],function(){return c[1].apply(b,arguments)||""})}),a?b.type=a:a},properties:[[/^_/,function(){this.bubbles=!1}],[/^\!/,function(){this._protect=!0}],[/\((.*)\)/,function(a,b){try{this.detail=_.resolve(b)||JSON.parse(b)}catch(c){this.detail=b}}],[/#(\w+)/g,function(a,b){(this.tags||(this.tags=[])).push(b),this[b]=!0}],[/^(\w+):/,function(a,b){this.category=b}]],splitRE:/ (?![^\(\)]*\))+/g,wrap:function(a,b,c){c=c||1;var d=function(d){var e=_.slice(arguments);d&&"string"!=typeof d||(d=this&&this!==Eventi?this:_.global,e.unshift(d)),e[c]=e[c]?(e[c]+"").split(_.splitRE):[""],e.length>b&&(e[b]=e.slice(b),e=e.slice(0,b+1));var f,g=_[a];if("length"in d&&d!==_.global)for(var h=0,i=d.length;i>h;h++)f=g.apply(e[0]=d[h],e);else f=g.apply(d,e);return void 0===f?this:f};return d.index=c,d}};Eventi._=_,(Eventi.fy=function(a){for(var b in Eventi){var c=Eventi[b];"function"!=typeof c||c.utility||Object.defineProperty(a,b,{value:c,writable:!0,configurable:!0})}return a}).utility=!0,_.fire=function(a,b,c,d){return"object"!=typeof c||c instanceof Event||!("bubbles"in c||"detail"in c||"cancelable"in c)?(void 0!==c&&(d=d?d.unshift(c)&&d:[c]),c={data:d}):c.data=d,_.fireAll(a,b,c)},_.fireAll=function(a,b,c){for(var d,e=0;e<b.length;e++)d=_.create(b[e],c),_.dispatch(a,d);return d},_.dispatch=function(a,b,c){(a.dispatchEvent||a[_key]||_.noop).call(a,b),a.parentObject&&b.bubbles&&!b.propagationStopped&&_.dispatch(a.parentObject,b,!0),!c&&b._singleton&&_.singleton(a,b)},Eventi.fire=_.wrap("fire",3),_.on=function(a,b,c,d,e){"function"==typeof c&&(void 0!==d&&(e=e?e.unshift(d)&&e:[d]),d=c,c=null);for(var f=0,g=b.length;g>f;f++)_.handler(a,b[f],c,d,e)},_.handler=function(a,b,c,d,e){var f={target:a,selector:c,fn:d,data:e,text:b,match:{}};return _.parse(b,f.match),delete f.match.tags,a!==_&&Eventi.fire(_,"handler#new",f),f.fn!==_.noop&&_.handlers(f.target,f.match.type).push(f),f},_.handlers=function(a,b){var c=_.listener(a),d=c.s[b];return d||(d=c.s[b]=[],a.addEventListener&&a.addEventListener(b,c)),d};var _key=_._key="_eventi"+Date.now();if(_.listener=function(a){var b=a[_key];return b||(b=function(a){var c=b.s[a.type];c&&_.handle(a,c)},b.s={},Object.defineProperty(a,_key,{value:b,writeable:!1,configurable:!0})),b},_.handle=function(a,b){for(var c,d,e=0;e<b.length&&!(_.matches(a,(c=b[e]).match)&&(d=_.target(c,a.target))&&(_.execute(d,a,c),a.immediatePropagationStopped));e++);},_.execute=function(a,b,c){var d=[b];b.data&&d.push.apply(d,b.data),c.data&&d.push.apply(d,c.data);try{c.fn.apply(a,d)}catch(e){_.async(function(){throw e})}},_.unhandle=function(a){a.fn=_.noop},_.matches=function(a,b,c){for(var d in b)if(b[d]!==a[d]&&(c||"_"!==d.charAt(0)))return!1;if(c)for(d in a)if("_"===d.charAt(0)&&a[d]!==b[d])return!1;return!0},_.target=function(a,b){return a.selector?_.closest(b,a.selector):a.target},_.closest=function(a,b){for(;a&&a.matches;){if(a.matches(b))return a;a=a.parentNode}},global.Element){var Ep=Element.prototype,aS="atchesSelector";Ep.matches||Object.defineProperty(Ep,"matches",{value:Ep["webkitM"+aS]||Ep["mozM"+aS]||Ep["msM"+aS]})}Eventi.on=_.wrap("on",4),document&&(_.init=function(){for(var a=document.querySelectorAll("[data-eventi]"),b=0,c=a.length;c>b;b++){var d=a[b],e=d.getAttribute("data-eventi");e&&_.declare(e,d)}(a.length||document.querySelectorAll("[click]").length)&&Eventi.on("click keyup",_.check)},_.declare=function(a,b){for(var c=a.split(_.splitRE),d=0,e=c.length;e>d;d++){var f=c[d],g=f.lastIndexOf("="),h=g>0?f.substring(g+1):void 0,i="/"===f.charAt(0),j=i?_.global:b;b=b||document,h&&(f=f.substring(0,g)),i&&(f=f.substring(1)),Eventi.on(j,f,_.mapped,b,h)}},_.mapped=function(a,b,c){for(var d=c||a.type,e=_.declarers(b,d,this!==_.global&&a.target),f=0,g=e.length;g>f;f++)_.declared(e[f],d,a)},_.declarers=function(a,b,c){var d="["+b+"]";if(c){for(var e=[];c&&c.matches&&c!==a.parentNode;)c.matches(d)&&e.push(c),c=c.parentNode;return e}return a.querySelectorAll(d)},_.declared=function(a,b,c){var d=a.getAttribute(b);if(d){var e=_.resolve(d,a)||_.resolve(d);"function"==typeof e?e.call(a,c):Eventi.fire(a,d,c)}},_.check=function(a){var b="click"===a.type&&_.click(a.target)||13===a.keyCode&&_.click(a.target,!0);b&&(_.mapped(a,document.documentElement,"click"),"noDefault"!==b||_.allowDefault(a.target)||a.preventDefault())},_.allowDefault=function(a){return"radio"===a.type||"checkbox"===a.type},_.click=function(a,b){var c=a.getAttribute("click");if(c&&"false"!==c)return"noDefault";if(!a.isContentEditable){var d=a.nodeName.toLowerCase();return"textarea"!==d&&("select"!==d||b)&&(b?!("a"===d&&a.getAttribute("href")||"button"===d||"input"===d&&_.buttonRE.test(a.type)):"input"!==d||_.buttonRE.test(a.type))}},_.buttonRE=/^(submit|button|reset)$/,Eventi.on("DOMContentLoaded",_.init)),_.properties.unshift([/^\^/,function(){this._singleton=!0}]),_.singleton=function(a,b){_.remember(a,b),b.bubbles&&!b.propagationStopped&&a!==_.global&&_.singleton(a.parentNode||a.parentObject||_.global,b)};var _skey=_._skey="^"+_key;_.remember=function(a,b){var c=a[_skey]||[];c.length||Object.defineProperty(a,_skey,{value:c,configurable:!0}),b[_skey]=!0,c.push(b)},Eventi.on(_,"handler#new",function(a,b){if(b.match._singleton){var c=b._fn=b.fn;b.fn=function(a){_.unhandle(b),a[_skey]||_.remember(b.target,a),c.apply(this,arguments)};for(var d=b.target[_skey]||[],e=0,f=d.length;f>e;e++){var g=d[e];if(_.matches(g,b.match)){var h=_.target(b,g.target);if(h){_.execute(h,g,b),b.fn=_.noop;break}}}}}),document&&Eventi.on("DOMContentLoaded",function(a){_.fire(document.documentElement,["^ready"],void 0,[a])}),_.keyRE=/\[([a-z-0-9,\.\/\[\`\\\]\']+)\]/,_.properties.push([_.keyRE,function(a,b){for(var c,d;(c=b.indexOf("-"))>0;)d=b.substring(0,c),b=b.substring(c+1),this[(_.special[d]||d)+"Key"]=!0;this.keyCode=_.codes[b]||parseInt(b,10)||0}]),_.special={command:"meta",apple:"meta"},_.codes={backspace:8,tab:9,enter:13,shift:16,ctrl:17,alt:18,capsLock:20,escape:27,start:91,command:224,pageUp:33,pageDown:34,end:35,home:36,left:37,up:38,right:39,down:40,insert:45,"delete":46,multiply:106,plus:107,minus:109,point:110,divide:111,numLock:144,",":188,".":190,"/":191,"`":192,"[":219,"\\":220,"]":221,"'":222,space:32};for(var n=0;10>n;n++)_.codes["num"+n]=96+n;for(var f=1;13>f;f++)_.codes["f"+f]=111+f;"abcdefghijklmnopqrstuvwxyz 0123456789".split("").forEach(function(a){_.codes[a]=a.toUpperCase().charCodeAt(0)});var h=global.history,l=global.location;_.pushState=h.pushState,h.pushState=function(){var a=_.pushState.apply(this,arguments);return _.dispatch(_.global,new Eventi("pushstate",{uri:arguments[2]})),a},Eventi.on("!popstate !hashchange !pushstate",_.at=function(a,b){return b=b||decodeURI(l.pathname+l.search+l.hash),b!==_.uri&&_.dispatch(_.global,new Eventi("location",{oldURI:_.uri,uri:_.uri=b,srcEvent:a})),b}).on("!location",function(a,b,c){if("string"==typeof b){var d=_.keys(b);d&&(b=d.reduce(function(a,b){return a.replace(new RegExp("\\{"+b+"\\}","g"),c[b]||global.location[b]||"")},b)),a.uri=b,b!==_.uri&&h.pushState(null,null,encodeURI(b))}else a.uri||(a.uri=_.uri)}).on(_,"handler#new",function(a,b){if("location"===b.match.type){if(b._target=b.target,b.target=_.global,b.selector){var c=b.selector;delete b.selector,"string"==typeof c&&(c=c.replace(/([.*+?^=!:$(|\[\/\\])/g,"\\$1"),(b.keys=_.keys(c))?c=c.replace(/\{\w+\}/g,"([^/?#]+)"):c.replace(/\{/g,"\\{"),c=new RegExp(c)),b.regexp=c}else b.regexp=/.+/;b._fn=b.fn,b.fn=function(a){_.location(a.uri,b,arguments)},_.execute(null,new Eventi("location",{uri:_.uri||_.at()}),b)}}),_.keys=function(a){var b=a.match(/\{\w+\}/g);return b&&b.map(function(a){return a.substring(1,a.length-1)})},_.location=function(a,b,c){var d=(a||_.uri).match(b.regexp);d&&(c=_.slice(c),c.splice.apply(c,[1,0].concat(d)),b.keys&&(c[1]=b.keys.reduce(function(a,b){return a[b]=d.shift(),a},{match:d.shift()})),b._fn.apply(b._target,c))},_.off=function(a,b,c){var d=a[_key];if(d){for(var e=0,f=b.length;f>e;e++){var g={fn:c,match:{}},h=_.parse(b[e],g.match);if(delete g.match.tags,h)_.clean(h,g,d,a);else for(h in d.s)_.clean(h,g,d,a)}_.empty(d.s)&&delete a[_key]}},_.unhandle=function(a){_.off(a.target,[a.text],a._fn||a.fn)},_.empty=function(a){for(var b in a)return!b;return!0},_.clean=function(a,b,c,d){var e=c.s[a];if(e){for(var f=0,g=e.length;g>f;f++)if(_.cleans(e[f],b)){var h=e.splice(f--,1)[0];d!==_&&Eventi.fire(_,"handler#off",h),g--}e.length||(d.removeEventListener&&d.removeEventListener(a,c),delete c.s[a])}},_.cleans=function(a,b){return _.matches(a.match,b.match,!0)&&(!b.fn||b.fn===(a._fn||a.fn))},Eventi.off=_.wrap("off",3),_.until=function(a,b,c,d,e,f){"string"!=typeof d&&(void 0!==e&&(f=f?f.unshift(e)&&f:[e]),e=d);for(var g=0,h=c.length;h>g;g++){var i=_.handler(a,c[g],d,e,f);_.untilAfter(i,b)}},_.untilAfter=function(a,b){var c=_.untilFn(a,b),d=a._fn=a.fn;a.fn=function(){d.apply(this,arguments),c()&&_.unhandle(a)}},_.untilFn=function(a,b){switch(typeof b){case"undefined":case"function":return b;case"number":return function(){return!--b};case"string":var c="!"===b.charAt(0);return c&&(b=b.substring(1)),function(){var d=_.resolve(b,a.target);return void 0===d&&(d=_.resolve(b)),c?!d:d}}},Eventi.until=_.wrap("until",5,2),_.comboRE=/\+|>/,_.fireAll=function(a,b,c,d){for(var e,f,g=0;g<b.length;g++){f=c.sequence=b[g].split(_.comboRE);for(var h=d||0;h<f.length&&(!e||!e.isSequencePaused());h++)f[h]?(c.index=h,e=c.previousEvent=_.create(f[h],c),_.sequence(e,c,a),_.dispatch(a,e)):f.splice(h--,1)}return e},_.sequence=function(a,b,c,d){a.resumeSequence=function(a){d&&(d=!1,_.fireAll(c,b.sequence,b,a||b.index))},a.pauseSequence=function(a){return d!==!1?(d=!0,a&&a.then(this.resumeSequence)):void 0},a.isSequencePaused=function(){return!!d}},Eventi.on(_,"handler#new",function(a,b){var c=b.text,d=c.match(_.comboRE);if(d){for(var e=c.split(d[0]),f=b.comboFn=_.comboFn(">"===d[0],e,c),g=0,h=e.length;h>g;g++)e[g]=_.handler(b.target,e[g],b.selector,f).type;f.reset()}}),_.comboTimeout=1e3,_.comboFn=function(a,b,c){var d,e,f=function(){e&&clearTimeout(e),d=b.slice()},g=function(b){e||(e=setTimeout(f,_.comboTimeout));var g=d.indexOf(b.type);(a?0===g:g>=0)&&(d.splice(g,1),d.length||(_.fire(b.target,c),f()))};return g.reset=f,g},Eventi.on(_,"handler#off",function(a,b){b.comboFn&&_.off(b.target,"",b.comboFn)}),_.types=function(a){return _.types[a]||(_.types[a]=function(b){var c=_.slice(arguments),d=this.index||1;return("object"!=typeof b||!b.dispatchEvent&&!b[_key])&&d--,c.splice(d,0,a),this.apply(null,c)})},_.bind=function(a,b){var c=function(){return b.apply(a,arguments)};return c.index=b.index,c},(Eventi.types=function(a){var b=_.slice(arguments);"string"==typeof a&&(a=Eventi);for(var c in Eventi){var d=a[c];if("function"==typeof d&&!d.utility){a!==Eventi&&d===Eventi[c]&&(d=a[c]=_.bind(a,d));for(var e=0,f=b.length;f>e;e++){var g=b[e];d[g]=_.types(g)}}}}).utility=!0,_.version="0.7.1";var sP=Event&&Event.prototype.stopPropagation||_.noop,sIP=Event&&Event.prototype.stopImmediatePropagation||_.noop;CustomEvent.prototype.stopPropagation=function(){this.propagationStopped=!0,sP.call(this)},CustomEvent.prototype.stopImmediatePropagation=function(){this.immediatePropagationStopped=!0,sIP.call(this)};var define=global.define||_.noop;define((global.exports||global).Eventi=Eventi)}(this,this.document); | ||
!function(global,document){"use strict";function Eventi(){return _.create.apply(this,arguments)}global.CustomEvent||(global.CustomEvent=document?function(a,b){b=b||{};var c=document.createEvent("CustomEvent");return c.initCustomEvent(a,!!b.bubbles,!!b.cancelable,b.detail),c}:function(a,b){b=b||{},this.type=a,this.bubbles=!!b.bubbles,this.detail=b.detail,this.timestamp=Date.now()},global.Event||(global.Event=global.CustomEvent));var _={global:new Function("return this")(),noop:function(){},slice:function(a,b){return Array.prototype.slice.call(a,b)},copy:function(a,b,c){if("object"==typeof a)for(c in a)a.hasOwnProperty(c)&&(b[c]=a[c])},async:global.setImmediate||function(a){return setTimeout(a,0)},resolveRE:/^([\w\$]+)?((\.[\w\$]+)|\[(\d+|'(\\'|[^'])+'|"(\\"|[^"])+")\])*$/,resolve:function(reference,context,tested){if(tested||_.resolveRE.test(reference)){context=context||global;try{return eval("context"+("["!==reference.charAt(0)?"."+reference:reference))}catch(e){}}},create:function(a,b){var c={text:a+""};a=_.parse(c.text,c,c),_.copy(b,c),"bubbles"in c||(c.bubbles=!0);var d=new CustomEvent(a,c);for(var e in c)_.skip.indexOf(e)<0&&(d[_.prop(e)]=c[e]);return d},skip:"bubbles cancelable detail type".split(" "),prop:function(a){return a},parse:function(a,b,c){return _.parsers.forEach(function(d){a=a.replace(d[0],function(){var a=_.slice(arguments,1);return a.unshift(b,c),d[1].apply(b,a)||""})}),a?b.type=a:a},parsers:[[/^(\W*)_/,function(a,b,c){return a.bubbles=!1,c}],[/\((.*)\)/,function(a,b,c){try{a.detail=_.resolve(c)||JSON.parse(c)}catch(d){a.detail=c}}],[/#(\w+)/g,function(a,b,c){(a.tags||(a.tags=[])).push(c),a[c]=!0}],[/^(\w+):/,function(a,b,c){a.category=c}]],wrap:function(a,b){return function(c){var d=_.slice(arguments);(!c||"string"==typeof c||c instanceof global.Event)&&d.unshift(c=this&&this!==Eventi?this:_.global),d.length>b&&(d[b]=d.slice(b),d=d.slice(0,b+1)),d[1]&&"string"!=typeof d[1]||(d[1]=_.split.ter(d[1]));var e,f=_[a];if("length"in c&&c!==_.global)for(var g=0,h=c.length;h>g;g++)e=f.apply(d[0]=c[g],d);else e=f.apply(c,d);return void 0===e?this:e}},split:{guard:{"(":")"},ter:function(a,b){var c,d=[],e="";if(a){b=_.slice(arguments,1),b.unshift(" ");for(var f=0,g=a.length;g>f;f++){var h=a.charAt(f);!c&&b.indexOf(h)>=0?(e&&d.push(e),e=""):(e+=h,c?c===h&&("\\"===e.charAt(e.length-2)?e=e.replace("\\"+h,h):c=null):c=_.split.guard[h])}e&&d.push(e)}else d.push("");return d}}};Eventi._=_,(Eventi.fy=function(a){for(var b in Eventi){var c=Eventi[b];"function"!=typeof c||c.utility||Object.defineProperty(a,b,{value:c,writable:!0,configurable:!0})}return a}).utility=!0,_.parsers.unshift([/^(\W*)\//,function(a,b,c){return b.global=!0,c}]),_.fire=function(a,b,c){return b instanceof Event?(b.data=c,_.dispatch(a,b),b):_.fireAll(a,b,{data:c})},_.fireAll=function(a,b,c){for(var d,e=0;e<b.length;e++)d=_.create(b[e],c),_.dispatch(a,d);return d},_.dispatch=function(a,b,c){b.global&&(a=_.global),(a.dispatchEvent||a[_key]||_.noop).call(a,b),a.parentObject&&b.bubbles&&!b.propagationStopped&&_.dispatch(a.parentObject,b,!0),!c&&b.singleton&&_.singleton(a,b)},Eventi.fire=_.wrap("fire",2),_.parsers.unshift([/^(\W*)\!/,function(a,b,c){return b.important=!0,c}]),_.on=function(a,b,c,d){if(Array.isArray(b))for(var e=0,f=b.length;f>e;e++)_.handler(a,b[e],c,d);else{void 0!==c&&(d=d?d.unshift(c)&&d:[c]);for(var g in b)_.handler(a,g,b[g],d)}},_.handler=function(a,b,c,d){var e={target:a,fn:c,data:d,text:b,event:{}};return _.parse(b,e.event,e),delete e.event.tags,a!==_&&Eventi.fire(_,"on:handler",e),e.fn!==_.noop&&(a=e.global===!0?_.global:e.target,_.handlers(a,e.event.type).push(e)),e},_.handlers=function(a,b){var c=_.listener(a),d=c.s[b];return d||(d=c.s[b]=[],a.addEventListener&&a.addEventListener(b,c)),d};var _key=_._key="_eventi"+Date.now();if(_.listener=function(a){var b=a[_key];return b||(b=function(a){var c=b.s[a.type];c&&_.handle(a,c)},b.s={},Object.defineProperty(a,_key,{value:b,writeable:!1,configurable:!0})),b},_.handle=function(a,b){for(var c,d=0;d<b.length&&(!_.matches(a,(c=b[d]).event)||(_.execute(a,c),!a.immediatePropagationStopped));d++);},_.execute=function(a,b){var c=[a],d=b.fn,e={target:b.target,args:c};if(a.data&&c.push.apply(c,a.data),b.data&&c.push.apply(c,b.data),b.filters)for(var f=0,g=b.filters.length;g>f&&e.target;f++)b.filters[f].call(e,a,b);if(e.target){try{d.apply(e.target,e.args)}catch(h){_.async(function(){throw h})}b.end&&b.end.apply(e.target,e.args)&&_.unhandle(b)}},_.filter=function(a,b){a.filters=a.filters||[],a.filters.push(b)},_.unhandle=function(a){a.fn=_.noop},_.matches=function(a,b){for(var c in b)if(b[c]!==a[c])return!1;return!0},Eventi.on=_.wrap("on",3),_.split.guard["<"]=">",_.parsers.unshift([/<(.+)>/,function(a,b,c){b.selector=c,_.delegate&&a!==b&&_.filter(b,_.delegate)}]),global.Element){_.delegate=function(a,b){this.target=_.closest(a.target,b.selector)},_.closest=function(a,b){for(;a&&a.matches;){if(a.matches(b))return a;a=a.parentNode}};var Ep=Element.prototype,aS="atchesSelector";Ep.matches||Object.defineProperty(Ep,"matches",{value:Ep["webkitM"+aS]||Ep["mozM"+aS]||Ep["msM"+aS]})}_.parsers.unshift([/=>(\w+)$/,function(a,b,c){b.alias=c,b!==a&&(b.data=b.data||[],b.data.push(c))}]),document&&(_.init=function(){for(var a=document.querySelectorAll("[data-eventi]"),b=0,c=a.length;c>b;b++){var d=a[b],e=d.getAttribute("data-eventi");e!==d.eventi&&(_.off&&d.eventi&&Eventi.off(d,d.eventi,_.declared),d.eventi=e,_.declare(d,e))}(a.length||document.querySelectorAll("[click]").length)&&Eventi.on("click keyup",_.check)},_.declare=function(a,b){for(var c=_.split.ter(b),d=0,e=c.length;e>d;d++)Eventi.on(a,c[d],_.declared)},_.declared=function(a,b){b="string"==typeof b?b:a.type;for(var c=_.declarers(this,b,a.target),d=0,e=c.length;e>d;d++)_.respond(c[d],b,a)},_.declarers=function(a,b,c){for(var d="["+b+"]",e=[],f=!1;c&&c.matches;){if(c.matches(d)&&e.push(c),c===a){f=!0;break}c=c.parentNode}return f?e:a.querySelectorAll(d)},_.respond=function(a,b,c){var d=a.getAttribute(b);if(d){var e=_.resolve(d,a)||_.resolve(d);"function"==typeof e?e.call(a,c):Eventi.fire(a,d,c)}},_.check=function(a){var b=a.target.getAttribute&&("click"===a.type&&_.click(a.target)||13===a.keyCode&&_.click(a.target,!0));b&&(_.declared.call(document.documentElement,a,"click"),"noDefault"!==b||_.allowDefault(a.target)||a.preventDefault())},_.allowDefault=function(a){return"radio"===a.type||"checkbox"===a.type},_.click=function(a,b){var c=a.getAttribute("click");if(c&&"false"!==c)return"noDefault";if(!a.isContentEditable){var d=a.nodeName.toLowerCase();return"textarea"!==d&&("select"!==d||b)&&(b?!("a"===d&&a.getAttribute("href")||"button"===d||"input"===d&&_.buttonRE.test(a.type)):"input"!==d||_.buttonRE.test(a.type))}},_.buttonRE=/^(submit|button|reset)$/,Eventi.on("DOMContentLoaded",_.init)),_.parsers.unshift([/^(\W*)\^/,function(a,b,c){return b.singleton=!0,a!==b&&_.filter(b,_.before),c}]),_.singleton=function(a,b){_.remember(a,b),b.bubbles&&!b.propagationStopped&&a!==_.global&&_.singleton(a.parentNode||a.parentObject||_.global,b)};var _skey=_._skey="^"+_key;_.remember=function(a,b){var c=a[_skey]||[];c.length||Object.defineProperty(a,_skey,{value:c,configurable:!0}),b[_skey]=!0,c.push(b)},_.before=function(a,b){_.unhandle(b),b.fn=_.noop,a[_skey]||_.remember(this.target,a)},Eventi.on(_,"on:handler",function(a,b){if(b.singleton)for(var c=b.target[_skey]||[],d=0,e=c.length;e>d;d++){var f=c[d];if(_.matches(f,b.event)){_.execute(f,b);break}}}),document&&Eventi.on("DOMContentLoaded",function(a){Eventi.fire(document.documentElement,"^ready",a)}),_.split.guard["["]="]",_.parsers.push([/\[([^ ]+)\]/,function(a,b,c){for(var d;(d=c.indexOf("-"))>0;)a[c.substring(0,d)+"Key"]=!0,c=c.substring(d+1);c&&(a.keyCode=_.codes[c]||parseInt(c,10)||c)}]),_.codes={backspace:8,tab:9,enter:13,shift:16,ctrl:17,alt:18,capsLock:20,escape:27,start:91,command:224,pageUp:33,pageDown:34,end:35,home:36,left:37,up:38,right:39,down:40,insert:45,"delete":46,multiply:106,plus:107,minus:109,point:110,divide:111,numLock:144,";":186,"=":187,",":188,"-":189,".":190,"/":191,"`":192,"[":219,"\\":220,"]":221,"'":222,space:32};for(var n=0;10>n;n++)_.codes["num"+n]=96+n;for(var f=1;13>f;f++)_.codes["f"+f]=111+f;if("abcdefghijklmnopqrstuvwxyz 0123456789".split("").forEach(function(a){_.codes[a]=a.toUpperCase().charCodeAt(0)}),_.split.guard["@"]="@",_.parsers.unshift([/@([^@]+)(@|$)/,function(a,b,c){b.location=c,_.location&&a!==b&&_.locationHandler(c,b)}]),global.history&&global.location){var current;_.pushState=history.pushState,history.pushState=function(){var a=_.pushState.apply(this,arguments);return _.dispatch(_.global,new CustomEvent("pushstate")),a},_.location=function(a,b){return b=b||decodeURI(location.pathname+location.search+location.hash),b!==current&&_.dispatch(_.global,new Eventi("location",{oldLocation:current,location:current=b,srcEvent:a})),current},_.setLocation=function(a,b,c){if("string"!=typeof b&&(c=b,b=a.location),b){var d=_.keys(b);d&&(b=d.reduce(function(a,b){return a.replace(new RegExp("\\{"+b+"\\}","g"),c[b]||location[b]||"")},b)),b!==current&&history.pushState(null,null,encodeURI(b))}},_.keys=function(a){var b=a.match(/\{\w+\}/g);return b&&b.map(function(a){return a.substring(1,a.length-1)})},_.locationHandler=function(a,b){var c=a;"`"===a.charAt(0)?c=c.substring(1,c.length-1):(c=c.replace(/([.*+?^=!:$(|\[\/\\])/g,"\\$1"),(b.keys=_.keys(c))?c=c.replace(/\{\w+\}/g,"([^/?#]+)"):c.replace(/\{/g,"\\{")),b.uriRE=new RegExp(c),_.filter(b,_.locationFilter)},_.locationFilter=function(a,b){var c=(a.uri||current).match(b.uriRE);c?(this.args.splice.apply(this.args,[1,0].concat(c)),b.keys&&(this.args[1]=b.keys.reduce(function(a,b){return a[b]=c.shift(),a},{match:c.shift()}))):this.target=void 0},Eventi.on("!popstate !hashchange !pushstate",_.location).on("!location",_.setLocation).on(_,"on:handler",function(a,b){"location"===b.event.type&&(b.global=!0,current||_.location(),_.execute(new Eventi("location",{location:current,srcEvent:a}),b))})}_.off=function(a,b,c){var d=a[_key];if(d){for(var e=0,f=b.length;f>e;e++){var g={event:{},handler:{},fn:c,text:b[e]};if(_.parse(b[e],g.event,g.handler),delete g.event.tags,delete g.handler.filters,delete g.handler.end,a!==_&&Eventi.fire(_,"off:filter",g),g.event.type)_.clean(g.event.type,g,d,a);else for(var h in d.s)_.clean(h,g,d,a)}_.empty(d.s)&&delete a[_key]}},_.unhandle=function(a){_.off(a.target,[a.text],a.fn)},_.empty=function(a){for(var b in a)return!b;return!0},_.clean=function(a,b,c,d){var e=c.s[a];if(e){for(var f=0,g=e.length;g>f;f++)if(_.cleans(e[f],b)){var h=e.splice(f--,1)[0];d!==_&&Eventi.fire(_,"off:cleaned",h),g--}e.length||(d.removeEventListener&&d.removeEventListener(a,c),delete c.s[a])}},_.cleans=function(a,b){return _.matches(a.event,b.event)&&_.matches(a,b.handler)&&(!a.important||b.handler.important&&_.matches(b.event,a.event))&&(!b.fn||b.fn===a.fn)},Eventi.off=_.wrap("off",3),_.parsers.unshift([/\$(\!?\w+(\.\w+)*)/,function(a,b,c){b.endtest=c,b.end=_.endTest(c)}]),_.endTest=function(a){var b=parseInt(a,10);if(b)return function(){return!--b};var c="!"===a.charAt(0);return c&&(a=a.substring(1)),a&&_.resolveRE.test(a)?function(){var b=_.resolve(a,this,!0);return void 0===b&&(b=_.resolve(a,!0)),"function"==typeof b&&(b=b.apply(this,arguments)),c?!b:b}:void 0},_.fireAll=function(a,b,c,d){for(var e,f,g=0;g<b.length;g++){f=c.sequence=_.split.ter(b[g],"+",",");for(var h=d||0;h<f.length&&(!e||!e.isSequencePaused());h++)f[h]?(c.index=h,e=c.previousEvent=_.create(f[h],c),_.sequence(e,c,a),_.dispatch(a,e)):f.splice(h--,1)}return e},_.sequence=function(a,b,c,d){a.resumeSequence=function(a){d&&(d=!1,_.fireAll(c,[b.sequence.join(",")],b,a||b.index+1))},a.pauseSequence=function(a){return d!==!1?(d=!0,a&&a.then(this.resumeSequence)):void 0},a.isSequencePaused=function(){return!!d}},_.combo={event:function(a){return _.combo[a]||(_.combo[a]={category:"combo",type:"_"+ ++_.combo.count})},split:function(a){var b=_.split.ter(a,"+");return b.length>1?b.ordered=!1:(b=_.split.ter(a,","),b.length>1&&(b.ordered=!0)),b},count:0,reset:function(){this.clear&&clearTimeout(this.clear),this.unfired=this.texts.slice(),this.events=[]},eventFn:function(a,b){if(this.timeout&&!this.clear&&(this.clear=setTimeout(this.reset,this.timeout)),!(this.ordered&&a-1!==this.unfired.lastIndexOf("")||(this.unfired[a]="",this.events.push(b),this.unfired.join("")))){var c=new Eventi("combo:"+this.event.type);c.events=this.events,c.text=this.text,_.dispatch(this.target,c),this.reset()}}},Eventi.on(_,"on:handler",function(a,b){var c=b.text,d=_.combo.split(c);d.length>1&&(b.event=_.combo.event(c),b.data&&"number"==typeof b.data[0]&&(b.timeout=b.data.shift()),delete b.singleton,delete b.selector,delete b.location,delete b.filters,delete b.endtest,delete b.end,b.texts=d,b.ordered=d.ordered,b.reset=_.combo.reset.bind(b),b.handlers=d.map(function(a,c){return _.handler(b.target,a,_.combo.eventFn.bind(b,c))}),b.reset())}).on(_,"off:filter",function(a,b){_.combo.split(b.text).length>1&&(b.event=_.combo.event(b.text))}).on(_,"off:cleaned",function(a,b){b.handlers&&b.handlers.forEach(_.unhandle)}),_.alias=function(a,b,c){return function(a){var d=_.slice(arguments),e="object"!=typeof a||!a.dispatchEvent&&!a[_key]?0:1;return d.splice(e,0,b),this.apply(c,d)}},(Eventi.alias=function(a){var b,c=_.slice(arguments,1);"string"==typeof a&&(c.unshift(a),a=Eventi);for(var d in Eventi){var e=a[d];if("function"==typeof e&&!e.utility){a!==Eventi&&e===Eventi[d]&&(e=a[d]=e.bind(a));for(var f=0,g=c.length;g>f;f++)b={},_.parse(c[f],b,b),b.alias=b.alias||b.type,e[b.alias]=_.alias(b.alias,c[f],a)}}return b}).utility=!0,_.version="1.0.0";var sP=global.Event&&Event.prototype.stopPropagation||_.noop,sIP=global.Event&&Event.prototype.stopImmediatePropagation||_.noop;CustomEvent.prototype.stopPropagation=function(){this.propagationStopped=!0,sP.call(this)},CustomEvent.prototype.stopImmediatePropagation=function(){this.immediatePropagationStopped=!0,sIP.call(this)};var define=global.define||_.noop;define((global.exports||global).Eventi=Eventi)}(this,this.document); |
@@ -1,2 +0,2 @@ | ||
/*! Eventi - v0.7.1 - 2014-03-13 | ||
/*! Eventi - v1.0.0 - 2014-04-03 | ||
* https://github.com/nbubna/Eventi | ||
@@ -22,2 +22,3 @@ * Copyright (c) 2014 ESHA Research; Licensed MIT */ | ||
}; | ||
if (!global.Event){ global.Event = global.CustomEvent; } | ||
} | ||
@@ -31,8 +32,8 @@ | ||
copy: function(a, b, p) { | ||
if (a){ for (p in a){ if (a.hasOwnProperty(p)){ b[p] = a[p]; }}} | ||
if (typeof a === "object"){ for (p in a){ if (a.hasOwnProperty(p)){ b[p] = a[p]; }}} | ||
}, | ||
async: global.setImmediate || function async(fn){ return setTimeout(fn, 0); }, | ||
resolveRE: /^([\w\$]+)?((\.[\w\$]+)|\[(\d+|'(\\'|[^'])+'|"(\\"|[^"])+")\])*$/, | ||
resolve: function(reference, context) { | ||
if (_.resolveRE.test(reference)) { | ||
resolve: function(reference, context, tested) { | ||
if (tested || _.resolveRE.test(reference)) { | ||
context = context || global; | ||
@@ -47,6 +48,6 @@ try { | ||
var props = { text: type+'' }; | ||
type = _.parse(props.text, props); | ||
type = _.parse(props.text, props, props); | ||
_.copy(copyThese, props); | ||
if (!('bubbles' in props)) { | ||
props.bubbles = true;// must bubble by default | ||
props.bubbles = true;// we bubble by default around here | ||
} | ||
@@ -64,53 +65,48 @@ | ||
prop: function(prop){ return prop; },// only an extension hook | ||
parse: function(type, props) { | ||
_.properties.forEach(function(property) { | ||
parse: function(type, event, handler) { | ||
_.parsers.forEach(function(property) { | ||
type = type.replace(property[0], function() { | ||
return property[1].apply(props, arguments) || ''; | ||
var args = _.slice(arguments, 1); | ||
args.unshift(event, handler); | ||
return property[1].apply(event, args) || ''; | ||
}); | ||
}); | ||
return type ? props.type = type : type; | ||
return type ? event.type = type : type; | ||
}, | ||
properties: [ | ||
[/^_/, function nobubble() { | ||
this.bubbles = false; | ||
parsers: [ | ||
[/^(\W*)_/, function(event, handler, other) { | ||
event.bubbles = false; | ||
return other; | ||
}], | ||
[/^\!/, function protect() {// | ||
this._protect = true; | ||
}], | ||
[/\((.*)\)/, function detail(m, val) { | ||
[/\((.*)\)/, function(event, handler, val) { | ||
try { | ||
this.detail = _.resolve(val) || JSON.parse(val); | ||
event.detail = _.resolve(val) || JSON.parse(val); | ||
} catch (e) { | ||
this.detail = val; | ||
event.detail = val; | ||
} | ||
}], | ||
[/#(\w+)/g, function tags(m, tag) { | ||
(this.tags||(this.tags=[])).push(tag); | ||
this[tag] = true; | ||
[/#(\w+)/g, function(event, handler, tag) { | ||
(event.tags||(event.tags=[])).push(tag); | ||
event[tag] = true; | ||
}], | ||
[/^(\w+):/, function category(m, cat) {// | ||
this.category = cat; | ||
[/^(\w+):/, function(event, handler, cat) {// | ||
event.category = cat; | ||
}] | ||
], | ||
splitRE: / (?![^\(\)]*\))+/g, | ||
wrap: function(name, expect, index) { | ||
index = index || 1; | ||
var wrapper = function wrapper(target) { | ||
wrap: function(name, dataIndex) { | ||
return function wrapper(target) { | ||
var args = _.slice(arguments); | ||
// ensure target param precedes event text | ||
if (!target || typeof target === "string") { | ||
target = !this || this === Eventi ? _.global : this; | ||
args.unshift(target); | ||
if (!target || typeof target === "string" || target instanceof global.Event) {// ensure target | ||
args.unshift(target = !this || this === Eventi ? _.global : this); | ||
} | ||
// ensure array of event text inputs | ||
args[index] = args[index] ? (args[index]+'').split(_.splitRE) : ['']; | ||
// gather ...data the old way | ||
if (args.length > expect) { | ||
args[expect] = args.slice(expect); | ||
args = args.slice(0, expect+1); | ||
if (args.length > dataIndex) {// gather ...data the old way | ||
args[dataIndex] = args.slice(dataIndex); | ||
args = args.slice(0, dataIndex+1); | ||
} | ||
// call fn for each target | ||
if (!args[1] || typeof args[1] === "string") { | ||
args[1] = _.split.ter(args[1]); | ||
} | ||
var fn = _[name], ret; | ||
if ('length' in target && target !== _.global) { | ||
if ('length' in target && target !== _.global) {// apply to each target | ||
for (var i=0,m=target.length; i<m; i++) { | ||
@@ -122,8 +118,45 @@ ret = fn.apply(args[0] = target[i], args); | ||
} | ||
// be fluent | ||
return ret === undefined ? this : ret; | ||
return ret === undefined ? this : ret;// be fluent | ||
}; | ||
wrapper.index = index; | ||
return wrapper; | ||
} | ||
}, | ||
split: { | ||
guard: { '(':')' }, | ||
ter: function(texts, delims) { | ||
var parts = [], | ||
text = '', | ||
guard; | ||
if (texts) { | ||
delims = _.slice(arguments, 1); | ||
delims.unshift(' '); | ||
for (var i=0,m=texts.length; i<m; i++) { | ||
var c = texts.charAt(i); | ||
if (!guard && delims.indexOf(c) >= 0) { | ||
if (text) { | ||
parts.push(text); | ||
} | ||
text = ''; | ||
} else { | ||
text += c; | ||
if (guard) { | ||
if (guard === c) { | ||
if (text.charAt(text.length-2) === '\\') { | ||
text = text.replace("\\"+c, c); | ||
} else { | ||
guard = null; | ||
} | ||
} | ||
} else { | ||
guard = _.split.guard[c]; | ||
} | ||
} | ||
} | ||
if (text) { | ||
parts.push(text); | ||
} | ||
} else { | ||
parts.push(''); | ||
} | ||
return parts; | ||
} | ||
} | ||
}; | ||
@@ -141,13 +174,13 @@ Eventi._ = _; | ||
_.fire = function(target, events, props, data) { | ||
if (typeof props === "object" && !(props instanceof Event) && | ||
('bubbles' in props || 'detail' in props || 'cancelable' in props)) { | ||
props.data = data; | ||
} else { | ||
if (props !== undefined) { | ||
data = data ? data.unshift(props) && data : [props]; | ||
} | ||
props = { data: data }; | ||
_.parsers.unshift([/^(\W*)\//, function(event, handler, other) { | ||
handler.global = true; | ||
return other; | ||
}]); | ||
_.fire = function(target, events, data) { | ||
if (events instanceof Event) { | ||
events.data = data; | ||
_.dispatch(target, events); | ||
return events; | ||
} | ||
return _.fireAll(target, events, props); | ||
return _.fireAll(target, events, {data:data}); | ||
}; | ||
@@ -163,2 +196,3 @@ _.fireAll = function(target, events, props) { | ||
_.dispatch = function(target, event, objectBubbling) { | ||
if (event.global){ target = _.global; } | ||
(target.dispatchEvent || target[_key] || _.noop).call(target, event); | ||
@@ -169,30 +203,36 @@ if (target.parentObject && event.bubbles && !event.propagationStopped) { | ||
// icky test/call, but lighter than wrapping or firing internal event | ||
if (!objectBubbling && event._singleton) { | ||
if (!objectBubbling && event.singleton) { | ||
_.singleton(target, event); | ||
} | ||
}; | ||
Eventi.fire = _.wrap('fire', 3); | ||
_.on = function(target, events, selector, fn, data) { | ||
// adjust for absence of selector | ||
if (typeof selector === "function") { | ||
Eventi.fire = _.wrap('fire', 2); | ||
_.parsers.unshift([/^(\W*)\!/, function(e, handler, other) {// | ||
handler.important = true; | ||
return other; | ||
}]); | ||
_.on = function(target, events, fn, data) { | ||
if (!Array.isArray(events)) { | ||
if (fn !== undefined) { | ||
data = data ? data.unshift(fn) && data : [fn]; | ||
} | ||
fn = selector; selector = null; | ||
for (var event in events) { | ||
_.handler(target, event, events[event], data); | ||
} | ||
} else { | ||
for (var i=0,m=events.length; i<m; i++) { | ||
_.handler(target, events[i], fn, data); | ||
} | ||
} | ||
for (var i=0,m=events.length; i<m; i++) { | ||
_.handler(target, events[i], selector, fn, data); | ||
} | ||
}; | ||
_.handler = function(target, text, selector, fn, data) { | ||
//TODO: consider moving selector into match, so we can specifically off delegates | ||
var handler = { target:target, selector:selector, fn:fn, data:data, text:text, match:{} }; | ||
_.parse(text, handler.match); | ||
delete handler.match.tags;// superfluous for matching | ||
_.handler = function(target, text, fn, data) { | ||
var handler = { target:target, fn:fn, data:data, text:text, event:{} }; | ||
_.parse(text, handler.event, handler); | ||
delete handler.event.tags;// superfluous for handlers | ||
if (target !== _) {// ignore internal events | ||
Eventi.fire(_, 'handler#new', handler); | ||
Eventi.fire(_, 'on:handler', handler); | ||
} | ||
// allow handler#new listeners to change these things | ||
// allow on:handler listeners to change these things | ||
if (handler.fn !== _.noop) { | ||
_.handlers(handler.target, handler.match.type).push(handler); | ||
target = handler.global === true ? _.global : handler.target; | ||
_.handlers(target, handler.event.type).push(handler); | ||
} | ||
@@ -228,66 +268,52 @@ return handler; | ||
}; | ||
_.handle = function(event, handlers) { | ||
for (var i=0, handler, target; i<handlers.length; i++) { | ||
if (_.matches(event, (handler = handlers[i]).match)) { | ||
if (target = _.target(handler, event.target)) { | ||
_.execute(target, event, handler); | ||
if (event.immediatePropagationStopped){ break; } | ||
} | ||
for (var i=0, handler; i<handlers.length; i++) { | ||
if (_.matches(event, (handler = handlers[i]).event)) { | ||
_.execute(event, handler); | ||
if (event.immediatePropagationStopped){ break; } | ||
} | ||
} | ||
}; | ||
_.execute = function(target, event, handler) { | ||
var args = [event]; | ||
_.execute = function(event, handler) { | ||
var args = [event], | ||
fn = handler.fn, | ||
call = { target: handler.target, args:args }; | ||
if (event.data){ args.push.apply(args, event.data); } | ||
if (handler.data){ args.push.apply(args, handler.data); } | ||
try { | ||
handler.fn.apply(target, args); | ||
} catch (e) { | ||
_.async(function(){ throw e; }); | ||
if (handler.filters) { | ||
for (var i=0,m=handler.filters.length; i<m && call.target; i++) { | ||
handler.filters[i].call(call, event, handler); | ||
} | ||
} | ||
if (call.target) { | ||
try { | ||
fn.apply(call.target, call.args); | ||
} catch (e) { | ||
_.async(function(){ throw e; }); | ||
} | ||
if (handler.end && handler.end.apply(call.target, call.args)) { | ||
_.unhandle(handler); | ||
} | ||
} | ||
}; | ||
_.filter = function(handler, fn) { | ||
handler.filters = handler.filters || []; | ||
handler.filters.push(fn); | ||
}; | ||
_.unhandle = function noop(handler){ handler.fn = _.noop; }; | ||
_.matches = function(event, match, strict) { | ||
_.matches = function(event, match) { | ||
for (var key in match) { | ||
if (match[key] !== event[key] && (strict || key.charAt(0) !== '_')) { | ||
if (match[key] !== event[key]) { | ||
return false; | ||
} | ||
} | ||
if (strict) { | ||
for (key in event) { | ||
if (key.charAt(0) === '_' && event[key] !== match[key]) { | ||
return false; | ||
} | ||
} | ||
} | ||
return true; | ||
}; | ||
_.target = function(handler, target) { | ||
return handler.selector ? _.closest(target, handler.selector) : handler.target; | ||
}; | ||
_.closest = function(el, selector) { | ||
while (el && el.matches) { | ||
if (el.matches(selector)) { | ||
return el; | ||
} | ||
el = el.parentNode; | ||
} | ||
}; | ||
if (global.Element) { | ||
var Ep = Element.prototype, | ||
aS = 'atchesSelector'; | ||
if (!Ep['matches']) { | ||
Object.defineProperty(Ep, 'matches', {value:Ep['webkitM'+aS]||Ep['mozM'+aS]||Ep['msM'+aS]}); | ||
} | ||
} | ||
Eventi.on = _.wrap('on', 3); | ||
Eventi.on = _.wrap('on', 4); | ||
_.version = "1.0.0"; | ||
_.version = "0.7.1"; | ||
var sP = (Event && Event.prototype.stopPropagation) || _.noop, | ||
sIP = (Event && Event.prototype.stopImmediatePropagation) || _.noop; | ||
var sP = (global.Event && Event.prototype.stopPropagation) || _.noop, | ||
sIP = (global.Event && Event.prototype.stopImmediatePropagation) || _.noop; | ||
CustomEvent.prototype.stopPropagation = function() { | ||
@@ -294,0 +320,0 @@ this.propagationStopped = true; |
@@ -1,4 +0,4 @@ | ||
/*! Eventi - v0.7.1 - 2014-03-13 | ||
/*! Eventi - v1.0.0 - 2014-04-03 | ||
* https://github.com/nbubna/Eventi | ||
* Copyright (c) 2014 ESHA Research; Licensed MIT */ | ||
!function(global,document){"use strict";function Eventi(){return _.create.apply(this,arguments)}global.CustomEvent||(global.CustomEvent=document?function(a,b){b=b||{};var c=document.createEvent("CustomEvent");return c.initCustomEvent(a,!!b.bubbles,!!b.cancelable,b.detail),c}:function(a,b){b=b||{},this.type=a,this.bubbles=!!b.bubbles,this.detail=b.detail,this.timestamp=Date.now()});var _={global:new Function("return this")(),noop:function(){},slice:function(a,b){return Array.prototype.slice.call(a,b)},copy:function(a,b,c){if(a)for(c in a)a.hasOwnProperty(c)&&(b[c]=a[c])},async:global.setImmediate||function(a){return setTimeout(a,0)},resolveRE:/^([\w\$]+)?((\.[\w\$]+)|\[(\d+|'(\\'|[^'])+'|"(\\"|[^"])+")\])*$/,resolve:function(reference,context){if(_.resolveRE.test(reference)){context=context||global;try{return eval("context"+("["!==reference.charAt(0)?"."+reference:reference))}catch(e){}}},create:function(a,b){var c={text:a+""};a=_.parse(c.text,c),_.copy(b,c),"bubbles"in c||(c.bubbles=!0);var d=new CustomEvent(a,c);for(var e in c)_.skip.indexOf(e)<0&&(d[_.prop(e)]=c[e]);return d},skip:"bubbles cancelable detail type".split(" "),prop:function(a){return a},parse:function(a,b){return _.properties.forEach(function(c){a=a.replace(c[0],function(){return c[1].apply(b,arguments)||""})}),a?b.type=a:a},properties:[[/^_/,function(){this.bubbles=!1}],[/^\!/,function(){this._protect=!0}],[/\((.*)\)/,function(a,b){try{this.detail=_.resolve(b)||JSON.parse(b)}catch(c){this.detail=b}}],[/#(\w+)/g,function(a,b){(this.tags||(this.tags=[])).push(b),this[b]=!0}],[/^(\w+):/,function(a,b){this.category=b}]],splitRE:/ (?![^\(\)]*\))+/g,wrap:function(a,b,c){c=c||1;var d=function(d){var e=_.slice(arguments);d&&"string"!=typeof d||(d=this&&this!==Eventi?this:_.global,e.unshift(d)),e[c]=e[c]?(e[c]+"").split(_.splitRE):[""],e.length>b&&(e[b]=e.slice(b),e=e.slice(0,b+1));var f,g=_[a];if("length"in d&&d!==_.global)for(var h=0,i=d.length;i>h;h++)f=g.apply(e[0]=d[h],e);else f=g.apply(d,e);return void 0===f?this:f};return d.index=c,d}};Eventi._=_,(Eventi.fy=function(a){for(var b in Eventi){var c=Eventi[b];"function"!=typeof c||c.utility||Object.defineProperty(a,b,{value:c,writable:!0,configurable:!0})}return a}).utility=!0,_.fire=function(a,b,c,d){return"object"!=typeof c||c instanceof Event||!("bubbles"in c||"detail"in c||"cancelable"in c)?(void 0!==c&&(d=d?d.unshift(c)&&d:[c]),c={data:d}):c.data=d,_.fireAll(a,b,c)},_.fireAll=function(a,b,c){for(var d,e=0;e<b.length;e++)d=_.create(b[e],c),_.dispatch(a,d);return d},_.dispatch=function(a,b,c){(a.dispatchEvent||a[_key]||_.noop).call(a,b),a.parentObject&&b.bubbles&&!b.propagationStopped&&_.dispatch(a.parentObject,b,!0),!c&&b._singleton&&_.singleton(a,b)},Eventi.fire=_.wrap("fire",3),_.on=function(a,b,c,d,e){"function"==typeof c&&(void 0!==d&&(e=e?e.unshift(d)&&e:[d]),d=c,c=null);for(var f=0,g=b.length;g>f;f++)_.handler(a,b[f],c,d,e)},_.handler=function(a,b,c,d,e){var f={target:a,selector:c,fn:d,data:e,text:b,match:{}};return _.parse(b,f.match),delete f.match.tags,a!==_&&Eventi.fire(_,"handler#new",f),f.fn!==_.noop&&_.handlers(f.target,f.match.type).push(f),f},_.handlers=function(a,b){var c=_.listener(a),d=c.s[b];return d||(d=c.s[b]=[],a.addEventListener&&a.addEventListener(b,c)),d};var _key=_._key="_eventi"+Date.now();if(_.listener=function(a){var b=a[_key];return b||(b=function(a){var c=b.s[a.type];c&&_.handle(a,c)},b.s={},Object.defineProperty(a,_key,{value:b,writeable:!1,configurable:!0})),b},_.handle=function(a,b){for(var c,d,e=0;e<b.length&&!(_.matches(a,(c=b[e]).match)&&(d=_.target(c,a.target))&&(_.execute(d,a,c),a.immediatePropagationStopped));e++);},_.execute=function(a,b,c){var d=[b];b.data&&d.push.apply(d,b.data),c.data&&d.push.apply(d,c.data);try{c.fn.apply(a,d)}catch(e){_.async(function(){throw e})}},_.unhandle=function(a){a.fn=_.noop},_.matches=function(a,b,c){for(var d in b)if(b[d]!==a[d]&&(c||"_"!==d.charAt(0)))return!1;if(c)for(d in a)if("_"===d.charAt(0)&&a[d]!==b[d])return!1;return!0},_.target=function(a,b){return a.selector?_.closest(b,a.selector):a.target},_.closest=function(a,b){for(;a&&a.matches;){if(a.matches(b))return a;a=a.parentNode}},global.Element){var Ep=Element.prototype,aS="atchesSelector";Ep.matches||Object.defineProperty(Ep,"matches",{value:Ep["webkitM"+aS]||Ep["mozM"+aS]||Ep["msM"+aS]})}Eventi.on=_.wrap("on",4),_.version="0.7.1";var sP=Event&&Event.prototype.stopPropagation||_.noop,sIP=Event&&Event.prototype.stopImmediatePropagation||_.noop;CustomEvent.prototype.stopPropagation=function(){this.propagationStopped=!0,sP.call(this)},CustomEvent.prototype.stopImmediatePropagation=function(){this.immediatePropagationStopped=!0,sIP.call(this)};var define=global.define||_.noop;define((global.exports||global).Eventi=Eventi)}(this,this.document); | ||
!function(global,document){"use strict";function Eventi(){return _.create.apply(this,arguments)}global.CustomEvent||(global.CustomEvent=document?function(a,b){b=b||{};var c=document.createEvent("CustomEvent");return c.initCustomEvent(a,!!b.bubbles,!!b.cancelable,b.detail),c}:function(a,b){b=b||{},this.type=a,this.bubbles=!!b.bubbles,this.detail=b.detail,this.timestamp=Date.now()},global.Event||(global.Event=global.CustomEvent));var _={global:new Function("return this")(),noop:function(){},slice:function(a,b){return Array.prototype.slice.call(a,b)},copy:function(a,b,c){if("object"==typeof a)for(c in a)a.hasOwnProperty(c)&&(b[c]=a[c])},async:global.setImmediate||function(a){return setTimeout(a,0)},resolveRE:/^([\w\$]+)?((\.[\w\$]+)|\[(\d+|'(\\'|[^'])+'|"(\\"|[^"])+")\])*$/,resolve:function(reference,context,tested){if(tested||_.resolveRE.test(reference)){context=context||global;try{return eval("context"+("["!==reference.charAt(0)?"."+reference:reference))}catch(e){}}},create:function(a,b){var c={text:a+""};a=_.parse(c.text,c,c),_.copy(b,c),"bubbles"in c||(c.bubbles=!0);var d=new CustomEvent(a,c);for(var e in c)_.skip.indexOf(e)<0&&(d[_.prop(e)]=c[e]);return d},skip:"bubbles cancelable detail type".split(" "),prop:function(a){return a},parse:function(a,b,c){return _.parsers.forEach(function(d){a=a.replace(d[0],function(){var a=_.slice(arguments,1);return a.unshift(b,c),d[1].apply(b,a)||""})}),a?b.type=a:a},parsers:[[/^(\W*)_/,function(a,b,c){return a.bubbles=!1,c}],[/\((.*)\)/,function(a,b,c){try{a.detail=_.resolve(c)||JSON.parse(c)}catch(d){a.detail=c}}],[/#(\w+)/g,function(a,b,c){(a.tags||(a.tags=[])).push(c),a[c]=!0}],[/^(\w+):/,function(a,b,c){a.category=c}]],wrap:function(a,b){return function(c){var d=_.slice(arguments);(!c||"string"==typeof c||c instanceof global.Event)&&d.unshift(c=this&&this!==Eventi?this:_.global),d.length>b&&(d[b]=d.slice(b),d=d.slice(0,b+1)),d[1]&&"string"!=typeof d[1]||(d[1]=_.split.ter(d[1]));var e,f=_[a];if("length"in c&&c!==_.global)for(var g=0,h=c.length;h>g;g++)e=f.apply(d[0]=c[g],d);else e=f.apply(c,d);return void 0===e?this:e}},split:{guard:{"(":")"},ter:function(a,b){var c,d=[],e="";if(a){b=_.slice(arguments,1),b.unshift(" ");for(var f=0,g=a.length;g>f;f++){var h=a.charAt(f);!c&&b.indexOf(h)>=0?(e&&d.push(e),e=""):(e+=h,c?c===h&&("\\"===e.charAt(e.length-2)?e=e.replace("\\"+h,h):c=null):c=_.split.guard[h])}e&&d.push(e)}else d.push("");return d}}};Eventi._=_,(Eventi.fy=function(a){for(var b in Eventi){var c=Eventi[b];"function"!=typeof c||c.utility||Object.defineProperty(a,b,{value:c,writable:!0,configurable:!0})}return a}).utility=!0,_.parsers.unshift([/^(\W*)\//,function(a,b,c){return b.global=!0,c}]),_.fire=function(a,b,c){return b instanceof Event?(b.data=c,_.dispatch(a,b),b):_.fireAll(a,b,{data:c})},_.fireAll=function(a,b,c){for(var d,e=0;e<b.length;e++)d=_.create(b[e],c),_.dispatch(a,d);return d},_.dispatch=function(a,b,c){b.global&&(a=_.global),(a.dispatchEvent||a[_key]||_.noop).call(a,b),a.parentObject&&b.bubbles&&!b.propagationStopped&&_.dispatch(a.parentObject,b,!0),!c&&b.singleton&&_.singleton(a,b)},Eventi.fire=_.wrap("fire",2),_.parsers.unshift([/^(\W*)\!/,function(a,b,c){return b.important=!0,c}]),_.on=function(a,b,c,d){if(Array.isArray(b))for(var e=0,f=b.length;f>e;e++)_.handler(a,b[e],c,d);else{void 0!==c&&(d=d?d.unshift(c)&&d:[c]);for(var g in b)_.handler(a,g,b[g],d)}},_.handler=function(a,b,c,d){var e={target:a,fn:c,data:d,text:b,event:{}};return _.parse(b,e.event,e),delete e.event.tags,a!==_&&Eventi.fire(_,"on:handler",e),e.fn!==_.noop&&(a=e.global===!0?_.global:e.target,_.handlers(a,e.event.type).push(e)),e},_.handlers=function(a,b){var c=_.listener(a),d=c.s[b];return d||(d=c.s[b]=[],a.addEventListener&&a.addEventListener(b,c)),d};var _key=_._key="_eventi"+Date.now();_.listener=function(a){var b=a[_key];return b||(b=function(a){var c=b.s[a.type];c&&_.handle(a,c)},b.s={},Object.defineProperty(a,_key,{value:b,writeable:!1,configurable:!0})),b},_.handle=function(a,b){for(var c,d=0;d<b.length&&(!_.matches(a,(c=b[d]).event)||(_.execute(a,c),!a.immediatePropagationStopped));d++);},_.execute=function(a,b){var c=[a],d=b.fn,e={target:b.target,args:c};if(a.data&&c.push.apply(c,a.data),b.data&&c.push.apply(c,b.data),b.filters)for(var f=0,g=b.filters.length;g>f&&e.target;f++)b.filters[f].call(e,a,b);if(e.target){try{d.apply(e.target,e.args)}catch(h){_.async(function(){throw h})}b.end&&b.end.apply(e.target,e.args)&&_.unhandle(b)}},_.filter=function(a,b){a.filters=a.filters||[],a.filters.push(b)},_.unhandle=function(a){a.fn=_.noop},_.matches=function(a,b){for(var c in b)if(b[c]!==a[c])return!1;return!0},Eventi.on=_.wrap("on",3),_.version="1.0.0";var sP=global.Event&&Event.prototype.stopPropagation||_.noop,sIP=global.Event&&Event.prototype.stopImmediatePropagation||_.noop;CustomEvent.prototype.stopPropagation=function(){this.propagationStopped=!0,sP.call(this)},CustomEvent.prototype.stopImmediatePropagation=function(){this.immediatePropagationStopped=!0,sIP.call(this)};var define=global.define||_.noop;define((global.exports||global).Eventi=Eventi)}(this,this.document); |
@@ -24,4 +24,4 @@ module.exports = function(grunt) { | ||
src: ['src/core.js','src/fire.js','src/on.js', | ||
'src/declare.js', 'src/singleton.js', 'src/key.js', 'src/location.js', | ||
'src/off.js', 'src/until.js', 'src/combo.js', 'src/types.js'] | ||
'src/delegate.js', 'src/declare.js', 'src/singleton.js', 'src/key.js', 'src/location.js', | ||
'src/off.js', 'src/end.js', 'src/sequence.js', 'src/combo.js', 'src/alias.js'] | ||
}, | ||
@@ -35,3 +35,3 @@ tall: { | ||
src: ['src/core.js','src/fire.js','src/on.js', | ||
'src/declare.js', 'src/singleton.js','src/key.js', 'src/location.js'] | ||
'src/delegate.js', 'src/declare.js', 'src/singleton.js','src/key.js', 'src/location.js'] | ||
}, | ||
@@ -38,0 +38,0 @@ }, |
{ | ||
"name": "eventi", | ||
"title": "Eventi", | ||
"version": "0.7.1", | ||
"version": "1.0.0", | ||
"homepage": "https://github.com/nbubna/Eventi", | ||
@@ -6,0 +6,0 @@ "author": { |
@@ -12,9 +12,9 @@ # Eventi | ||
## TODO | ||
* finish key tests | ||
* finish until tests | ||
* finish combo tests | ||
* documentation | ||
* demo app/site | ||
* integrations (jQuery, Visual Event 2, Capo, etc) | ||
* consider limited grouping syntax for types with partial overlap: `group:{type#tag other$1}#tag2` but probably don't bother due to incompatibility w/aliasing and current parsing | ||
* consider wildcard * syntax, to require a match field presence instead of equality, or possibly partial equality. but resist doing it, as this could get out of hand... | ||
## Motive | ||
@@ -24,9 +24,11 @@ | ||
* Application events (aka custom events) are usually under-used or poorly-used in webapps. | ||
* Environment events get simple types and rich data, not the mushed-up 'nounVerbAdjective' types most heavy custom event users tolerate. | ||
* Custom events could use rich data, especially if there's simple ways to create and utilize it. | ||
* Event handling features in general need a boost to encourage use in advanced apps (particularly single page ones). | ||
* Events are the best way to decouple modules and components without isolating them entirely. | ||
* DOM event bubbling, in particular, has much potential for meaningful event based interfaces. | ||
* Environment events get simple types and rich data, not the mushed-up 'nounVerbAdjective' types with poor data that most heavy custom event users end up using. | ||
* Custom events can be awesome, especially when you have rich features and patterns that are simple to use. | ||
* Declarative events are completely unsupported out there. This is a travesty. | ||
## Goal | ||
* A featureful event platform that's easy to use and to extend. | ||
* A declarative syntax for creating and handling rich, informative events. | ||
* A rich event platform that's easy to use and to extend. | ||
* A declarative syntax for working with rich, informative events. | ||
* DOM and object support | ||
@@ -37,7 +39,7 @@ * Handling for complex event types (combos, async sequences, singletons, etc). | ||
* Lots of solid, maintainable test code | ||
* Impressive visual and/or interactive demo (ideas, anyone?) | ||
* Impressive, interactive demo (ideas, anyone?) | ||
* Three versions (tall, grande, venti): tall is frame/core/fire/on, grande adds declare/singleton/key/location, venti adds off/until/combo/types | ||
* Venti is the default version to encourage much event-based awesomeness for everyone. | ||
* Grande includes basic webapp tools. | ||
* Tall could be enough for lite server work. | ||
* Tall could be enough for light server-side work. | ||
@@ -62,7 +64,5 @@ ## Code Plans | ||
* space delimited multiple registration: `Eventi.on([target, ]'first second third', fn)` | ||
* filter by selector (aka delegation): `Eventi.on([target, ]'selector', 'type', fn)` | ||
* filter by category and/or tag: `Eventi.on([target, ]"category:type#tag", fn)` | ||
* bind data w/listener: `Eventi.on([target, ]'type', fn, data)` | ||
* applying rich event data as listener arg(s): `Eventi.on([target, ]'type', function(e, arg, arg){})` | ||
* alias Element.prototype.matches from the prefixed matchesSelector versions | ||
* implementation: one listener per target that gets registered for every handled type. the listener handles each event by looking amongst its handlers for those that match the event and executing them | ||
@@ -79,2 +79,6 @@ | ||
#### delegate.js (requires on.js) | ||
* alias Element.prototype.matches from the prefixed matchesSelector versions | ||
* filter by selector (aka delegation): `Eventi.on([target, ]'type<.selector>', fn)` | ||
#### declare.js (requires on.js and fire.js) | ||
@@ -98,5 +102,5 @@ * declare `data-eventi="submit /beforeunload=quit"` on a root or container element | ||
#### location.js (requires on.js and fire.js) | ||
* event-based routing: `Eventi.on('location', '?view={view}'||regex, function(e, url, params){ console.log(params.view); })` | ||
* event-based history.pushState: `Eventi.fire('location', '?view={0}', ['foo'])` | ||
* consistent event for all popstate/hashchange/pushstate changes: `Eventi.on('location', function(e){ console.log(e.uri, e.oldURI, e.srcEvent); })` | ||
* event-based routing: `Eventi.on('location@?view={view}', function(e, url, params){ console.log(params.view); })` | ||
* event-based history.pushState: `Eventi.fire('location@?view={0}', ['foo'])` | ||
* consistent event for all popstate/hashchange/pushstate changes: `Eventi.on('location', function(e){ console.log(e.location, e.oldLocation, e.srcEvent); })` | ||
@@ -109,21 +113,22 @@ | ||
#### until.js (requires on.js) | ||
#### end.js (requires on.js) | ||
* this will remove handlers once the specified condition is satisfied | ||
* only tests condition upon matching event | ||
* countdown to zero: `Eventi.until([target, ]number, 'type', fn)` | ||
* test ref for truthiness: `Eventi.until([target, ]'reference', 'type', fn)` | ||
* call function for truthiness: `Eventi.until([target, ]testFn, 'type', fn)` | ||
* number of executions: `Eventi.on([target, ]'type$3', fn)` | ||
* test ref for truthiness: `Eventi.on([target, ]'type$reference', fn)` | ||
* call function for truthiness: `Eventi.on([target, ]'type$test.fn', fn)` | ||
#### combo.js (requires fire.js and on.js) | ||
* combo events (call after all specified events, then reset): `Eventi.on([target, ]'foo+bar', fn)` | ||
* event sequences (ordered combos): `Eventi.on([target, ]'one>two>three', fn...)` | ||
* fire combos (always in sequence): `Eventi.fire([target, ]'first>second'[, data...])` | ||
#### sequence.js (requires fire.js) | ||
* fire controllable sequence of events: `Eventi.fire([target, ]'first,second'[, data...])` | ||
* event sequence firing controls (w/async support via promises): `e.pauseSequence([promise])`,`e.resumeSequence()`, `e.isSequencePaused()` | ||
* configurable time allowed between events (for listening, not firing): `Eventi._.comboTimeout = 1000` | ||
#### types.js (requires core) | ||
#### combo.js (requires on.js and off.js) | ||
* combo events (call after all specified events, then reset): `Eventi.on([target, ]'foo+bar', fn)` | ||
* event sequences (ordered combos): `Eventi.on([target, ]'one,two,three', fn...)` | ||
* configurable timeout for combo events: `Eventi.on([target, ]'one,two', fn, 1000)` | ||
#### alias.js (requires core and declare.js) | ||
* provide both global and local type specification with minimal API | ||
* global: `Eventi.types('type');` -> `Eventi.on.type([target, ]handler)` | ||
* local (after Eventi.fy(o)): `Eventi.types(o, 'type', 'type2')` -> `target.until.type2(1, handler)` | ||
* obviously, types cannot have the same name as Function properties like 'call' or 'length' | ||
* global: `Eventi.alias('type');` -> `Eventi.on.type([target, ]handler)` | ||
* local (after Eventi.fy(o)): `Eventi.alias(o, 'type', 'type2')` -> `target.until.type2(1, handler)` | ||
* obviously, aliases cannot have the same name as Function properties like 'call' or 'length' | ||
@@ -135,3 +140,3 @@ | ||
* listen for events in jQuery's manual bubbling system (ick again) | ||
* wrap $.fn.trigger, $.fn.on, $.fn.off, and maybe $.fn.one to intercept calls with Eventi params/syntax | ||
* wrap $.fn.trigger, $.fn.on, $.fn.off, and maybe $.fn.one to intercept calls with Eventi syntax | ||
@@ -143,8 +148,6 @@ #### visual.js | ||
## Release History | ||
* 2014-02-11 [v0.5.0][] (first public release) | ||
* 2014-03-07 [v0.6.3][] (location events, crucial fixes) | ||
* 2014-03-13 [v0.7.1][] (s/signal/types, crucial fixes) | ||
* 2014-02-11 [v0.5.0][] (alpha) | ||
* 2014-04-02 [v1.0.0][] (beta) | ||
[v0.5.0]: https://github.com/nbubna/Eventi/tree/0.5.0 | ||
[v0.6.3]: https://github.com/nbubna/Eventi/tree/0.6.3 | ||
[v0.7.1]: https://github.com/nbubna/Eventi/tree/0.7.1 | ||
[v1.0.0]: https://github.com/nbubna/Eventi/tree/1.0.0 |
135
src/combo.js
@@ -1,77 +0,74 @@ | ||
_.comboRE = /\+|>/; | ||
// overwrite fire.js' _.fireAll to watch for combo events | ||
_.fireAll = function(target, events, props, _resumeIndex) { | ||
var event, sequence; | ||
for (var i=0; i<events.length; i++) { | ||
sequence = props.sequence = events[i].split(_.comboRE); | ||
for (var j=_resumeIndex||0; j < sequence.length && (!event||!event.isSequencePaused()); j++) { | ||
if (sequence[j]) { | ||
props.index = j; | ||
event = props.previousEvent = _.create(sequence[j], props); | ||
_.sequence(event, props, target); | ||
_.dispatch(target, event); | ||
} else { | ||
sequence.splice(j--, 1); | ||
_.combo = { | ||
event: function(text) { | ||
return _.combo[text] || (_.combo[text] = { | ||
category: 'combo', | ||
type: '_'+(++_.combo.count) | ||
}); | ||
}, | ||
split: function(text) { | ||
var parts = _.split.ter(text, '+'); | ||
if (parts.length > 1) { | ||
parts.ordered = false; | ||
} else { | ||
parts = _.split.ter(text, ','); | ||
if (parts.length > 1) { | ||
parts.ordered = true; | ||
} | ||
} | ||
} | ||
return event; | ||
}; | ||
_.sequence = function(event, props, target, paused) { | ||
event.resumeSequence = function(index) { | ||
if (paused) { | ||
paused = false; | ||
_.fireAll(target, props.sequence, props, index||props.index); | ||
return parts; | ||
}, | ||
count: 0, | ||
reset: function() { | ||
if (this.clear){ clearTimeout(this.clear); } | ||
this.unfired = this.texts.slice(); | ||
this.events = []; | ||
}, | ||
eventFn: function(index, e) { | ||
if (this.timeout && !this.clear) { | ||
this.clear = setTimeout(this.reset, this.timeout); | ||
} | ||
}; | ||
event.pauseSequence = function(promise) { | ||
if (paused !== false) {// multiple pauses is nonsense | ||
paused = true; | ||
return promise && promise.then(this.resumeSequence); | ||
if (!this.ordered || index-1 === this.unfired.lastIndexOf('')) { | ||
this.unfired[index] = ''; | ||
this.events.push(e); | ||
if (!this.unfired.join('')) { | ||
var event = new Eventi('combo:'+this.event.type); | ||
event.events = this.events; | ||
event.text = this.text; | ||
_.dispatch(this.target, event); | ||
this.reset(); | ||
} | ||
} | ||
}; | ||
event.isSequencePaused = function(){ return !!paused; }; | ||
} | ||
}; | ||
Eventi.on(_, 'handler#new', function comboHandler(e, handler) { | ||
Eventi.on(_, 'on:handler', function comboHandler(e, handler) { | ||
var text = handler.text, | ||
joint = text.match(_.comboRE); | ||
if (joint) { | ||
var types = text.split(joint[0]), | ||
fn = handler.comboFn = _.comboFn(joint[0]==='>', types, text); | ||
for (var i=0,m=types.length; i<m; i++) { | ||
// override full type with parsed, core type for comboFn's use | ||
types[i] = _.handler(handler.target, types[i], handler.selector, fn).type; | ||
} | ||
fn.reset(); | ||
texts = _.combo.split(text); | ||
if (texts.length > 1) { | ||
handler.event = _.combo.event(text); | ||
if (handler.data && typeof handler.data[0] === "number") { | ||
handler.timeout = handler.data.shift(); | ||
} | ||
delete handler.singleton; | ||
delete handler.selector; | ||
delete handler.location; | ||
delete handler.filters; | ||
delete handler.endtest; | ||
delete handler.end; | ||
// set up combo event handlers | ||
handler.texts = texts; | ||
handler.ordered = texts.ordered; | ||
handler.reset = _.combo.reset.bind(handler); | ||
handler.handlers = texts.map(function(text, index) { | ||
return _.handler(handler.target, text, _.combo.eventFn.bind(handler, index)); | ||
}); | ||
handler.reset(); | ||
} | ||
}); | ||
_.comboTimeout = 1000; | ||
_.comboFn = function(ordered, types, text) { | ||
var waitingFor, | ||
clear, | ||
reset = function() { | ||
if (clear){ clearTimeout(clear); } | ||
waitingFor = types.slice(); | ||
}, | ||
fn = function(e) { | ||
if (!clear){ clear = setTimeout(reset, _.comboTimeout); } | ||
var i = waitingFor.indexOf(e.type); | ||
if (ordered ? i === 0 : i >= 0) { | ||
waitingFor.splice(i, 1); | ||
if (!waitingFor.length) { | ||
_.fire(e.target, text); | ||
reset(); | ||
} | ||
} | ||
}; | ||
fn.reset = reset; | ||
return fn; | ||
}; | ||
// watch for handler.comboFn and remove sub-handlers | ||
Eventi.on(_, 'handler#off', function cleanedHandler(e, handler) { | ||
if (handler.comboFn) { | ||
_.off(handler.target, '', handler.comboFn); | ||
} | ||
}).on(_, 'off:filter', function comboFilter(e, filter) { | ||
if (_.combo.split(filter.text).length > 1) { | ||
filter.event = _.combo.event(filter.text); | ||
} | ||
}).on(_, 'off:cleaned', function comboOff(e, handler) { | ||
if (handler.handlers) { | ||
handler.handlers.forEach(_.unhandle); | ||
} | ||
}); |
120
src/core.js
@@ -7,8 +7,8 @@ function Eventi(){ return _.create.apply(this, arguments); } | ||
copy: function(a, b, p) { | ||
if (a){ for (p in a){ if (a.hasOwnProperty(p)){ b[p] = a[p]; }}} | ||
if (typeof a === "object"){ for (p in a){ if (a.hasOwnProperty(p)){ b[p] = a[p]; }}} | ||
}, | ||
async: global.setImmediate || function async(fn){ return setTimeout(fn, 0); }, | ||
resolveRE: /^([\w\$]+)?((\.[\w\$]+)|\[(\d+|'(\\'|[^'])+'|"(\\"|[^"])+")\])*$/, | ||
resolve: function(reference, context) { | ||
if (_.resolveRE.test(reference)) { | ||
resolve: function(reference, context, tested) { | ||
if (tested || _.resolveRE.test(reference)) { | ||
context = context || global; | ||
@@ -23,6 +23,6 @@ try { | ||
var props = { text: type+'' }; | ||
type = _.parse(props.text, props); | ||
type = _.parse(props.text, props, props); | ||
_.copy(copyThese, props); | ||
if (!('bubbles' in props)) { | ||
props.bubbles = true;// must bubble by default | ||
props.bubbles = true;// we bubble by default around here | ||
} | ||
@@ -40,53 +40,48 @@ | ||
prop: function(prop){ return prop; },// only an extension hook | ||
parse: function(type, props) { | ||
_.properties.forEach(function(property) { | ||
parse: function(type, event, handler) { | ||
_.parsers.forEach(function(property) { | ||
type = type.replace(property[0], function() { | ||
return property[1].apply(props, arguments) || ''; | ||
var args = _.slice(arguments, 1); | ||
args.unshift(event, handler); | ||
return property[1].apply(event, args) || ''; | ||
}); | ||
}); | ||
return type ? props.type = type : type; | ||
return type ? event.type = type : type; | ||
}, | ||
properties: [ | ||
[/^_/, function nobubble() { | ||
this.bubbles = false; | ||
parsers: [ | ||
[/^(\W*)_/, function(event, handler, other) { | ||
event.bubbles = false; | ||
return other; | ||
}], | ||
[/^\!/, function protect() {// | ||
this._protect = true; | ||
}], | ||
[/\((.*)\)/, function detail(m, val) { | ||
[/\((.*)\)/, function(event, handler, val) { | ||
try { | ||
this.detail = _.resolve(val) || JSON.parse(val); | ||
event.detail = _.resolve(val) || JSON.parse(val); | ||
} catch (e) { | ||
this.detail = val; | ||
event.detail = val; | ||
} | ||
}], | ||
[/#(\w+)/g, function tags(m, tag) { | ||
(this.tags||(this.tags=[])).push(tag); | ||
this[tag] = true; | ||
[/#(\w+)/g, function(event, handler, tag) { | ||
(event.tags||(event.tags=[])).push(tag); | ||
event[tag] = true; | ||
}], | ||
[/^(\w+):/, function category(m, cat) {// | ||
this.category = cat; | ||
[/^(\w+):/, function(event, handler, cat) {// | ||
event.category = cat; | ||
}] | ||
], | ||
splitRE: / (?![^\(\)]*\))+/g, | ||
wrap: function(name, expect, index) { | ||
index = index || 1; | ||
var wrapper = function wrapper(target) { | ||
wrap: function(name, dataIndex) { | ||
return function wrapper(target) { | ||
var args = _.slice(arguments); | ||
// ensure target param precedes event text | ||
if (!target || typeof target === "string") { | ||
target = !this || this === Eventi ? _.global : this; | ||
args.unshift(target); | ||
if (!target || typeof target === "string" || target instanceof global.Event) {// ensure target | ||
args.unshift(target = !this || this === Eventi ? _.global : this); | ||
} | ||
// ensure array of event text inputs | ||
args[index] = args[index] ? (args[index]+'').split(_.splitRE) : ['']; | ||
// gather ...data the old way | ||
if (args.length > expect) { | ||
args[expect] = args.slice(expect); | ||
args = args.slice(0, expect+1); | ||
if (args.length > dataIndex) {// gather ...data the old way | ||
args[dataIndex] = args.slice(dataIndex); | ||
args = args.slice(0, dataIndex+1); | ||
} | ||
// call fn for each target | ||
if (!args[1] || typeof args[1] === "string") { | ||
args[1] = _.split.ter(args[1]); | ||
} | ||
var fn = _[name], ret; | ||
if ('length' in target && target !== _.global) { | ||
if ('length' in target && target !== _.global) {// apply to each target | ||
for (var i=0,m=target.length; i<m; i++) { | ||
@@ -98,8 +93,45 @@ ret = fn.apply(args[0] = target[i], args); | ||
} | ||
// be fluent | ||
return ret === undefined ? this : ret; | ||
return ret === undefined ? this : ret;// be fluent | ||
}; | ||
wrapper.index = index; | ||
return wrapper; | ||
} | ||
}, | ||
split: { | ||
guard: { '(':')' }, | ||
ter: function(texts, delims) { | ||
var parts = [], | ||
text = '', | ||
guard; | ||
if (texts) { | ||
delims = _.slice(arguments, 1); | ||
delims.unshift(' '); | ||
for (var i=0,m=texts.length; i<m; i++) { | ||
var c = texts.charAt(i); | ||
if (!guard && delims.indexOf(c) >= 0) { | ||
if (text) { | ||
parts.push(text); | ||
} | ||
text = ''; | ||
} else { | ||
text += c; | ||
if (guard) { | ||
if (guard === c) { | ||
if (text.charAt(text.length-2) === '\\') { | ||
text = text.replace("\\"+c, c); | ||
} else { | ||
guard = null; | ||
} | ||
} | ||
} else { | ||
guard = _.split.guard[c]; | ||
} | ||
} | ||
} | ||
if (text) { | ||
parts.push(text); | ||
} | ||
} else { | ||
parts.push(''); | ||
} | ||
return parts; | ||
} | ||
} | ||
}; | ||
@@ -106,0 +138,0 @@ Eventi._ = _; |
@@ -0,1 +1,8 @@ | ||
_.parsers.unshift([/=>(\w+)$/, function(event, handler, alias) { | ||
handler.alias = alias; | ||
if (handler !== event) { | ||
handler.data = handler.data || []; | ||
handler.data.push(alias); | ||
} | ||
}]); | ||
if (document) { | ||
@@ -5,6 +12,10 @@ _.init = function init() { | ||
for (var i=0,m=nodes.length; i<m; i++) { | ||
var node = nodes[i], | ||
mapping = node.getAttribute('data-eventi'); | ||
if (mapping) { | ||
_.declare(mapping, node); | ||
var target = nodes[i], | ||
mapping = target.getAttribute('data-eventi'); | ||
if (mapping !== target.eventi) { | ||
if (_.off && target.eventi) { | ||
Eventi.off(target, target.eventi, _.declared); | ||
} | ||
target.eventi = mapping; | ||
_.declare(target, mapping); | ||
} | ||
@@ -16,41 +27,35 @@ } | ||
}; | ||
_.declare = function(mapping, mapper) {// register listener | ||
var types = mapping.split(_.splitRE); | ||
for (var i=0,m=types.length; i<m; i++) { | ||
var type = types[i], | ||
eq = type.lastIndexOf('='), | ||
alias = eq > 0 ? type.substring(eq+1) : undefined, | ||
global = type.charAt(0) === '/', | ||
context = global ? _.global : mapper; | ||
mapper = mapper || document; | ||
if (alias){ type = type.substring(0, eq); } | ||
if (global){ type = type.substring(1); } | ||
Eventi.on(context, type, _.mapped, mapper, alias); | ||
_.declare = function(target, mapping) {// register listener | ||
var texts = _.split.ter(mapping); | ||
for (var i=0,m=texts.length; i<m; i++) { | ||
Eventi.on(target, texts[i], _.declared); | ||
} | ||
}; | ||
_.mapped = function(e, mapper, alias) {// lookup handlers | ||
var type = alias || e.type, | ||
nodes = _.declarers(mapper, type, this !== _.global && e.target); | ||
_.declared = function(e, alias) {// lookup handlers | ||
alias = typeof alias === "string" ? alias : e.type; | ||
var nodes = _.declarers(this, alias, e.target); | ||
for (var i=0,m=nodes.length; i<m; i++) { | ||
_.declared(nodes[i], type, e); | ||
_.respond(nodes[i], alias, e); | ||
} | ||
}; | ||
_.declarers = function(mapper, type, target) { | ||
var query = '['+type+']'; | ||
if (target) { | ||
// gather matching parents up to the mapper | ||
var nodes = []; | ||
while (target && target.matches && target !== mapper.parentNode) { | ||
if (target.matches(query)) { | ||
nodes.push(target); | ||
} | ||
target = target.parentNode; | ||
_.declarers = function(target, alias, node) { | ||
var query = '['+alias+']', | ||
// gather matching parents up to the target | ||
nodes = [], | ||
descendant = false; | ||
while (node && node.matches) { | ||
if (node.matches(query)) { | ||
nodes.push(node); | ||
} | ||
return nodes; | ||
if (node === target) { | ||
descendant = true; | ||
break; | ||
} | ||
node = node.parentNode; | ||
} | ||
// gather all declarations within the mapper | ||
return mapper.querySelectorAll(query); | ||
// if node isn't a descendant of target, handler must be global | ||
return descendant ? nodes : target.querySelectorAll(query); | ||
}; | ||
_.declared = function(node, type, e) {// execute handler | ||
var response = node.getAttribute(type); | ||
_.respond = function(node, alias, e) {// execute handler | ||
var response = node.getAttribute(alias); | ||
if (response) { | ||
@@ -66,6 +71,7 @@ var fn = _.resolve(response, node) || _.resolve(response); | ||
_.check = function(e) { | ||
var click = (e.type === 'click' && _.click(e.target)) || | ||
(e.keyCode === 13 && _.click(e.target, true)); | ||
var click = e.target.getAttribute && | ||
((e.type === 'click' && _.click(e.target)) || | ||
(e.keyCode === 13 && _.click(e.target, true))); | ||
if (click) { | ||
_.mapped(e, document.documentElement, 'click'); | ||
_.declared.call(document.documentElement, e, 'click'); | ||
if (click === 'noDefault' && !_.allowDefault(e.target)) { | ||
@@ -72,0 +78,0 @@ e.preventDefault(); |
@@ -1,12 +0,12 @@ | ||
_.fire = function(target, events, props, data) { | ||
if (typeof props === "object" && !(props instanceof Event) && | ||
('bubbles' in props || 'detail' in props || 'cancelable' in props)) { | ||
props.data = data; | ||
} else { | ||
if (props !== undefined) { | ||
data = data ? data.unshift(props) && data : [props]; | ||
} | ||
props = { data: data }; | ||
_.parsers.unshift([/^(\W*)\//, function(event, handler, other) { | ||
handler.global = true; | ||
return other; | ||
}]); | ||
_.fire = function(target, events, data) { | ||
if (events instanceof Event) { | ||
events.data = data; | ||
_.dispatch(target, events); | ||
return events; | ||
} | ||
return _.fireAll(target, events, props); | ||
return _.fireAll(target, events, {data:data}); | ||
}; | ||
@@ -22,2 +22,3 @@ _.fireAll = function(target, events, props) { | ||
_.dispatch = function(target, event, objectBubbling) { | ||
if (event.global){ target = _.global; } | ||
(target.dispatchEvent || target[_key] || _.noop).call(target, event); | ||
@@ -28,6 +29,6 @@ if (target.parentObject && event.bubbles && !event.propagationStopped) { | ||
// icky test/call, but lighter than wrapping or firing internal event | ||
if (!objectBubbling && event._singleton) { | ||
if (!objectBubbling && event.singleton) { | ||
_.singleton(target, event); | ||
} | ||
}; | ||
Eventi.fire = _.wrap('fire', 3); | ||
Eventi.fire = _.wrap('fire', 2); |
@@ -1,13 +0,12 @@ | ||
// add key syntax to _.parse's supported event properties | ||
_.keyRE = /\[([a-z-0-9,\.\/\[\`\\\]\']+)\]/; | ||
_.properties.push([_.keyRE, function parseKey(m, name) { | ||
var dash, key; | ||
while ((dash = name.indexOf('-')) > 0) { | ||
key = name.substring(0, dash); | ||
name = name.substring(dash+1); | ||
this[(_.special[key]||key)+'Key'] = true; | ||
_.split.guard['['] = ']'; | ||
_.parsers.push([/\[([^ ]+)\]/, function(event, handler, key) {//' | ||
var dash; | ||
while ((dash = key.indexOf('-')) > 0) { | ||
event[key.substring(0, dash)+'Key'] = true; | ||
key = key.substring(dash+1); | ||
} | ||
this.keyCode = _.codes[name] || parseInt(name, 10) || 0; | ||
if (key) { | ||
event.keyCode = _.codes[key] || parseInt(key, 10) || key; | ||
} | ||
}]); | ||
_.special = { command: 'meta', apple: 'meta' }; | ||
_.codes = { | ||
@@ -17,3 +16,3 @@ backspace:8, tab:9, enter:13, shift:16, ctrl:17, alt:18, capsLock:20, escape:27, start:91, command:224, | ||
multiply:106, plus:107, minus:109, point:110, divide:111, numLock:144,// numpad controls | ||
',':188, '.':190, '/':191, '`':192, '[':219, '\\':220, ']':221, '\'':222, space:32// symbols | ||
';':186, '=':187, ',':188, '-':189, '.':190, '/':191, '`':192, '[':219, '\\':220, ']':221, '\'':222, space:32// symbols | ||
}; | ||
@@ -20,0 +19,0 @@ for (var n=0; n<10; n++){ _.codes['num'+n] = 96+n; }// numpad numbers |
@@ -1,85 +0,94 @@ | ||
var h = global.history, | ||
l = global.location; | ||
_.pushState = h.pushState; | ||
h.pushState = function() { | ||
var ret = _.pushState.apply(this, arguments); | ||
_.dispatch(_.global, new Eventi('pushstate', {uri:arguments[2]})); | ||
return ret; | ||
}; | ||
Eventi.on('!popstate !hashchange !pushstate', _.at = function(e, uri) { | ||
uri = uri || decodeURI(l.pathname + l.search + l.hash); | ||
if (uri !== _.uri) { | ||
_.dispatch(_.global, new Eventi('location', { | ||
oldURI: _.uri, | ||
uri: _.uri = uri, | ||
srcEvent: e | ||
})); | ||
_.split.guard['@'] = '@'; | ||
_.parsers.unshift([/@([^@]+)(@|$)/, function(event, handler, uri) { | ||
handler.location = uri; | ||
if (_.location && event !== handler) { | ||
_.locationHandler(uri, handler); | ||
} | ||
return uri; | ||
}) | ||
.on('!location', function setUri(e, uri, fill) { | ||
if (typeof uri === "string") { | ||
var keys = _.keys(uri); | ||
if (keys) { | ||
uri = keys.reduce(function(s, key) { | ||
return s.replace(new RegExp('\\{'+key+'\\}',"g"), | ||
fill[key] || global.location[key] || ''); | ||
}, uri); | ||
}]); | ||
if (global.history && global.location) { | ||
var current; | ||
_.pushState = history.pushState; | ||
history.pushState = function() { | ||
var ret = _.pushState.apply(this, arguments); | ||
_.dispatch(_.global, new CustomEvent('pushstate')); | ||
return ret; | ||
}; | ||
_.location = function(e, uri) { | ||
uri = uri || decodeURI(location.pathname + location.search + location.hash); | ||
if (uri !== current) { | ||
_.dispatch(_.global, new Eventi('location', { | ||
oldLocation: current, | ||
location: current = uri, | ||
srcEvent: e | ||
})); | ||
} | ||
e.uri = uri; | ||
if (uri !== _.uri) { | ||
h.pushState(null,null, encodeURI(uri)); | ||
return current; | ||
}; | ||
_.setLocation = function(e, uri, fill) { | ||
if (typeof uri !== "string") { | ||
fill = uri; | ||
uri = e.location; | ||
} | ||
} else if (!e.uri) { | ||
e.uri = _.uri; | ||
} | ||
}) | ||
.on(_, 'handler#new', function location(e, handler) { | ||
if (handler.match.type === "location") { | ||
// always listen on window, but save given target to use as context | ||
handler._target = handler.target; | ||
handler.target = _.global; | ||
if (handler.selector) { | ||
// overloading on.js' selector argument with uri template/regex | ||
var re = handler.selector; | ||
delete handler.selector; | ||
if (typeof re === "string") { | ||
re = re.replace(/([.*+?^=!:$(|\[\/\\])/g, "\\$1"); | ||
if (handler.keys = _.keys(re)) { | ||
re = re.replace(/\{\w+\}/g, "([^\/?#]+)"); | ||
} else { | ||
re.replace(/\{/g, '\\{'); | ||
} | ||
re = new RegExp(re); | ||
if (uri) { | ||
var keys = _.keys(uri); | ||
if (keys) { | ||
uri = keys.reduce(function(s, key) { | ||
return s.replace(new RegExp('\\{'+key+'\\}',"g"), | ||
fill[key] || location[key] || ''); | ||
}, uri); | ||
} | ||
handler.regexp = re; | ||
if (uri !== current) { | ||
history.pushState(null, null, encodeURI(uri)); | ||
} | ||
} | ||
}; | ||
_.keys = function(tmpl) { | ||
var keys = tmpl.match(/\{\w+\}/g); | ||
return keys && keys.map(function(key) { | ||
return key.substring(1, key.length-1); | ||
}); | ||
}; | ||
_.locationHandler = function(uri, handler) { | ||
var re = uri; | ||
if (uri.charAt(0) === '`') { | ||
re = re.substring(1, re.length-1); | ||
} else { | ||
handler.regexp = /.+/; | ||
re = re.replace(/([.*+?^=!:$(|\[\/\\])/g, "\\$1");// escape uri/regexp conflicts | ||
if (handler.keys = _.keys(re)) { | ||
re = re.replace(/\{\w+\}/g, "([^\/?#]+)"); | ||
} else { | ||
re.replace(/\{/g, '\\{'); | ||
} | ||
} | ||
handler._fn = handler.fn; | ||
handler.fn = function(e){ _.location(e.uri, handler, arguments); }; | ||
// try for current uri match immediately | ||
_.execute(null, new Eventi('location',{uri:_.uri||_.at()}), handler); | ||
} | ||
}); | ||
_.keys = function(tmpl) { | ||
var keys = tmpl.match(/\{\w+\}/g); | ||
return keys && keys.map(function(key) { | ||
return key.substring(1, key.length-1); | ||
handler.uriRE = new RegExp(re); | ||
_.filter(handler, _.locationFilter); | ||
}; | ||
_.locationFilter = function(event, handler) { | ||
var matches = (event.uri || current).match(handler.uriRE); | ||
if (matches) { | ||
this.args.splice.apply(this.args, [1,0].concat(matches)); | ||
if (handler.keys) { | ||
// put key/match object in place of full match | ||
this.args[1] = handler.keys.reduce(function(o, key) { | ||
o[key] = matches.shift(); | ||
return o; | ||
}, { match: matches.shift() }); | ||
} | ||
} else { | ||
this.target = undefined; | ||
} | ||
}; | ||
Eventi.on('!popstate !hashchange !pushstate', _.location) | ||
.on('!location', _.setLocation) | ||
.on(_, 'on:handler', function location(e, handler) { | ||
if (handler.event.type === 'location') { | ||
// force global | ||
handler.global = true; | ||
// try for current uri match immediately | ||
if (!current) { | ||
_.location(); | ||
} | ||
_.execute(new Eventi('location',{location:current, srcEvent:e}), handler); | ||
} | ||
}); | ||
}; | ||
_.location = function(uri, handler, args) { | ||
var matches = (uri||_.uri).match(handler.regexp); | ||
if (matches) { | ||
args = _.slice(args); | ||
args.splice.apply(args, [1,0].concat(matches)); | ||
if (handler.keys) { | ||
// put key/match object in place of full match | ||
args[1] = handler.keys.reduce(function(o, key) { | ||
o[key] = matches.shift(); | ||
return o; | ||
}, { match: matches.shift() }); | ||
} | ||
handler._fn.apply(handler._target, args); | ||
} | ||
}; | ||
} |
_.off = function(target, events, fn) { | ||
//TODO: support filtering by selector/location | ||
var listener = target[_key]; | ||
if (listener) { | ||
for (var i=0, m=events.length; i<m; i++) { | ||
var filter = { fn:fn, match:{} }, | ||
type = _.parse(events[i], filter.match); | ||
delete filter.match.tags;// superfluous for matching | ||
if (type) { | ||
_.clean(type, filter, listener, target); | ||
var filter = { event:{}, handler:{}, fn:fn, text:events[i] }; | ||
_.parse(events[i], filter.event, filter.handler); | ||
// delete superfluous properties | ||
delete filter.event.tags; | ||
delete filter.handler.filters; | ||
delete filter.handler.end; | ||
if (target !== _) { | ||
Eventi.fire(_, 'off:filter', filter); | ||
} | ||
if (filter.event.type) { | ||
_.clean(filter.event.type, filter, listener, target); | ||
} else { | ||
for (type in listener.s) { | ||
for (var type in listener.s) { | ||
_.clean(type, filter, listener, target); | ||
@@ -23,3 +28,3 @@ } | ||
_.unhandle = function off(handler) { | ||
_.off(handler.target, [handler.text], handler._fn||handler.fn); | ||
_.off(handler.target, [handler.text], handler.fn); | ||
}; | ||
@@ -34,3 +39,3 @@ _.empty = function(o){ for (var k in o){ return !k; } return true; }; | ||
if (target !== _) {// ignore internal events | ||
Eventi.fire(_, 'handler#off', cleaned); | ||
Eventi.fire(_, 'off:cleaned', cleaned); | ||
} | ||
@@ -49,5 +54,8 @@ m--; | ||
_.cleans = function(handler, filter) { | ||
return _.matches(handler.match, filter.match, true) && | ||
(!filter.fn || filter.fn === (handler._fn||handler.fn)); | ||
return _.matches(handler.event, filter.event) && | ||
_.matches(handler, filter.handler) && | ||
(!handler.important || (filter.handler.important && | ||
_.matches(filter.event, handler.event))) && | ||
(!filter.fn || filter.fn === handler.fn); | ||
}; | ||
Eventi.off = _.wrap('off', 3); |
108
src/on.js
@@ -1,24 +0,30 @@ | ||
_.on = function(target, events, selector, fn, data) { | ||
// adjust for absence of selector | ||
if (typeof selector === "function") { | ||
_.parsers.unshift([/^(\W*)\!/, function(e, handler, other) {// | ||
handler.important = true; | ||
return other; | ||
}]); | ||
_.on = function(target, events, fn, data) { | ||
if (!Array.isArray(events)) { | ||
if (fn !== undefined) { | ||
data = data ? data.unshift(fn) && data : [fn]; | ||
} | ||
fn = selector; selector = null; | ||
for (var event in events) { | ||
_.handler(target, event, events[event], data); | ||
} | ||
} else { | ||
for (var i=0,m=events.length; i<m; i++) { | ||
_.handler(target, events[i], fn, data); | ||
} | ||
} | ||
for (var i=0,m=events.length; i<m; i++) { | ||
_.handler(target, events[i], selector, fn, data); | ||
} | ||
}; | ||
_.handler = function(target, text, selector, fn, data) { | ||
//TODO: consider moving selector into match, so we can specifically off delegates | ||
var handler = { target:target, selector:selector, fn:fn, data:data, text:text, match:{} }; | ||
_.parse(text, handler.match); | ||
delete handler.match.tags;// superfluous for matching | ||
_.handler = function(target, text, fn, data) { | ||
var handler = { target:target, fn:fn, data:data, text:text, event:{} }; | ||
_.parse(text, handler.event, handler); | ||
delete handler.event.tags;// superfluous for handlers | ||
if (target !== _) {// ignore internal events | ||
Eventi.fire(_, 'handler#new', handler); | ||
Eventi.fire(_, 'on:handler', handler); | ||
} | ||
// allow handler#new listeners to change these things | ||
// allow on:handler listeners to change these things | ||
if (handler.fn !== _.noop) { | ||
_.handlers(handler.target, handler.match.type).push(handler); | ||
target = handler.global === true ? _.global : handler.target; | ||
_.handlers(target, handler.event.type).push(handler); | ||
} | ||
@@ -54,60 +60,46 @@ return handler; | ||
}; | ||
_.handle = function(event, handlers) { | ||
for (var i=0, handler, target; i<handlers.length; i++) { | ||
if (_.matches(event, (handler = handlers[i]).match)) { | ||
if (target = _.target(handler, event.target)) { | ||
_.execute(target, event, handler); | ||
if (event.immediatePropagationStopped){ break; } | ||
} | ||
for (var i=0, handler; i<handlers.length; i++) { | ||
if (_.matches(event, (handler = handlers[i]).event)) { | ||
_.execute(event, handler); | ||
if (event.immediatePropagationStopped){ break; } | ||
} | ||
} | ||
}; | ||
_.execute = function(target, event, handler) { | ||
var args = [event]; | ||
_.execute = function(event, handler) { | ||
var args = [event], | ||
fn = handler.fn, | ||
call = { target: handler.target, args:args }; | ||
if (event.data){ args.push.apply(args, event.data); } | ||
if (handler.data){ args.push.apply(args, handler.data); } | ||
try { | ||
handler.fn.apply(target, args); | ||
} catch (e) { | ||
_.async(function(){ throw e; }); | ||
if (handler.filters) { | ||
for (var i=0,m=handler.filters.length; i<m && call.target; i++) { | ||
handler.filters[i].call(call, event, handler); | ||
} | ||
} | ||
if (call.target) { | ||
try { | ||
fn.apply(call.target, call.args); | ||
} catch (e) { | ||
_.async(function(){ throw e; }); | ||
} | ||
if (handler.end && handler.end.apply(call.target, call.args)) { | ||
_.unhandle(handler); | ||
} | ||
} | ||
}; | ||
_.filter = function(handler, fn) { | ||
handler.filters = handler.filters || []; | ||
handler.filters.push(fn); | ||
}; | ||
_.unhandle = function noop(handler){ handler.fn = _.noop; }; | ||
_.matches = function(event, match, strict) { | ||
_.matches = function(event, match) { | ||
for (var key in match) { | ||
if (match[key] !== event[key] && (strict || key.charAt(0) !== '_')) { | ||
if (match[key] !== event[key]) { | ||
return false; | ||
} | ||
} | ||
if (strict) { | ||
for (key in event) { | ||
if (key.charAt(0) === '_' && event[key] !== match[key]) { | ||
return false; | ||
} | ||
} | ||
} | ||
return true; | ||
}; | ||
_.target = function(handler, target) { | ||
return handler.selector ? _.closest(target, handler.selector) : handler.target; | ||
}; | ||
_.closest = function(el, selector) { | ||
while (el && el.matches) { | ||
if (el.matches(selector)) { | ||
return el; | ||
} | ||
el = el.parentNode; | ||
} | ||
}; | ||
if (global.Element) { | ||
var Ep = Element.prototype, | ||
aS = 'atchesSelector'; | ||
if (!Ep['matches']) { | ||
Object.defineProperty(Ep, 'matches', {value:Ep['webkitM'+aS]||Ep['mozM'+aS]||Ep['msM'+aS]}); | ||
} | ||
} | ||
Eventi.on = _.wrap('on', 4); | ||
Eventi.on = _.wrap('on', 3); |
// add singleton to _.parse's supported event properties | ||
_.properties.unshift([/^\^/, function singleton(){ this._singleton = true; }]); | ||
_.parsers.unshift([/^(\W*)\^/, function(event, handler, other) { | ||
handler.singleton = true; | ||
if (event !== handler) { | ||
_.filter(handler, _.before); | ||
} | ||
return other; | ||
}]); | ||
@@ -20,14 +26,12 @@ // _.fire's _.dispatch will call this when appropriate | ||
}; | ||
_.before = function singleton(event, handler) { | ||
_.unhandle(handler); | ||
handler.fn = _.noop;// tell _.handler not to keep this | ||
if (!event[_skey]) {// remember this non-singleton as singleton for handler's sake | ||
_.remember(this.target, event); | ||
} | ||
}; | ||
Eventi.on(_, 'handler#new', function singleton(e, handler) { | ||
if (handler.match._singleton) { | ||
var fn = handler._fn = handler.fn; | ||
handler.fn = function singleton(e) { | ||
_.unhandle(handler); | ||
if (!e[_skey]) {// remember this non-singleton as singleton for handler's sake | ||
_.remember(handler.target, e); | ||
} | ||
fn.apply(this, arguments); | ||
}; | ||
Eventi.on(_, 'on:handler', function singleton(e, handler) { | ||
if (handler.singleton) { | ||
// search target's saved singletons, execute handler upon match | ||
@@ -37,9 +41,5 @@ var saved = handler.target[_skey]||[]; | ||
var event = saved[i]; | ||
if (_.matches(event, handler.match)) { | ||
var target = _.target(handler, event.target); | ||
if (target) { | ||
_.execute(target, event, handler); | ||
handler.fn = _.noop;// tell _.handler not to keep this | ||
break; | ||
} | ||
if (_.matches(event, handler.event)) { | ||
_.execute(event, handler); | ||
break; | ||
} | ||
@@ -52,4 +52,4 @@ } | ||
Eventi.on('DOMContentLoaded', function ready(e) { | ||
_.fire(document.documentElement, ['^ready'], undefined, [e]); | ||
Eventi.fire(document.documentElement, '^ready', e); | ||
}); | ||
} |
@@ -26,10 +26,99 @@ (function() { | ||
function onCombo(text, fn, fire) { | ||
Eventi.on(text, function(e) { | ||
equal(e.category, 'combo'); | ||
equal(e.text, text); | ||
if (fn) { | ||
fn.apply(this, arguments); | ||
} | ||
Eventi.off(text); | ||
}); | ||
if (!fire) { | ||
fire = text; | ||
} | ||
Eventi.fire(fire); | ||
Eventi.fire(fire);//twice to test off | ||
} | ||
test('ordered', function() { | ||
expect(6); | ||
onCombo('one,two', function(e) { | ||
ok(Array.isArray(e.events)); | ||
equal(e.events.length, 2); | ||
equal(e.events[0].type, 'one'); | ||
equal(e.events[1].type, 'two'); | ||
}); | ||
}); | ||
test('unordered', function() { | ||
expect(2); | ||
onCombo('this+that', null, 'that this'); | ||
}); | ||
test('unordered with ordered sub', function() { | ||
expect(2); | ||
onCombo('this+that,then', null, 'this that then'); | ||
}); | ||
test('unordered with overlapping ordered subs', function() { | ||
expect(2); | ||
onCombo('first,this+that,then', null, 'first that this then'); | ||
}); | ||
test('sub-events with properties', function() { | ||
expect(3); | ||
onCombo('cat:this+that#tag', function(e) { | ||
equal(e.tags, undefined); | ||
}); | ||
}); | ||
asyncTest('timeout success', function() { | ||
expect(1); | ||
Eventi.on('one,two', function(e) { | ||
ok(e); | ||
}, 500); | ||
Eventi.fire('one'); | ||
setTimeout(function() { | ||
start(); | ||
Eventi.fire('two'); | ||
Eventi.off('one,two'); | ||
}, 100); | ||
}); | ||
asyncTest('timeout fail', function() { | ||
expect(0); | ||
Eventi.on('this+that', function(e) { | ||
ok(!e,'should not have e'); | ||
}, 100); | ||
Eventi.fire('this'); | ||
setTimeout(function() { | ||
start(); | ||
Eventi.fire('that'); | ||
Eventi.off('this+that'); | ||
}, 500); | ||
}); | ||
test('internal api presence', function() { | ||
ok(_.comboRE, "_.comboRE"); | ||
ok(_.sequence, "_.sequence"); | ||
ok(typeof _.comboTimeout === "number", "_.comboTimeout"); | ||
ok(_.comboFn, "_.comboFn"); | ||
notEqual(_.cleaned, _.noop, "_.cleaned should be overridden"); | ||
equal(typeof _.combo, "object", "_.combo"); | ||
equal(typeof _.combo.count, "number", "_.combo.count"); | ||
equal(typeof _.combo.split, "function", "_.combo.split"); | ||
equal(typeof _.combo.reset, "function", "_.combo.reset"); | ||
equal(typeof _.combo.event, "function", "_.combo.event"); | ||
equal(typeof _.combo.eventFn, "function", "_.combo.eventFn"); | ||
}); | ||
test('_.combo.split', function() { | ||
var single = _.combo.split('single'); | ||
deepEqual(single, ['single']); | ||
var ordered = _.combo.split('one,two'); | ||
deepEqual(ordered, ['one','two'], 'should have both events'); | ||
strictEqual(ordered.ordered, true, 'should be ordered'); | ||
var unordered = _.combo.split('this+that'); | ||
deepEqual(unordered, ['this','that'], 'should have both events'); | ||
strictEqual(unordered.ordered, false, 'should be unordered'); | ||
var both = _.combo.split('one,two+other'); | ||
deepEqual(both, ['one,two', 'other'], 'should be split on unordered'); | ||
strictEqual(unordered.ordered, false, 'should be unordered'); | ||
}); | ||
}()); |
@@ -46,3 +46,3 @@ (function() { | ||
test('new Eventi("_!category:type#tag#label(\'detail\')")', function() { | ||
var e = new Eventi("_!category:type#tag#label(\"detail\")"); | ||
var e = new Eventi("_category:type#tag#label(\"detail\")"); | ||
equal(e.bubbles, false, 'should not be set to bubble'); | ||
@@ -55,3 +55,2 @@ equal(e.category, 'category', 'should be in category'); | ||
equal(e.detail, 'detail', 'should have detail'); | ||
equal(e._protect, true, 'should be protected'); | ||
}); | ||
@@ -90,5 +89,7 @@ | ||
ok(_.parse, "_.parse"); | ||
ok(_.properties, "_.properties"); | ||
ok(_.splitRE, "_.splitRE"); | ||
ok(_.parsers, "_.parsers"); | ||
ok(_.wrap, "_.wrap"); | ||
equal(typeof _.split, "object", "_.split"); | ||
equal(typeof _.split.guard, "object", "_.split.guard"); | ||
equal(typeof _.split.ter, "function", "_.split.ter"); | ||
}); | ||
@@ -189,2 +190,8 @@ | ||
test("_.split.ter", function() { | ||
deepEqual(_.split.ter('a b'), ['a','b']); | ||
deepEqual(_.split.ter('a( ) b()'), ['a( )','b()']); | ||
deepEqual(_.split.ter('a(\\)) b'), ['a())','b']); | ||
}); | ||
}()); |
@@ -35,7 +35,7 @@ (function() { | ||
listener = el[_._key]; | ||
equal(attr, 'simple type#rich=alias /global', 'should have right attribute'); | ||
equal(attr, 'simple type#rich=>alias /glocal', 'should have right attribute'); | ||
ok(listener, 'should have a listener'); | ||
ok(listener.s.simple, 'should listen for simple'); | ||
ok(listener.s.type, 'should listen for type'); | ||
ok(!listener.s.global, 'should not listen for global'); | ||
ok(!listener.s.glocal, 'should not listen for glocal'); | ||
}); | ||
@@ -70,3 +70,3 @@ | ||
test('/global="elementHandle"', function() { | ||
test('/glocal="elementHandle"', function() { | ||
expect(2); | ||
@@ -76,6 +76,6 @@ var parent = document.getElementById('declare'), | ||
el.elementHandle = function(e) { | ||
equal(e.type, 'global'); | ||
equal(this, el);// global event gets declared context | ||
equal(e.type, 'glocal'); | ||
equal(this, el);// glocal event gets declared context | ||
}; | ||
Eventi.fire(document.body, 'global'); | ||
Eventi.fire(document.body, 'glocal'); | ||
delete el.elementHandle; | ||
@@ -103,3 +103,3 @@ }); | ||
ok(_.declare, "_.declare"); | ||
ok(_.mapped, "_.mapped"); | ||
ok(_.respond, "_.respond"); | ||
ok(_.declarers, "_.declarers"); | ||
@@ -121,10 +121,10 @@ ok(_.declared, "_.declared"); | ||
test('_.declarers global', function() { | ||
test('_.declarers glocal', function() { | ||
var mapper = document.getElementById('declare'), | ||
nodes = _.declarers(mapper, 'global', false); | ||
nodes = _.declarers(mapper, 'glocal', false); | ||
equal(nodes.length, 1); | ||
equal(nodes[0], document.querySelector('#declare [global]')); | ||
equal(nodes[0], document.querySelector('#declare [glocal]')); | ||
}); | ||
function declared(type, value, fn) { | ||
function respond(type, value, fn) { | ||
var node = document.createElement('span'); | ||
@@ -136,6 +136,6 @@ node.setAttribute(type, value); | ||
document.getElementById('qunit-fixture').appendChild(node); | ||
_.declared(node, type, new CustomEvent(type)); | ||
_.respond(node, type, new CustomEvent(type)); | ||
} | ||
test('_.declared mapped event', function() { | ||
test('_.respond mapped event', function() { | ||
expect(1); | ||
@@ -145,9 +145,9 @@ Eventi.on('type', function(e, oe) { | ||
}); | ||
declared('mapped', 'type'); | ||
respond('mapped', 'type'); | ||
Eventi.off('type'); | ||
}); | ||
test('_.declared local fn', function() { | ||
test('_.respond local fn', function() { | ||
expect(1); | ||
declared('local', 'elementFn', function(e) { | ||
respond('local', 'elementFn', function(e) { | ||
equal(e.type, 'local'); | ||
@@ -157,3 +157,3 @@ }); | ||
test('_.declared global fn', function() { | ||
test('_.respond global fn', function() { | ||
expect(1); | ||
@@ -163,12 +163,12 @@ window.globalFn = function(e) { | ||
}; | ||
declared('global', 'globalFn'); | ||
respond('global', 'globalFn'); | ||
delete window.globalFn; | ||
}); | ||
test('_.declared nested fn', function() { | ||
test('_.respond nested fn', function() { | ||
expect(1); | ||
window.ns = {fn: function(e) { | ||
equal(e.type, 'nested'); | ||
}} | ||
; declared('nested', 'ns.fn'); | ||
}}; | ||
respond('nested', 'ns.fn'); | ||
delete window.ns; | ||
@@ -175,0 +175,0 @@ }); |
@@ -90,9 +90,10 @@ (function() { | ||
test('Eventi.fire(event, props)', function() { | ||
expect(1); | ||
window.addEventListener('props', function(e) { | ||
equal(e.detail, 'detail', 'should have detail of "detail"'); | ||
test('Eventi.fire(new CustomEvent("test")', function() { | ||
expect(2); | ||
var target = {}, | ||
event = new CustomEvent('test'); | ||
Eventi.on(target, 'test', function(e) { | ||
strictEqual(e, event); | ||
}); | ||
Eventi.fire('props', { detail:'detail' }); | ||
Eventi.fire(document.documentElement, 'props', { bubbles:false }); | ||
equal(Eventi.fire(target, event), event); | ||
}); | ||
@@ -102,3 +103,2 @@ | ||
ok(_.fire, "_.fire"); | ||
ok(_.fireAll, "_.fireAll"); | ||
ok(_.dispatch, "_.dispatch"); | ||
@@ -105,0 +105,0 @@ }); |
@@ -23,9 +23,44 @@ (function() { | ||
//var _ = Eventi._; | ||
var _ = Eventi._; | ||
module('Eventi key'); | ||
test('Eventi.on("fake[ctrl-meta-shift-a]",fn)', function() { | ||
Eventi.on('key[ctrl-meta-shift-a]', function(e) { | ||
equal(e.type, 'key'); | ||
equal(e.ctrlKey, true); | ||
equal(e.metaKey, true); | ||
equal(e.shiftKey, true); | ||
equal(e.keyCode, 65); | ||
}); | ||
Eventi.fire('key[meta-shift-ctrl-a]'); | ||
}); | ||
test('Eventi.on("nocode[ctrl-]", fn)', function() { | ||
Eventi.on("nocode[ctrl-]", function(e) { | ||
equal(e.ctrlKey, true); | ||
ok(!e.keyCode); | ||
}); | ||
Eventi.fire('nocode[ctrl-]'); | ||
}); | ||
test('Eventi.on("dash[shift--] dash[-]",fn)', function() { | ||
expect(2); | ||
Eventi.on("dash[shift--] dash[-]", function(e) { | ||
equal(e.keyCode, 189); | ||
}); | ||
Eventi.fire('dash[shift--]'); | ||
}); | ||
test('Eventi.on("guard[\\]] escape", fn)', function() { | ||
Eventi.on("guard[\\]] escape", function(e) { | ||
equal(e.type, 'guard'); | ||
}); | ||
Eventi.fire("guard[]]"); | ||
}); | ||
test('internal api presence', function() { | ||
expect(0); | ||
equal(typeof _.codes, "object", "_.codes"); | ||
equal(_.split.guard['['], ']'); | ||
}); | ||
}()); |
@@ -37,5 +37,5 @@ (function() { | ||
var uri = 'Eventi.html'; | ||
Eventi.on('location', uri, function(e, match) { | ||
Eventi.on('location@'+uri, function(e, match) { | ||
equal(e.type, 'location'); | ||
ok(e.uri, 'event should have uri'); | ||
ok(e.location, 'event should have uri'); | ||
equal(match, uri); | ||
@@ -49,3 +49,3 @@ Eventi.off('location'); | ||
expect(2); | ||
Eventi.on('location', /(\w+)\.html/, function(e, match, file) { | ||
Eventi.on('location@`(\\w+)\\.html`', function(e, match, file) { | ||
equal(match, 'Eventi.html'); | ||
@@ -60,3 +60,3 @@ equal(file, 'Eventi'); | ||
expect(4); | ||
Eventi.on('location', '{file}.html', function(e, vals, file) { | ||
Eventi.on('location@{file}.html', function(e, vals, file) { | ||
equal(typeof vals, "object", "should have match object"); | ||
@@ -73,3 +73,3 @@ equal(vals.file, 'Eventi'); | ||
expect(2); | ||
Eventi.on('location', 'test', function(e, match, hdata) { | ||
Eventi.on('location@test', function(e, match, hdata) { | ||
equal(match, 'test'); | ||
@@ -85,3 +85,3 @@ equal(hdata, 'hdata'); | ||
Eventi.on('location', '#hashed', function(e) { | ||
equal(e.uri, location.pathname+location.search+'#hashed'); | ||
equal(e.location, location.pathname+location.search+'#hashed'); | ||
Eventi.off('location'); | ||
@@ -110,3 +110,3 @@ history.pushState(null,null,home); | ||
Eventi.on('location#all', function(e) { | ||
equal(e.uri, _.uri, 'should have current uri'); | ||
equal(e.location, _.location(), 'should have current uri'); | ||
Eventi.off('location#all'); | ||
@@ -118,7 +118,7 @@ }); | ||
expect(3); | ||
Eventi.on('location', '?search', function(e) { | ||
Eventi.on('location@?search', function(e) { | ||
Eventi.off('location'); | ||
ok(e.srcEvent, 'should have srcEvent'); | ||
equal(e.srcEvent.type, 'pushstate','should be pushstate source'); | ||
equal(e.uri, location.pathname+'?search', 'should have correct e.uri'); | ||
equal(e.location, location.pathname+'?search', 'should have correct e.location'); | ||
history.pushState(null,null,home); | ||
@@ -131,7 +131,7 @@ }); | ||
expect(5); | ||
var uri = _.uri, | ||
var uri = _.location(), | ||
fired = false; | ||
Eventi.on('location', '?view={view}', function(e, match) { | ||
equal(e.oldURI, uri); | ||
equal(e.uri, location.pathname + '?view=foo'); | ||
Eventi.on('location@?view={view}', function(e, match) { | ||
equal(e.oldLocation, uri); | ||
equal(e.location, location.pathname + '?view=foo'); | ||
equal(e.srcEvent && e.srcEvent.type, 'pushstate'); | ||
@@ -149,7 +149,7 @@ equal(match.view, 'foo'); | ||
expect(2); | ||
Eventi.on('location', '?search', function(e) { | ||
ok(e.uri.indexOf('?search') > 0); | ||
Eventi.on('location@?search', function(e) { | ||
ok(e.location.indexOf('?search') > 0); | ||
}) | ||
.on('location', '#hashes', function(e) { | ||
ok(e.uri.indexOf('#hashes') > 0); | ||
.on('location@#hashes', function(e) { | ||
ok(e.location.indexOf('#hashes') > 0); | ||
Eventi.off('location'); | ||
@@ -163,3 +163,3 @@ history.pushState(null,null,home); | ||
var target = {}; | ||
Eventi.on(target, 'location', '#target', function() { | ||
Eventi.on(target, 'location@#target', function() { | ||
equal(this, target, 'should have target context'); | ||
@@ -175,9 +175,12 @@ Eventi.off('location'); | ||
test('internal api presence', function() { | ||
equal(typeof _.at, "function", "_.at"); | ||
equal(typeof _.pushState, "function", "_.pushState"); | ||
equal(typeof _.location, "function", "_.location"); | ||
equal(typeof _.keys, "function", "_.keys"); | ||
equal(typeof _.location, "function", "_.location"); | ||
equal(typeof _.setLocation, "function", "_.setLocation"); | ||
equal(typeof _.locationHandler, "function", "_.locationHandler"); | ||
equal(typeof _.locationFilter, "function", "_.locationFilter"); | ||
}); | ||
test('_.at', function() { | ||
equal(_.at(), decodeURI(location.pathname+location.search+location.hash)); | ||
test('_.location', function() { | ||
equal(_.location(), decodeURI(location.pathname+location.search+location.hash)); | ||
}); | ||
@@ -184,0 +187,0 @@ |
@@ -117,12 +117,13 @@ (function() { | ||
test('Eventi.off("!protected")', function() { | ||
test('Eventi.off("!important#tag")', function() { | ||
expect(2); | ||
Eventi.on("!protected", function(e) { | ||
equal(e.type, 'protected'); | ||
equal(e._protect, undefined); | ||
Eventi.on("!important#tag", function(e) { | ||
equal(e.type, 'important'); | ||
equal(e.important, undefined); | ||
}) | ||
.off("protected")// should fail to turn it off | ||
.fire("protected"); | ||
Eventi.off("!protected") | ||
.fire("protected"); | ||
.off("important") | ||
.off('important#tag') | ||
.fire("important#tag"); | ||
Eventi.off("!important#tag") | ||
.fire("important#tag"); | ||
}); | ||
@@ -151,3 +152,19 @@ | ||
test('handler#off event', function() { | ||
test('off:filter event', function() { | ||
expect(2); | ||
var target = {}, | ||
type = 'filterme', | ||
fn = function(e, f) { | ||
if (f.event.type === type) { | ||
equal(e.type, 'filter'); | ||
equal(e.category, 'off'); | ||
} | ||
}; | ||
Eventi.on(target, type, function(){}) | ||
.on(_, 'off:filter', fn) | ||
.off(target, type) | ||
.off(_, 'off:filter', fn); | ||
}); | ||
test('off:cleaned event', function() { | ||
expect(4); | ||
@@ -157,5 +174,5 @@ var target = {}, | ||
fn = function(e, h) { | ||
if (h.match.type === type) { | ||
ok(e.off); | ||
equal(e.type, 'handler'); | ||
if (h.event.type === type) { | ||
equal(e.type, 'cleaned'); | ||
equal(e.category, 'off'); | ||
ok(h === handler, 'should pass off\'ed handler'); | ||
@@ -167,5 +184,5 @@ } | ||
ok(handler, 'should be able to snag ref to handler'); | ||
Eventi.on(_, 'handler#off', fn) | ||
Eventi.on(_, 'off:cleaned', fn) | ||
.off(target, type) | ||
.off(_, 'handler#off', fn); | ||
.off(_, 'off:cleaned', fn); | ||
}); | ||
@@ -172,0 +189,0 @@ |
@@ -26,6 +26,2 @@ (function() { | ||
test('3rd party/polyfill api presence', function() { | ||
ok(typeof Element.prototype.matches === "function", "Element.prototype.matches"); | ||
}); | ||
test('external api presence', function() { | ||
@@ -65,13 +61,16 @@ ok(typeof Eventi.on === "function", 'Eventi.on'); | ||
test('Eventi.on(type,selector,fn)', function() { | ||
var parent = document.querySelector('#on'), | ||
kid = parent.querySelector('.closest'); | ||
Eventi.on('click', '#on', function(e, edata) { | ||
equal(e.type, 'click'); | ||
equal(edata, 'edata'); | ||
equal(this, parent); | ||
equal(e.target, kid); | ||
}); | ||
Eventi.fire(kid, 'click', 'edata'); | ||
Eventi.off('click'); | ||
test('Eventi.on({type:fn,other:fn2})', function() { | ||
expect(3); | ||
var target = {}, | ||
handlers = { | ||
type: function(e) { | ||
equal(e.type, 'type'); | ||
}, | ||
"other#tagged": function(e) { | ||
equal(e.type, 'other'); | ||
equal(e.tagged, true); | ||
} | ||
}; | ||
Eventi.on(target, handlers); | ||
Eventi.fire(target, Object.keys(handlers)); | ||
}); | ||
@@ -100,14 +99,9 @@ | ||
}, | ||
handler = { data: ['handlerData'], fn: fn }; | ||
handler = { target:target, data: ['handlerData'], fn: fn, filters:[] }; | ||
e.data = ['eventData']; | ||
_.execute(target, e, handler); | ||
_.execute(e, handler); | ||
}); | ||
test('_.closest', function() { | ||
equal(_.closest(document, 'foo'), undefined, 'undefined for non Elements'); | ||
var root = document.querySelector('#on'), | ||
div = root.querySelector('.closest'); | ||
equal(_.closest(div, 'div'), div, 'el should prefer itself to parent'); | ||
equal(_.closest(div, '#on'), root, 'should find parent when element does not match'); | ||
}); | ||
//TODO: test handler.filters | ||
//TODO: test handler.end | ||
@@ -122,3 +116,3 @@ test('_.matches', function() { | ||
test('handler#new event', function() { | ||
test('on:handler event', function() { | ||
expect(4); | ||
@@ -130,10 +124,10 @@ var target = {}, | ||
if (h.text === type) {// don't let problems with _.off bug us | ||
ok(e['new']); | ||
equal(e.type, 'handler'); | ||
equal(e.category, 'on'); | ||
passed = h; | ||
} | ||
}; | ||
Eventi.on(_, 'handler#new', fn) | ||
Eventi.on(_, 'on:handler', fn) | ||
.on(target, type, function(){}) | ||
.off(_, 'handler#new', fn); | ||
.off(_, 'on:handler', fn); | ||
var handler = target[_._key].s[type][0]; | ||
@@ -152,6 +146,4 @@ ok(handler, 'should get new handler directly'); | ||
ok(_.matches, "_.matches"); | ||
ok(_.target, "_.target"); | ||
ok(_.closest, "_.closest"); | ||
}); | ||
}()); |
@@ -30,3 +30,3 @@ (function() { | ||
equal(e.type, 'ready'); | ||
ok(e._singleton); | ||
ok(e.singleton); | ||
equal(oe.type, 'DOMContentLoaded'); | ||
@@ -41,3 +41,3 @@ }); | ||
equal(e.type, 'once'); | ||
ok(!e._singleton); | ||
ok(!e.singleton); | ||
equal(e[_._skey], true); | ||
@@ -85,5 +85,2 @@ }); | ||
test('internal api presence', function() { | ||
var e = {}; | ||
_.properties[0][1].call(e); | ||
ok(e._singleton, '_.properties has singleton parser up front'); | ||
ok(_.singleton, '_.singleton'); | ||
@@ -90,0 +87,0 @@ ok(_._skey, '_._key'); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
312105
66
6947
0
145