Comparing version 0.4.10 to 0.4.11-1
111
bean.js
@@ -24,2 +24,5 @@ /*! | ||
, detachEvent = 'detachEvent' | ||
, ownerDocument = 'ownerDocument' | ||
, targetS = 'target' | ||
, qSA = 'querySelectorAll' | ||
, doc = document || {} | ||
@@ -34,3 +37,3 @@ , root = doc.documentElement || {} | ||
, touchTypeRegex = /^touch|^gesture/i | ||
, ONE = { one: 1 } // singleton for quick matching making add() do one() | ||
, ONE = {} // singleton for quick matching making add() do one() | ||
@@ -41,3 +44,3 @@ , nativeEvents = (function (hash, events, i) { | ||
return hash | ||
})({}, ( | ||
}({}, ( | ||
'click dblclick mouseup mousedown contextmenu ' + // mouse buttons | ||
@@ -49,3 +52,4 @@ 'mousewheel mousemultiwheel DOMMouseScroll ' + // mouse wheel | ||
'focus blur change reset select submit ' + // form elements | ||
'load unload beforeunload resize move DOMContentLoaded readystatechange ' + // window | ||
'load unload beforeunload resize move DOMContentLoaded '+ // window | ||
'readystatechange message ' + // window | ||
'error abort scroll ' + // misc | ||
@@ -58,3 +62,3 @@ (W3C_MODEL ? // element.fireEvent('onXYZ'... is not forgiving if we try to fire an event | ||
'gesturestart gesturechange gestureend ' + // gesture | ||
'message readystatechange pageshow pagehide popstate ' + // window | ||
'readystatechange pageshow pagehide popstate ' + // window | ||
'hashchange offline online ' + // window | ||
@@ -70,24 +74,25 @@ 'afterprint beforeprint ' + // printing | ||
).split(' ') | ||
) | ||
)) | ||
, customEvents = (function () { | ||
var cdp = 'compareDocumentPosition' | ||
var isAncestor = cdp in root | ||
? function (element, container) { | ||
return container[cdp] && (container[cdp](element) & 16) === 16 | ||
} | ||
: 'contains' in root | ||
? function (element, container) { | ||
container = container.nodeType === 9 || container === window ? root : container | ||
return container !== element && container.contains(element) | ||
} | ||
: function (element, container) { | ||
while (element = element.parentNode) if (element === container) return 1 | ||
return 0 | ||
} | ||
, isAncestor = cdp in root | ||
? function (element, container) { | ||
return container[cdp] && (container[cdp](element) & 16) === 16 | ||
} | ||
: 'contains' in root | ||
? function (element, container) { | ||
container = container.nodeType === 9 || container === window ? root : container | ||
return container !== element && container.contains(element) | ||
} | ||
: function (element, container) { | ||
while (element = element.parentNode) if (element === container) return 1 | ||
return 0 | ||
} | ||
function check(event) { | ||
var related = event.relatedTarget | ||
if (!related) return related === null | ||
return (related !== this && related.prefix !== 'xul' && !/document/.test(this.toString()) && !isAncestor(related, this)) | ||
return !related | ||
? related === null | ||
: (related !== this && related.prefix !== 'xul' && !/document/.test(this.toString()) && !isAncestor(related, this)) | ||
} | ||
@@ -100,3 +105,3 @@ | ||
} | ||
})() | ||
}()) | ||
@@ -110,2 +115,3 @@ , fixEvent = (function () { | ||
, touchProps = commonProps.concat('touches targetTouches changedTouches scale rotation'.split(' ')) | ||
, messageProps = commonProps.concat(['data', 'origin', 'source']) | ||
, preventDefault = 'preventDefault' | ||
@@ -151,3 +157,3 @@ , createPreventDefault = function (event) { | ||
, type = event.type | ||
, target = event.target || event.srcElement | ||
, target = event[targetS] || event.srcElement | ||
@@ -157,3 +163,3 @@ result[preventDefault] = createPreventDefault(event) | ||
result.stop = createStop(result) | ||
result.target = target && target.nodeType === 3 ? target.parentNode : target | ||
result[targetS] = target && target.nodeType === 3 ? target.parentNode : target | ||
@@ -183,2 +189,4 @@ if (isNative) { // we only need basic augmentation on custom events, the rest is too expensive | ||
props = textProps | ||
} else if (type === 'message') { | ||
props = messageProps | ||
} | ||
@@ -189,3 +197,3 @@ copyProps(event, result, props || commonProps) | ||
} | ||
})() | ||
}()) | ||
@@ -200,2 +208,3 @@ // if we're in old IE we can't do onpropertychange on doc or win so we use doc.documentElement for both | ||
function entry(element, type, handler, original, namespaces) { | ||
var isNative = this.isNative = nativeEvents[type] && element[eventSupport] | ||
this.element = element | ||
@@ -207,7 +216,6 @@ this.type = type | ||
this.custom = customEvents[type] | ||
this.isNative = nativeEvents[type] && element[eventSupport] | ||
this.eventType = W3C_MODEL || this.isNative ? type : 'propertychange' | ||
this.customType = !W3C_MODEL && !this.isNative && type | ||
this.target = targetElement(element, this.isNative) | ||
this.eventSupport = this.target[eventSupport] | ||
this.eventType = W3C_MODEL || isNative ? type : 'propertychange' | ||
this.customType = !W3C_MODEL && !isNative && type | ||
this[targetS] = targetElement(element, isNative) | ||
this[eventSupport] = this[targetS][eventSupport] | ||
} | ||
@@ -241,3 +249,3 @@ | ||
return entry | ||
})() | ||
}()) | ||
@@ -314,4 +322,16 @@ , registry = (function () { | ||
return { has: has, get: get, put: put, del: del, entries: entries } | ||
})() | ||
}()) | ||
, selectorEngine = doc[qSA] | ||
? function (s, r) { | ||
return r[qSA](s) | ||
} | ||
: function () { | ||
throw new Error('Bean: No selector engine installed') // eeek | ||
} | ||
, setSelectorEngine = function (e) { | ||
selectorEngine = e | ||
} | ||
// add and remove listeners to DOM elements | ||
@@ -329,5 +349,5 @@ , listener = W3C_MODEL ? function (element, type, fn, add) { | ||
, handler = function (event) { | ||
event = fixEvent(event || ((this.ownerDocument || this.document || this).parentWindow || win).event, true) | ||
event = fixEvent(event || ((this[ownerDocument] || this.document || this).parentWindow || win).event, true) | ||
if (beanDel) // delegated event, fix the fix | ||
event.currentTarget = beanDel.ft(event.target, element) | ||
event.currentTarget = beanDel.ft(event[targetS], element) | ||
return fn.apply(element, [event].concat(args)) | ||
@@ -342,6 +362,6 @@ } | ||
, handler = function (event) { | ||
var target = beanDel ? beanDel.ft(event.target, element) : this // deleated event | ||
var target = beanDel ? beanDel.ft(event[targetS], element) : this // deleated event | ||
if (condition ? condition.apply(target, arguments) : W3C_MODEL ? true : event && event.propertyName === '_on' + type || !event) { | ||
if (event) { | ||
event = fixEvent(event || ((this.ownerDocument || this.document || this).parentWindow || win).event, isNative) | ||
event = fixEvent(event || ((this[ownerDocument] || this.document || this).parentWindow || win).event, isNative) | ||
event.currentTarget = target | ||
@@ -371,4 +391,4 @@ } | ||
if (handlers[i].inNamespaces(namespaces)) { | ||
if ((entry = handlers[i]).eventSupport) | ||
listener(entry.target, entry.eventType, entry.handler, false, entry.type) | ||
if ((entry = handlers[i])[eventSupport]) | ||
listener(entry[targetS], entry.eventType, entry.handler, false, entry.type) | ||
// TODO: this is problematic, we have a registry.get() and registry.del() that | ||
@@ -402,7 +422,9 @@ // both do registry searches so we waste cycles doing this. Needs to be rolled into | ||
customHandler(element, entry.handler, type, false, args, false) | ||
if (entry.eventSupport) | ||
listener(entry.target, entry.eventType, entry.handler, true, entry.customType) | ||
if (entry[eventSupport]) | ||
listener(entry[targetS], entry.eventType, entry.handler, true, entry.customType) | ||
} | ||
, del = function (selector, fn, $) { | ||
//TODO: findTarget (therefore $) is called twice, once for match and once for | ||
// setting e.currentTarget, fix this so it's only needed once | ||
var findTarget = function (target, root) { | ||
@@ -418,5 +440,4 @@ var i, array = typeof selector === 'string' ? $(selector, root) : selector | ||
, handler = function (e) { | ||
var match = findTarget(e.target, this) | ||
if (match) | ||
fn.apply(match, arguments) | ||
var match = findTarget(e[targetS], this) | ||
match && fn.apply(match, arguments) | ||
} | ||
@@ -433,3 +454,3 @@ | ||
, remove = function (element, typeSpec, fn) { | ||
var k, m, type, namespaces, i | ||
var k, type, namespaces, i | ||
, rm = removeListener | ||
@@ -466,2 +487,3 @@ , isString = typeSpec && typeof typeSpec === 'string' | ||
// 5th argument, $=selector engine, is deprecated and will be removed | ||
, add = function (element, events, fn, delfn, $) { | ||
@@ -480,3 +502,3 @@ var type, types, i, args | ||
types = (isDel ? fn : events).split(' ') | ||
isDel && (fn = del(events, (originalFn = delfn), $)) && (args = slice.call(args, 1)) | ||
isDel && (fn = del(events, (originalFn = delfn), $ || selectorEngine)) && (args = slice.call(args, 1)) | ||
// special case for one() | ||
@@ -552,2 +574,3 @@ this === ONE && (fn = once(remove, element, events, fn, originalFn)) | ||
, fire: fire | ||
, setSelectorEngine: setSelectorEngine | ||
, noConflict: function () { | ||
@@ -554,0 +577,0 @@ context[name] = old |
@@ -10,2 +10,2 @@ /*! | ||
*/ | ||
!function(a,b,c){typeof module!="undefined"?module.exports=c(a,b):typeof define=="function"&&typeof define.amd=="object"?define(c):b[a]=c(a,b)}("bean",this,function(a,b){var c=window,d=b[a],e=/over|out/,f=/[^\.]*(?=\..*)\.|.*/,g=/\..*/,h="addEventListener",i="attachEvent",j="removeEventListener",k="detachEvent",l=document||{},m=l.documentElement||{},n=m[h],o=n?h:i,p=Array.prototype.slice,q=/click|mouse(?!(.*wheel|scroll))|menu|drag|drop/i,r=/mouse.*(wheel|scroll)/i,s=/^text/i,t=/^touch|^gesture/i,u={one:1},v=function(a,b,c){for(c=0;c<b.length;c++)a[b[c]]=1;return a}({},("click dblclick mouseup mousedown contextmenu mousewheel mousemultiwheel DOMMouseScroll mouseover mouseout mousemove selectstart selectend keydown keypress keyup orientationchange focus blur change reset select submit load unload beforeunload resize move DOMContentLoaded readystatechange error abort scroll "+(n?"show input invalid touchstart touchmove touchend touchcancel gesturestart gesturechange gestureend message readystatechange pageshow pagehide popstate hashchange offline online afterprint beforeprint dragstart dragenter dragover dragleave drag drop dragend loadstart progress suspend emptied stalled loadmetadata loadeddata canplay canplaythrough playing waiting seeking seeked ended durationchange timeupdate play pause ratechange volumechange cuechange checking noupdate downloading cached updateready obsolete ":"")).split(" ")),w=function(){function c(a){var c=a.relatedTarget;return c?c!==this&&c.prefix!=="xul"&&!/document/.test(this.toString())&&!b(c,this):c===null}var a="compareDocumentPosition",b=a in m?function(b,c){return c[a]&&(c[a](b)&16)===16}:"contains"in m?function(a,b){return b=b.nodeType===9||b===window?m:b,b!==a&&b.contains(a)}:function(a,b){while(a=a.parentNode)if(a===b)return 1;return 0};return{mouseenter:{base:"mouseover",condition:c},mouseleave:{base:"mouseout",condition:c},mousewheel:{base:/Firefox/.test(navigator.userAgent)?"DOMMouseScroll":"mousewheel"}}}(),x=function(){var a="altKey attrChange attrName bubbles cancelable ctrlKey currentTarget detail eventPhase getModifierState isTrusted metaKey relatedNode relatedTarget shiftKey srcElement target timeStamp type view which".split(" "),b=a.concat("button buttons clientX clientY dataTransfer fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" ")),c=b.concat("wheelDelta wheelDeltaX wheelDeltaY wheelDeltaZ axis".split(" ")),d=a.concat("char charCode key keyCode keyIdentifier keyLocation".split(" ")),f=a.concat(["data"]),g=a.concat("touches targetTouches changedTouches scale rotation".split(" ")),h="preventDefault",i=function(a){return function(){a[h]?a[h]():a.returnValue=!1}},j="stopPropagation",k=function(a){return function(){a[j]?a[j]():a.cancelBubble=!0}},n=function(a){return function(){a[h](),a[j](),a.stopped=!0}},o=function(a,b,c){var d,e;for(d=c.length;d--;)e=c[d],!(e in b)&&e in a&&(b[e]=a[e])};return function(p,u){var v={originalEvent:p,isNative:u};if(!p)return v;var w,x=p.type,y=p.target||p.srcElement;v[h]=i(p),v[j]=k(p),v.stop=n(v),v.target=y&&y.nodeType===3?y.parentNode:y;if(u){if(x.indexOf("key")!==-1)w=d,v.keyCode=p.keyCode||p.which;else if(q.test(x)){w=b,v.rightClick=p.which===3||p.button===2,v.pos={x:0,y:0};if(p.pageX||p.pageY)v.clientX=p.pageX,v.clientY=p.pageY;else if(p.clientX||p.clientY)v.clientX=p.clientX+l.body.scrollLeft+m.scrollLeft,v.clientY=p.clientY+l.body.scrollTop+m.scrollTop;e.test(x)&&(v.relatedTarget=p.relatedTarget||p[(x==="mouseover"?"from":"to")+"Element"])}else t.test(x)?w=g:r.test(x)?w=c:s.test(x)&&(w=f);o(p,v,w||a)}return v}}(),y=function(a,b){return!n&&!b&&(a===l||a===c)?m:a},z=function(){function a(a,b,c,d,e){this.element=a,this.type=b,this.handler=c,this.original=d,this.namespaces=e,this.custom=w[b],this.isNative=v[b]&&a[o],this.eventType=n||this.isNative?b:"propertychange",this.customType=!n&&!this.isNative&&b,this.target=y(a,this.isNative),this.eventSupport=this.target[o]}return a.prototype={inNamespaces:function(a){var b,c;if(!a)return!0;if(!this.namespaces)return!1;for(b=a.length;b--;)for(c=this.namespaces.length;c--;)if(a[b]===this.namespaces[c])return!0;return!1},matches:function(a,b,c){return this.element===a&&(!b||this.original===b)&&(!c||this.handler===c)}},a}(),A=function(){var a={},b=function(c,d,e,f,g){if(!d||d==="*")for(var h in a)h.charAt(0)==="$"&&b(c,h.substr(1),e,f,g);else{var i=0,j,k=a["$"+d],l=c==="*";if(!k)return;for(j=k.length;i<j;i++)if(l||k[i].matches(c,e,f))if(!g(k[i],k,i,d))return}},c=function(b,c,d){var e,f=a["$"+c];if(f)for(e=f.length;e--;)if(f[e].matches(b,d,null))return!0;return!1},d=function(a,c,d){var e=[];return b(a,c,d,null,function(a){return e.push(a)}),e},e=function(b){return(a["$"+b.type]||(a["$"+b.type]=[])).push(b),b},f=function(c){b(c.element,c.type,null,c.handler,function(b,c,d){return c.splice(d,1),c.length===0&&delete a["$"+b.type],!1})},g=function(){var b,c=[];for(b in a)b.charAt(0)==="$"&&(c=c.concat(a[b]));return c};return{has:c,get:d,put:e,del:f,entries:g}}(),B=n?function(a,b,c,d){a[d?h:j](b,c,!1)}:function(a,b,c,d,e){e&&d&&a["_on"+e]===null&&(a["_on"+e]=0),a[d?i:k]("on"+b,c)},C=function(a,b,d){var e=b.__beanDel,f=function(f){return f=x(f||((this.ownerDocument||this.document||this).parentWindow||c).event,!0),e&&(f.currentTarget=e.ft(f.target,a)),b.apply(a,[f].concat(d))};return f.__beanDel=e,f},D=function(a,b,d,e,f,g){var h=b.__beanDel,i=function(i){var j=h?h.ft(i.target,a):this;if(e?e.apply(j,arguments):n?!0:i&&i.propertyName==="_on"+d||!i)i&&(i=x(i||((this.ownerDocument||this.document||this).parentWindow||c).event,g),i.currentTarget=j),b.apply(a,i&&(!f||f.length===0)?arguments:p.call(arguments,i?0:1).concat(f))};return i.__beanDel=h,i},E=function(a,b,c,d,e){return function(){a(b,c,e),d.apply(this,arguments)}},F=function(a,b,c,d){var e,f,h,i=b&&b.replace(g,""),j=A.get(a,i,c);for(e=0,f=j.length;e<f;e++)j[e].inNamespaces(d)&&((h=j[e]).eventSupport&&B(h.target,h.eventType,h.handler,!1,h.type),A.del(h))},G=function(a,b,c,d,e){var h,i=b.replace(g,""),j=b.replace(f,"").split(".");if(A.has(a,i,c))return a;i==="unload"&&(c=E(F,a,i,c,d)),w[i]&&(w[i].condition&&(c=D(a,c,i,w[i].condition,e,!0)),i=w[i].base||i),h=A.put(new z(a,i,c,d,j[0]&&j)),h.handler=h.isNative?C(a,h.handler,e):D(a,h.handler,i,!1,e,!1),h.eventSupport&&B(h.target,h.eventType,h.handler,!0,h.customType)},H=function(a,b,c){var d=function(b,d){var e,f=typeof a=="string"?c(a,d):a;for(;b&&b!==d;b=b.parentNode)for(e=f.length;e--;)if(f[e]===b)return b},e=function(a){var c=d(a.target,this);c&&b.apply(c,arguments)};return e.__beanDel={ft:d,selector:a,$:c},e},I=function(a,b,c){var d,e,h,i,j,k=F,l=b&&typeof b=="string";if(l&&b.indexOf(" ")>0){b=b.split(" ");for(j=b.length;j--;)I(a,b[j],c);return a}h=l&&b.replace(g,""),h&&w[h]&&(h=w[h].type);if(!b||l){if(i=l&&b.replace(f,""))i=i.split(".");k(a,h,c,i)}else if(typeof b=="function")k(a,null,b);else for(d in b)b.hasOwnProperty(d)&&I(a,d,b[d]);return a},J=function(a,b,c,d,e){var f,g,h,i,j=c,k=c&&typeof c=="string";if(b&&!c&&typeof b=="object")for(f in b)b.hasOwnProperty(f)&&J.apply(this,[a,f,b[f]]);else{i=arguments.length>3?p.call(arguments,3):[],g=(k?c:b).split(" "),k&&(c=H(b,j=d,e))&&(i=p.call(i,1)),this===u&&(c=E(I,a,b,c,j));for(h=g.length;h--;)G(a,g[h],c,j,i)}return a},K=function(){return J.apply(u,arguments)},L=n?function(a,b,d){var e=l.createEvent(a?"HTMLEvents":"UIEvents");e[a?"initEvent":"initUIEvent"](b,!0,!0,c,1),d.dispatchEvent(e)}:function(a,b,c){c=y(c,a),a?c.fireEvent("on"+b,l.createEventObject()):c["_on"+b]++},M=function(a,b,c){var d,e,h,i,j,k=b.split(" ");for(d=k.length;d--;){b=k[d].replace(g,"");if(i=k[d].replace(f,""))i=i.split(".");if(!i&&!c&&a[o])L(v[b],b,a);else{j=A.get(a,b),c=[!1].concat(c);for(e=0,h=j.length;e<h;e++)j[e].inNamespaces(i)&&j[e].handler.apply(a,c)}}return a},N=function(a,b,c){var d=0,e=A.get(b,c),f=e.length,g,h;for(;d<f;d++)e[d].original&&(h=e[d].handler.__beanDel,h?g=[a,h.selector,e[d].type,e[d].original,h.$]:g=[a,e[d].type,e[d].original],J.apply(null,g));return a},O={add:J,one:K,remove:I,clone:N,fire:M,noConflict:function(){return b[a]=d,this}};if(c[i]){var P=function(){var a,b=A.entries();for(a in b)b[a].type&&b[a].type!=="unload"&&I(b[a].element,b[a].type);c[k]("onunload",P),c.CollectGarbage&&c.CollectGarbage()};c[i]("onunload",P)}return O}) | ||
!function(a,b,c){typeof module!="undefined"?module.exports=c(a,b):typeof define=="function"&&typeof define.amd=="object"?define(c):b[a]=c(a,b)}("bean",this,function(a,b){var c=window,d=b[a],e=/over|out/,f=/[^\.]*(?=\..*)\.|.*/,g=/\..*/,h="addEventListener",i="attachEvent",j="removeEventListener",k="detachEvent",l="ownerDocument",m="target",n="querySelectorAll",o=document||{},p=o.documentElement||{},q=p[h],r=q?h:i,s=Array.prototype.slice,t=/click|mouse(?!(.*wheel|scroll))|menu|drag|drop/i,u=/mouse.*(wheel|scroll)/i,v=/^text/i,w=/^touch|^gesture/i,x={},y=function(a,b,c){for(c=0;c<b.length;c++)a[b[c]]=1;return a}({},("click dblclick mouseup mousedown contextmenu mousewheel mousemultiwheel DOMMouseScroll mouseover mouseout mousemove selectstart selectend keydown keypress keyup orientationchange focus blur change reset select submit load unload beforeunload resize move DOMContentLoaded readystatechange message error abort scroll "+(q?"show input invalid touchstart touchmove touchend touchcancel gesturestart gesturechange gestureend readystatechange pageshow pagehide popstate hashchange offline online afterprint beforeprint dragstart dragenter dragover dragleave drag drop dragend loadstart progress suspend emptied stalled loadmetadata loadeddata canplay canplaythrough playing waiting seeking seeked ended durationchange timeupdate play pause ratechange volumechange cuechange checking noupdate downloading cached updateready obsolete ":"")).split(" ")),z=function(){function c(a){var c=a.relatedTarget;return c?c!==this&&c.prefix!=="xul"&&!/document/.test(this.toString())&&!b(c,this):c===null}var a="compareDocumentPosition",b=a in p?function(b,c){return c[a]&&(c[a](b)&16)===16}:"contains"in p?function(a,b){return b=b.nodeType===9||b===window?p:b,b!==a&&b.contains(a)}:function(a,b){while(a=a.parentNode)if(a===b)return 1;return 0};return{mouseenter:{base:"mouseover",condition:c},mouseleave:{base:"mouseout",condition:c},mousewheel:{base:/Firefox/.test(navigator.userAgent)?"DOMMouseScroll":"mousewheel"}}}(),A=function(){var a="altKey attrChange attrName bubbles cancelable ctrlKey currentTarget detail eventPhase getModifierState isTrusted metaKey relatedNode relatedTarget shiftKey srcElement target timeStamp type view which".split(" "),b=a.concat("button buttons clientX clientY dataTransfer fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" ")),c=b.concat("wheelDelta wheelDeltaX wheelDeltaY wheelDeltaZ axis".split(" ")),d=a.concat("char charCode key keyCode keyIdentifier keyLocation".split(" ")),f=a.concat(["data"]),g=a.concat("touches targetTouches changedTouches scale rotation".split(" ")),h=a.concat(["data","origin","source"]),i="preventDefault",j=function(a){return function(){a[i]?a[i]():a.returnValue=!1}},k="stopPropagation",l=function(a){return function(){a[k]?a[k]():a.cancelBubble=!0}},n=function(a){return function(){a[i](),a[k](),a.stopped=!0}},q=function(a,b,c){var d,e;for(d=c.length;d--;)e=c[d],!(e in b)&&e in a&&(b[e]=a[e])};return function(r,s){var x={originalEvent:r,isNative:s};if(!r)return x;var y,z=r.type,A=r[m]||r.srcElement;x[i]=j(r),x[k]=l(r),x.stop=n(x),x[m]=A&&A.nodeType===3?A.parentNode:A;if(s){if(z.indexOf("key")!==-1)y=d,x.keyCode=r.keyCode||r.which;else if(t.test(z)){y=b,x.rightClick=r.which===3||r.button===2,x.pos={x:0,y:0};if(r.pageX||r.pageY)x.clientX=r.pageX,x.clientY=r.pageY;else if(r.clientX||r.clientY)x.clientX=r.clientX+o.body.scrollLeft+p.scrollLeft,x.clientY=r.clientY+o.body.scrollTop+p.scrollTop;e.test(z)&&(x.relatedTarget=r.relatedTarget||r[(z==="mouseover"?"from":"to")+"Element"])}else w.test(z)?y=g:u.test(z)?y=c:v.test(z)?y=f:z==="message"&&(y=h);q(r,x,y||a)}return x}}(),B=function(a,b){return!q&&!b&&(a===o||a===c)?p:a},C=function(){function a(a,b,c,d,e){var f=this.isNative=y[b]&&a[r];this.element=a,this.type=b,this.handler=c,this.original=d,this.namespaces=e,this.custom=z[b],this.eventType=q||f?b:"propertychange",this.customType=!q&&!f&&b,this[m]=B(a,f),this[r]=this[m][r]}return a.prototype={inNamespaces:function(a){var b,c;if(!a)return!0;if(!this.namespaces)return!1;for(b=a.length;b--;)for(c=this.namespaces.length;c--;)if(a[b]===this.namespaces[c])return!0;return!1},matches:function(a,b,c){return this.element===a&&(!b||this.original===b)&&(!c||this.handler===c)}},a}(),D=function(){var a={},b=function(c,d,e,f,g){if(!d||d==="*")for(var h in a)h.charAt(0)==="$"&&b(c,h.substr(1),e,f,g);else{var i=0,j,k=a["$"+d],l=c==="*";if(!k)return;for(j=k.length;i<j;i++)if(l||k[i].matches(c,e,f))if(!g(k[i],k,i,d))return}},c=function(b,c,d){var e,f=a["$"+c];if(f)for(e=f.length;e--;)if(f[e].matches(b,d,null))return!0;return!1},d=function(a,c,d){var e=[];return b(a,c,d,null,function(a){return e.push(a)}),e},e=function(b){return(a["$"+b.type]||(a["$"+b.type]=[])).push(b),b},f=function(c){b(c.element,c.type,null,c.handler,function(b,c,d){return c.splice(d,1),c.length===0&&delete a["$"+b.type],!1})},g=function(){var b,c=[];for(b in a)b.charAt(0)==="$"&&(c=c.concat(a[b]));return c};return{has:c,get:d,put:e,del:f,entries:g}}(),E=o[n]?function(a,b){return b[n](a)}:function(){throw new Error("Bean: No selector engine installed")},F=function(a){E=a},G=q?function(a,b,c,d){a[d?h:j](b,c,!1)}:function(a,b,c,d,e){e&&d&&a["_on"+e]===null&&(a["_on"+e]=0),a[d?i:k]("on"+b,c)},H=function(a,b,d){var e=b.__beanDel,f=function(f){return f=A(f||((this[l]||this.document||this).parentWindow||c).event,!0),e&&(f.currentTarget=e.ft(f[m],a)),b.apply(a,[f].concat(d))};return f.__beanDel=e,f},I=function(a,b,d,e,f,g){var h=b.__beanDel,i=function(i){var j=h?h.ft(i[m],a):this;if(e?e.apply(j,arguments):q?!0:i&&i.propertyName==="_on"+d||!i)i&&(i=A(i||((this[l]||this.document||this).parentWindow||c).event,g),i.currentTarget=j),b.apply(a,i&&(!f||f.length===0)?arguments:s.call(arguments,i?0:1).concat(f))};return i.__beanDel=h,i},J=function(a,b,c,d,e){return function(){a(b,c,e),d.apply(this,arguments)}},K=function(a,b,c,d){var e,f,h,i=b&&b.replace(g,""),j=D.get(a,i,c);for(e=0,f=j.length;e<f;e++)j[e].inNamespaces(d)&&((h=j[e])[r]&&G(h[m],h.eventType,h.handler,!1,h.type),D.del(h))},L=function(a,b,c,d,e){var h,i=b.replace(g,""),j=b.replace(f,"").split(".");if(D.has(a,i,c))return a;i==="unload"&&(c=J(K,a,i,c,d)),z[i]&&(z[i].condition&&(c=I(a,c,i,z[i].condition,e,!0)),i=z[i].base||i),h=D.put(new C(a,i,c,d,j[0]&&j)),h.handler=h.isNative?H(a,h.handler,e):I(a,h.handler,i,!1,e,!1),h[r]&&G(h[m],h.eventType,h.handler,!0,h.customType)},M=function(a,b,c){var d=function(b,d){var e,f=typeof a=="string"?c(a,d):a;for(;b&&b!==d;b=b.parentNode)for(e=f.length;e--;)if(f[e]===b)return b},e=function(a){var c=d(a[m],this);c&&b.apply(c,arguments)};return e.__beanDel={ft:d,selector:a,$:c},e},N=function(a,b,c){var d,e,h,i,j=K,k=b&&typeof b=="string";if(k&&b.indexOf(" ")>0){b=b.split(" ");for(i=b.length;i--;)N(a,b[i],c);return a}e=k&&b.replace(g,""),e&&z[e]&&(e=z[e].type);if(!b||k){if(h=k&&b.replace(f,""))h=h.split(".");j(a,e,c,h)}else if(typeof b=="function")j(a,null,b);else for(d in b)b.hasOwnProperty(d)&&N(a,d,b[d]);return a},O=function(a,b,c,d,e){var f,g,h,i,j=c,k=c&&typeof c=="string";if(b&&!c&&typeof b=="object")for(f in b)b.hasOwnProperty(f)&&O.apply(this,[a,f,b[f]]);else{i=arguments.length>3?s.call(arguments,3):[],g=(k?c:b).split(" "),k&&(c=M(b,j=d,e||E))&&(i=s.call(i,1)),this===x&&(c=J(N,a,b,c,j));for(h=g.length;h--;)L(a,g[h],c,j,i)}return a},P=function(){return O.apply(x,arguments)},Q=q?function(a,b,d){var e=o.createEvent(a?"HTMLEvents":"UIEvents");e[a?"initEvent":"initUIEvent"](b,!0,!0,c,1),d.dispatchEvent(e)}:function(a,b,c){c=B(c,a),a?c.fireEvent("on"+b,o.createEventObject()):c["_on"+b]++},R=function(a,b,c){var d,e,h,i,j,k=b.split(" ");for(d=k.length;d--;){b=k[d].replace(g,"");if(i=k[d].replace(f,""))i=i.split(".");if(!i&&!c&&a[r])Q(y[b],b,a);else{j=D.get(a,b),c=[!1].concat(c);for(e=0,h=j.length;e<h;e++)j[e].inNamespaces(i)&&j[e].handler.apply(a,c)}}return a},S=function(a,b,c){var d=0,e=D.get(b,c),f=e.length,g,h;for(;d<f;d++)e[d].original&&(h=e[d].handler.__beanDel,h?g=[a,h.selector,e[d].type,e[d].original,h.$]:g=[a,e[d].type,e[d].original],O.apply(null,g));return a},T={add:O,one:P,remove:N,clone:S,fire:R,setSelectorEngine:F,noConflict:function(){return b[a]=d,this}};if(c[i]){var U=function(){var a,b=D.entries();for(a in b)b[a].type&&b[a].type!=="unload"&&N(b[a].element,b[a].type);c[k]("onunload",U),c.CollectGarbage&&c.CollectGarbage()};c[i]("onunload",U)}return T}) |
{ | ||
"name": "bean" | ||
, "description": "an events api for javascript" | ||
, "version": "0.4.10" | ||
, "version": "0.4.11-1" | ||
, "homepage": "https://github.com/fat/bean" | ||
@@ -6,0 +6,0 @@ , "authors": [ |
@@ -57,14 +57,7 @@ Bean | ||
// event delegated events | ||
bean.add(element, '.content p', 'click', handler, queryEngine); | ||
bean.add(element, '.content p', 'click', handler); | ||
``` | ||
*(note: to use event delegation with a selector, you must pass bean.add a reference to a selector engine like qwery or sizzle)* | ||
Developers working on Mobile Webkit applications like iPhone or Android, you may wish to simply provide the following query selector with Bean: | ||
**Note**: the 5th parameter (selector engine) of previous Bean releases is now deprecated and will be removed in future versions. Use `setSelectorEngine()` instead. | ||
```javascript | ||
bean.add(element, '.content p', 'click', fn, function (selector) { | ||
return document.querySelectorAll(selector); | ||
}); | ||
``` | ||
Or alternatively, you can pass an array of elements (this actually cuts down on selector engine work, and is a more performant means of delegation if you know your DOM won't be changing: | ||
@@ -149,4 +142,13 @@ | ||
setSelectorEngine() | ||
---- | ||
<code>bean.setSelectorEngine()</code> allows you to set a default selector engine for all your delegation needs. | ||
custom events | ||
```javascript | ||
bean.setSelectorEngine(qwery); | ||
``` | ||
**Note**: `querySelectorAll()` is used as the default selector engine, this is available on most modern platforms such as mobile WebKit. To support event delegation on older browsers you will need to install a selector engine. | ||
Custom events | ||
------------- | ||
@@ -172,3 +174,3 @@ Bean uses methods similar to [Dean Edwards' event model](http://dean.edwards.name/weblog/2009/03/callbacks-vs-events/) to ensure custom events behave like real events, rather than just callbacks. | ||
object support | ||
Object support | ||
-------------- | ||
@@ -175,0 +177,0 @@ Good news, everything you can do in Bean with an element, you can also do with an object! This is particularly useful for working with classes or plugins. |
111
src/bean.js
@@ -15,2 +15,5 @@ !function (name, context, definition) { | ||
, detachEvent = 'detachEvent' | ||
, ownerDocument = 'ownerDocument' | ||
, targetS = 'target' | ||
, qSA = 'querySelectorAll' | ||
, doc = document || {} | ||
@@ -25,3 +28,3 @@ , root = doc.documentElement || {} | ||
, touchTypeRegex = /^touch|^gesture/i | ||
, ONE = { one: 1 } // singleton for quick matching making add() do one() | ||
, ONE = {} // singleton for quick matching making add() do one() | ||
@@ -32,3 +35,3 @@ , nativeEvents = (function (hash, events, i) { | ||
return hash | ||
})({}, ( | ||
}({}, ( | ||
'click dblclick mouseup mousedown contextmenu ' + // mouse buttons | ||
@@ -40,3 +43,4 @@ 'mousewheel mousemultiwheel DOMMouseScroll ' + // mouse wheel | ||
'focus blur change reset select submit ' + // form elements | ||
'load unload beforeunload resize move DOMContentLoaded readystatechange ' + // window | ||
'load unload beforeunload resize move DOMContentLoaded '+ // window | ||
'readystatechange message ' + // window | ||
'error abort scroll ' + // misc | ||
@@ -49,3 +53,3 @@ (W3C_MODEL ? // element.fireEvent('onXYZ'... is not forgiving if we try to fire an event | ||
'gesturestart gesturechange gestureend ' + // gesture | ||
'message readystatechange pageshow pagehide popstate ' + // window | ||
'readystatechange pageshow pagehide popstate ' + // window | ||
'hashchange offline online ' + // window | ||
@@ -61,24 +65,25 @@ 'afterprint beforeprint ' + // printing | ||
).split(' ') | ||
) | ||
)) | ||
, customEvents = (function () { | ||
var cdp = 'compareDocumentPosition' | ||
var isAncestor = cdp in root | ||
? function (element, container) { | ||
return container[cdp] && (container[cdp](element) & 16) === 16 | ||
} | ||
: 'contains' in root | ||
? function (element, container) { | ||
container = container.nodeType === 9 || container === window ? root : container | ||
return container !== element && container.contains(element) | ||
} | ||
: function (element, container) { | ||
while (element = element.parentNode) if (element === container) return 1 | ||
return 0 | ||
} | ||
, isAncestor = cdp in root | ||
? function (element, container) { | ||
return container[cdp] && (container[cdp](element) & 16) === 16 | ||
} | ||
: 'contains' in root | ||
? function (element, container) { | ||
container = container.nodeType === 9 || container === window ? root : container | ||
return container !== element && container.contains(element) | ||
} | ||
: function (element, container) { | ||
while (element = element.parentNode) if (element === container) return 1 | ||
return 0 | ||
} | ||
function check(event) { | ||
var related = event.relatedTarget | ||
if (!related) return related === null | ||
return (related !== this && related.prefix !== 'xul' && !/document/.test(this.toString()) && !isAncestor(related, this)) | ||
return !related | ||
? related === null | ||
: (related !== this && related.prefix !== 'xul' && !/document/.test(this.toString()) && !isAncestor(related, this)) | ||
} | ||
@@ -91,3 +96,3 @@ | ||
} | ||
})() | ||
}()) | ||
@@ -101,2 +106,3 @@ , fixEvent = (function () { | ||
, touchProps = commonProps.concat('touches targetTouches changedTouches scale rotation'.split(' ')) | ||
, messageProps = commonProps.concat(['data', 'origin', 'source']) | ||
, preventDefault = 'preventDefault' | ||
@@ -142,3 +148,3 @@ , createPreventDefault = function (event) { | ||
, type = event.type | ||
, target = event.target || event.srcElement | ||
, target = event[targetS] || event.srcElement | ||
@@ -148,3 +154,3 @@ result[preventDefault] = createPreventDefault(event) | ||
result.stop = createStop(result) | ||
result.target = target && target.nodeType === 3 ? target.parentNode : target | ||
result[targetS] = target && target.nodeType === 3 ? target.parentNode : target | ||
@@ -174,2 +180,4 @@ if (isNative) { // we only need basic augmentation on custom events, the rest is too expensive | ||
props = textProps | ||
} else if (type === 'message') { | ||
props = messageProps | ||
} | ||
@@ -180,3 +188,3 @@ copyProps(event, result, props || commonProps) | ||
} | ||
})() | ||
}()) | ||
@@ -191,2 +199,3 @@ // if we're in old IE we can't do onpropertychange on doc or win so we use doc.documentElement for both | ||
function entry(element, type, handler, original, namespaces) { | ||
var isNative = this.isNative = nativeEvents[type] && element[eventSupport] | ||
this.element = element | ||
@@ -198,7 +207,6 @@ this.type = type | ||
this.custom = customEvents[type] | ||
this.isNative = nativeEvents[type] && element[eventSupport] | ||
this.eventType = W3C_MODEL || this.isNative ? type : 'propertychange' | ||
this.customType = !W3C_MODEL && !this.isNative && type | ||
this.target = targetElement(element, this.isNative) | ||
this.eventSupport = this.target[eventSupport] | ||
this.eventType = W3C_MODEL || isNative ? type : 'propertychange' | ||
this.customType = !W3C_MODEL && !isNative && type | ||
this[targetS] = targetElement(element, isNative) | ||
this[eventSupport] = this[targetS][eventSupport] | ||
} | ||
@@ -232,3 +240,3 @@ | ||
return entry | ||
})() | ||
}()) | ||
@@ -305,4 +313,16 @@ , registry = (function () { | ||
return { has: has, get: get, put: put, del: del, entries: entries } | ||
})() | ||
}()) | ||
, selectorEngine = doc[qSA] | ||
? function (s, r) { | ||
return r[qSA](s) | ||
} | ||
: function () { | ||
throw new Error('Bean: No selector engine installed') // eeek | ||
} | ||
, setSelectorEngine = function (e) { | ||
selectorEngine = e | ||
} | ||
// add and remove listeners to DOM elements | ||
@@ -320,5 +340,5 @@ , listener = W3C_MODEL ? function (element, type, fn, add) { | ||
, handler = function (event) { | ||
event = fixEvent(event || ((this.ownerDocument || this.document || this).parentWindow || win).event, true) | ||
event = fixEvent(event || ((this[ownerDocument] || this.document || this).parentWindow || win).event, true) | ||
if (beanDel) // delegated event, fix the fix | ||
event.currentTarget = beanDel.ft(event.target, element) | ||
event.currentTarget = beanDel.ft(event[targetS], element) | ||
return fn.apply(element, [event].concat(args)) | ||
@@ -333,6 +353,6 @@ } | ||
, handler = function (event) { | ||
var target = beanDel ? beanDel.ft(event.target, element) : this // deleated event | ||
var target = beanDel ? beanDel.ft(event[targetS], element) : this // deleated event | ||
if (condition ? condition.apply(target, arguments) : W3C_MODEL ? true : event && event.propertyName === '_on' + type || !event) { | ||
if (event) { | ||
event = fixEvent(event || ((this.ownerDocument || this.document || this).parentWindow || win).event, isNative) | ||
event = fixEvent(event || ((this[ownerDocument] || this.document || this).parentWindow || win).event, isNative) | ||
event.currentTarget = target | ||
@@ -362,4 +382,4 @@ } | ||
if (handlers[i].inNamespaces(namespaces)) { | ||
if ((entry = handlers[i]).eventSupport) | ||
listener(entry.target, entry.eventType, entry.handler, false, entry.type) | ||
if ((entry = handlers[i])[eventSupport]) | ||
listener(entry[targetS], entry.eventType, entry.handler, false, entry.type) | ||
// TODO: this is problematic, we have a registry.get() and registry.del() that | ||
@@ -393,7 +413,9 @@ // both do registry searches so we waste cycles doing this. Needs to be rolled into | ||
customHandler(element, entry.handler, type, false, args, false) | ||
if (entry.eventSupport) | ||
listener(entry.target, entry.eventType, entry.handler, true, entry.customType) | ||
if (entry[eventSupport]) | ||
listener(entry[targetS], entry.eventType, entry.handler, true, entry.customType) | ||
} | ||
, del = function (selector, fn, $) { | ||
//TODO: findTarget (therefore $) is called twice, once for match and once for | ||
// setting e.currentTarget, fix this so it's only needed once | ||
var findTarget = function (target, root) { | ||
@@ -409,5 +431,4 @@ var i, array = typeof selector === 'string' ? $(selector, root) : selector | ||
, handler = function (e) { | ||
var match = findTarget(e.target, this) | ||
if (match) | ||
fn.apply(match, arguments) | ||
var match = findTarget(e[targetS], this) | ||
match && fn.apply(match, arguments) | ||
} | ||
@@ -424,3 +445,3 @@ | ||
, remove = function (element, typeSpec, fn) { | ||
var k, m, type, namespaces, i | ||
var k, type, namespaces, i | ||
, rm = removeListener | ||
@@ -457,2 +478,3 @@ , isString = typeSpec && typeof typeSpec === 'string' | ||
// 5th argument, $=selector engine, is deprecated and will be removed | ||
, add = function (element, events, fn, delfn, $) { | ||
@@ -471,3 +493,3 @@ var type, types, i, args | ||
types = (isDel ? fn : events).split(' ') | ||
isDel && (fn = del(events, (originalFn = delfn), $)) && (args = slice.call(args, 1)) | ||
isDel && (fn = del(events, (originalFn = delfn), $ || selectorEngine)) && (args = slice.call(args, 1)) | ||
// special case for one() | ||
@@ -543,2 +565,3 @@ this === ONE && (fn = once(remove, element, events, fn, originalFn)) | ||
, fire: fire | ||
, setSelectorEngine: setSelectorEngine | ||
, noConflict: function () { | ||
@@ -545,0 +568,0 @@ context[name] = old |
@@ -6,7 +6,5 @@ !function ($) { | ||
return function () { | ||
for (var args, i = 0, l = this.length; i < l; i++) { | ||
args = [this[i]].concat(_args, Array.prototype.slice.call(arguments, 0)) | ||
args.length == 4 && args.push($) | ||
!arguments.length && method == 'add' && type && (method = 'fire') | ||
b[method].apply(this, args) | ||
for (var i = 0, l = this.length; i < l; i++) { | ||
if (!arguments.length && method == 'add' && type) method = 'fire' | ||
b[method].apply(this, [this[i]].concat(_args, Array.prototype.slice.call(arguments, 0))) | ||
} | ||
@@ -49,8 +47,6 @@ return this | ||
, shortcuts = [ | ||
'blur', 'change', 'click', 'dblclick', 'error', 'focus', 'focusin' | ||
, 'focusout', 'keydown', 'keypress', 'keyup', 'load', 'mousedown' | ||
, 'mouseenter', 'mouseleave', 'mouseout', 'mouseover', 'mouseup', 'mousemove' | ||
, 'resize', 'scroll', 'select', 'submit', 'unload' | ||
] | ||
, shortcuts = | ||
('blur change click dblclick error focus focusin focusout keydown keypress ' | ||
+ 'keyup load mousedown mouseenter mouseleave mouseout mouseover mouseup ' | ||
+ 'mousemove resize scroll select submit unload').split(' ') | ||
@@ -61,3 +57,5 @@ for (var i = shortcuts.length; i--;) { | ||
b.setSelectorEngine($) | ||
$.ender(methods, true) | ||
}(ender) |
@@ -1,12 +0,31 @@ | ||
if (!window.console) { | ||
window.console = { log: function () {}} | ||
/*globals bean:true sink:true start:true Syn:true qwery: true*/ | ||
// basic feature-tests, some tests shouldn't run in certain browsers | ||
var features = { | ||
w3c: !!window.addEventListener | ||
, qSA: !!document.querySelectorAll | ||
, createEvent: (function () { | ||
try { | ||
document.createEvent('KeyEvents') | ||
return true | ||
} catch (e) { | ||
try { | ||
document.createEvent('TextEvent') | ||
return true | ||
} catch (e) { } | ||
} | ||
return false | ||
}()) | ||
, message: !!window.postMessage | ||
} | ||
if (!window.console) window.console = { log: function () {}} | ||
sink('no conflict', function (test, ok) { | ||
test('should return old bean back to context', 1, function () { | ||
var b = bean.noConflict(); | ||
ok(bean() == 'success', 'old bean called'); | ||
window.bean = b; | ||
}); | ||
}); | ||
var b = bean.noConflict() | ||
ok(bean() == 'success', 'old bean called') | ||
window.bean = b | ||
}) | ||
}) | ||
@@ -16,113 +35,125 @@ sink('add', function (test, ok) { | ||
test('add: should return the element passed in', 1, function () { | ||
var el = document.getElementById('input'); | ||
var returned = bean.add(el, 'click', function () {}); | ||
ok(el == returned, 'returns the element passed in'); | ||
bean.remove(el); | ||
}); | ||
var el = document.getElementById('input') | ||
, returned = bean.add(el, 'click', function () {}) | ||
ok(el == returned, 'returns the element passed in') | ||
bean.remove(el) | ||
}) | ||
test('add: should be able to add single events to elements', 1, function () { | ||
var el = document.getElementById('input'); | ||
var el = document.getElementById('input') | ||
bean.add(el, 'click', function () { | ||
bean.remove(el); | ||
ok(true, 'adds single events to elements'); | ||
}); | ||
Syn.click(el); | ||
}); | ||
bean.remove(el) | ||
ok(true, 'adds single events to elements') | ||
}) | ||
Syn.click(el) | ||
}) | ||
test('add: should be able to add single events to objects', 1, function () { | ||
var obj = {}; | ||
var obj = {} | ||
bean.add(obj, 'complete', function () { | ||
ok(true, 'adds single events to objects'); | ||
}); | ||
bean.fire(obj, 'complete'); | ||
bean.remove(obj); | ||
bean.fire(obj, 'complete'); | ||
}); | ||
ok(true, 'adds single events to objects') | ||
}) | ||
bean.fire(obj, 'complete') | ||
bean.remove(obj) | ||
bean.fire(obj, 'complete') | ||
}) | ||
test('add: scope should be equal to element', 1, function () { | ||
var el = document.getElementById('input'); | ||
var el = document.getElementById('input') | ||
bean.add(el, 'click', function (e) { | ||
bean.remove(el); | ||
bean.remove(el) | ||
ok(this == el, 'equal to element') | ||
}); | ||
Syn.click(el); | ||
}); | ||
}) | ||
Syn.click(el) | ||
}) | ||
test('add: should recieve an event method', 1, function () { | ||
var el = document.getElementById('input'); | ||
var el = document.getElementById('input') | ||
bean.add(el, 'click', function (e) { | ||
bean.remove(el); | ||
bean.remove(el) | ||
ok(e != null, 'recieves an event method') | ||
}); | ||
Syn.click(el); | ||
}); | ||
}) | ||
Syn.click(el) | ||
}) | ||
test('add: should be able to pass x amount of additional arguments', 4, function () { | ||
var el = document.getElementById('input'); | ||
handler = function (e, foo, bar, baz) { | ||
bean.remove(el); | ||
ok(e != null, 'listener was called with event'); | ||
ok(foo === 1, 'listener was called with correct argument'); | ||
ok(bar === 2, 'listener was called with correct argument'); | ||
ok(baz === 3, 'listener was called with correct argument'); | ||
}; | ||
bean.add(el, 'click', handler, 1, 2, 3); | ||
Syn.click(el); | ||
}); | ||
var el = document.getElementById('input') | ||
, handler = function (e, foo, bar, baz) { | ||
bean.remove(el) | ||
ok(e != null, 'listener was called with event') | ||
ok(foo === 1, 'listener was called with correct argument') | ||
ok(bar === 2, 'listener was called with correct argument') | ||
ok(baz === 3, 'listener was called with correct argument') | ||
} | ||
bean.add(el, 'click', handler, 1, 2, 3) | ||
Syn.click(el) | ||
}) | ||
test('add: should be able to add multiple events by space seperating them', 2, function () { | ||
var el = document.getElementById('input'); | ||
var el = document.getElementById('input') | ||
bean.add(el, 'click keypress', function () { | ||
ok(true, 'adds multiple events by space seperating them'); | ||
}); | ||
Syn.click(el).key('j'); | ||
}); | ||
ok(true, 'adds multiple events by space seperating them') | ||
}) | ||
Syn.click(el).key('j') | ||
}) | ||
test('add: should add same event only one time', 1, function () { | ||
var el = document.getElementById('input'); | ||
bean.remove(el); | ||
var handler = function () {ok(true, 'adds same event only one time')}; | ||
bean.add(el, 'click', handler); | ||
bean.add(el, 'click', handler); | ||
bean.add(el, 'click', handler); | ||
Syn.click(el); | ||
}); | ||
var el = document.getElementById('input') | ||
, handler = function () {ok(true, 'adds same event only one time')} | ||
bean.remove(el) | ||
bean.add(el, 'click', handler) | ||
bean.add(el, 'click', handler) | ||
bean.add(el, 'click', handler) | ||
Syn.click(el) | ||
}) | ||
test('add: should be able to add multiple events of the same type', 3, function () { | ||
var el = document.getElementById('input'); | ||
bean.remove(el); | ||
bean.add(el, 'click', function () {ok(true, 'adds multiple events of the same type 1')}); | ||
bean.add(el, 'click', function () {ok(true, 'adds multiple events of the same type 2')}); | ||
bean.add(el, 'click', function () {ok(true, 'adds multiple events of the same type 3')}); | ||
Syn.click(el); | ||
}); | ||
var el = document.getElementById('input') | ||
bean.remove(el) | ||
bean.add(el, 'click', function () {ok(true, 'adds multiple events of the same type 1')}) | ||
bean.add(el, 'click', function () {ok(true, 'adds multiple events of the same type 2')}) | ||
bean.add(el, 'click', function () {ok(true, 'adds multiple events of the same type 3')}) | ||
Syn.click(el) | ||
}) | ||
test('add: should be able to add multiple events simultaneously with an object literal', 2, function () { | ||
var el = document.getElementById('input'); | ||
bean.remove(el); | ||
var el = document.getElementById('input') | ||
bean.remove(el) | ||
bean.add(el, { | ||
click: function () { | ||
ok(true, 'adds multiple events simultaneously with an object literal 1'); | ||
ok(true, 'adds multiple events simultaneously with an object literal 1') | ||
}, | ||
keydown: function () { | ||
ok(true, 'adds multiple events simultaneously with an object literal 2'); | ||
bean.remove(el); | ||
ok(true, 'adds multiple events simultaneously with an object literal 2') | ||
bean.remove(el) | ||
} | ||
}); | ||
Syn.click(el).key('j'); | ||
}); | ||
}) | ||
Syn.click(el).key('j') | ||
}) | ||
test('add: should bubble up dom', 1, function () { | ||
var el1 = document.getElementById('foo'); | ||
var el2 = document.getElementById('bar'); | ||
bean.add(el1, 'click', function () {ok(true, 'bubbles up dom')}); | ||
Syn.click(el2); | ||
}); | ||
var el1 = document.getElementById('foo') | ||
, el2 = document.getElementById('bar') | ||
bean.add(el1, 'click', function () {ok(true, 'bubbles up dom')}) | ||
Syn.click(el2) | ||
}) | ||
test('add: shouldn\'t trigger event when adding additional custom event listeners', 0, function () { | ||
var el = document.getElementById('input'); | ||
bean.add(el, 'foo', function () {ok(true, 'additional custom event listeners trigger event 1')}); | ||
bean.add(el, 'foo', function () {ok(true, 'additional custom event listeners trigger event 2')}); | ||
}); | ||
var el = document.getElementById('input') | ||
bean.add(el, 'foo', function () {ok(true, 'additional custom event listeners trigger event 1')}) | ||
bean.add(el, 'foo', function () {ok(true, 'additional custom event listeners trigger event 2')}) | ||
}) | ||
if (features.message) { | ||
test('add: should bind onmessage to window', 3, function () { | ||
bean.add(window, 'message', function(e) { | ||
ok(e.data === 'hello there', 'data should be copied') | ||
ok(e.origin === e.originalEvent.origin, 'origin should be copied') | ||
ok(e.source === e.originalEvent.source, 'source should be copied') | ||
}) | ||
window.postMessage('hello there', '*') | ||
}) | ||
} | ||
test('one: should only trigger handler once', 1, function () { | ||
@@ -134,3 +165,3 @@ var el = document.getElementById('input') | ||
Syn.click(el) | ||
}); | ||
}) | ||
@@ -144,3 +175,3 @@ test('one: should be removable', 0, function () { | ||
Syn.click(el) | ||
}); | ||
}) | ||
@@ -152,20 +183,20 @@ }) | ||
test('fire: should be able to fire an event', 1, function () { | ||
var el = document.getElementById('input'); | ||
bean.remove(el); | ||
bean.add(el, 'click', function () {ok(true, 'fires an event')}); | ||
bean.fire(el, 'click'); | ||
}); | ||
var el = document.getElementById('input') | ||
bean.remove(el) | ||
bean.add(el, 'click', function () {ok(true, 'fires an event')}) | ||
bean.fire(el, 'click') | ||
}) | ||
test('fire: should be able to fire multiple events by space seperation', 2, function () { | ||
var el = document.getElementById('input'); | ||
bean.remove(el); | ||
bean.add(el, 'mousedown', function () {ok(true, 'fires multiple events by space seperation 1')}); | ||
bean.add(el, 'mouseup', function () {ok(true, 'fires multiple events by space seperation 2')}); | ||
bean.fire(el, 'mousedown mouseup'); | ||
}); | ||
var el = document.getElementById('input') | ||
bean.remove(el) | ||
bean.add(el, 'mousedown', function () {ok(true, 'fires multiple events by space seperation 1')}) | ||
bean.add(el, 'mouseup', function () {ok(true, 'fires multiple events by space seperation 2')}) | ||
bean.fire(el, 'mousedown mouseup') | ||
}) | ||
test('fire: should be able to pass multiple arguments to custom event', 4, function () { | ||
// jquery like array syntax | ||
var el = document.getElementById('input'); | ||
bean.remove(el); | ||
var el = document.getElementById('input') | ||
bean.remove(el) | ||
bean.add(el, 'foo', function (one, two, three) { | ||
@@ -176,5 +207,5 @@ ok(arguments.length == 3, 'fires an event with 3 arguments') | ||
ok(three == 3, 'value should equal 3') | ||
}); | ||
bean.fire(el, 'foo', [1, 2, 3]); | ||
}); | ||
}) | ||
bean.fire(el, 'foo', [1, 2, 3]) | ||
}) | ||
@@ -186,40 +217,39 @@ }) | ||
test('custom: should be able to add single custom events', 1, function () { | ||
var el = document.getElementById('input'); | ||
bean.remove(el); | ||
var el = document.getElementById('input') | ||
bean.remove(el) | ||
bean.add(el, 'partytime', function () { | ||
ok(true, 'add single custom events'); | ||
}); | ||
bean.fire(el, 'partytime'); | ||
}); | ||
ok(true, 'add single custom events') | ||
}) | ||
bean.fire(el, 'partytime') | ||
}) | ||
test('custom: should bubble up dom like traditional events', 1, function () { | ||
if (!window.addEventListener) { | ||
//dean edwards onpropertychange hack doesn't bubble unfortunately :( | ||
return ok(true, 'internet explorer is not a bubler, turns out.') | ||
} | ||
var el1 = document.getElementById('foo'); | ||
var el2 = document.getElementById('bar'); | ||
bean.add(el1, 'partytime', function () {ok(true, 'bubbles up dom like traditional events')}); | ||
bean.fire(el2, 'partytime'); | ||
}); | ||
if (features.w3c) { | ||
//dean edwards' onpropertychange hack doesn't bubble unfortunately :( | ||
test('custom: should bubble up dom like traditional events', 1, function () { | ||
var el1 = document.getElementById('foo') | ||
, el2 = document.getElementById('bar') | ||
bean.add(el1, 'partytime', function () {ok(true, 'bubbles up dom like traditional events')}) | ||
bean.fire(el2, 'partytime') | ||
}) | ||
} | ||
test('custom: should be able to add, fire and remove custom events to document', 1, function () { | ||
bean.remove(document); | ||
bean.remove(document) | ||
bean.add(document, 'justlookatthat', function () { | ||
ok(true, 'add custom events to document'); | ||
ok(true, 'add custom events to document') | ||
bean.remove(document, 'justlookatthat') | ||
}); | ||
bean.fire(document, 'justlookatthat'); | ||
bean.fire(document, 'justlookatthat'); | ||
}); | ||
}) | ||
bean.fire(document, 'justlookatthat') | ||
bean.fire(document, 'justlookatthat') | ||
}) | ||
test('custom: should be able to add, fire and remove custom events to window', 1, function () { | ||
bean.remove(window); | ||
bean.remove(window) | ||
bean.add(window, 'spiffy', function () { | ||
ok(true, 'add custom events to window'); | ||
ok(true, 'add custom events to window') | ||
bean.remove(window, 'spiffy') | ||
}); | ||
bean.fire(window, 'spiffy'); | ||
bean.fire(window, 'spiffy'); | ||
}); | ||
}) | ||
bean.fire(window, 'spiffy') | ||
bean.fire(window, 'spiffy') | ||
}) | ||
@@ -231,86 +261,71 @@ }) | ||
test('event: should have correct target', 1, function () { | ||
var el1 = document.getElementById('foo'); | ||
var el2 = document.getElementById('bar'); | ||
bean.remove(el1, 'click'); | ||
bean.add(el1, 'click', function (e) {ok(e.target == el2, 'has correct target')}); | ||
Syn.click(el2); | ||
}); | ||
var el1 = document.getElementById('foo') | ||
, el2 = document.getElementById('bar') | ||
bean.remove(el1, 'click') | ||
bean.add(el1, 'click', function (e) {ok(e.target == el2, 'has correct target')}) | ||
Syn.click(el2) | ||
}) | ||
test('event: should have stop propagation method', 1, function () { | ||
var el = document.getElementById('foo'); | ||
bean.remove(el); | ||
bean.add(el, 'click', function (e) {ok(e.stopPropagation != null, 'has stop propagation')}); | ||
Syn.click(el); | ||
}); | ||
var el = document.getElementById('foo') | ||
bean.remove(el) | ||
bean.add(el, 'click', function (e) {ok(e.stopPropagation != null, 'has stop propagation')}) | ||
Syn.click(el) | ||
}) | ||
test('event: should have preventDefault method', 1, function () { | ||
var el = document.getElementById('foo'); | ||
bean.remove(el); | ||
bean.add(el, 'click', function (e) {ok(e.preventDefault != null, 'has prevent default method')}); | ||
Syn.click(el); | ||
}); | ||
var el = document.getElementById('foo') | ||
bean.remove(el) | ||
bean.add(el, 'click', function (e) {ok(e.preventDefault != null, 'has prevent default method')}) | ||
Syn.click(el) | ||
}) | ||
test('event: should have stop propagation method on custom event', 1, function () { | ||
var el = document.getElementById('foo'); | ||
bean.remove(el); | ||
bean.add(el, 'customEvent', function (e) {ok(e.stopPropagation != null, 'has stop propagation')}); | ||
bean.fire(el, 'customEvent'); | ||
}); | ||
var el = document.getElementById('foo') | ||
bean.remove(el) | ||
bean.add(el, 'customEvent', function (e) {ok(e.stopPropagation != null, 'has stop propagation')}) | ||
bean.fire(el, 'customEvent') | ||
}) | ||
test('event: should have preventDefault method on custom event', 1, function () { | ||
var el = document.getElementById('foo'); | ||
bean.remove(el); | ||
bean.add(el, 'customEvent', function (e) {ok(e.preventDefault != null, 'has prevent default method')}); | ||
bean.fire(el, 'customEvent'); | ||
}); | ||
var el = document.getElementById('foo') | ||
bean.remove(el) | ||
bean.add(el, 'customEvent', function (e) {ok(e.preventDefault != null, 'has prevent default method')}) | ||
bean.fire(el, 'customEvent') | ||
}) | ||
test('event: stop should preventDefault and stopPropagation', 1, function () { | ||
// first feature-test, if we don't support native createEvent then there's | ||
// no point running this test unfortunately | ||
var supported = false | ||
try { | ||
document.createEvent('KeyEvents') | ||
supported = true | ||
} catch (e) { | ||
try { | ||
document.createEvent('TextEvent') | ||
supported = true | ||
} catch (e) { } | ||
} | ||
if (!supported) { | ||
ok(true, 'not running test in this browser, native createEvent() not supported') | ||
return | ||
} | ||
if (features.createEvent) { | ||
test('event: stop should preventDefault and stopPropagation', 1, function () { | ||
// we should be able to prevent a keypress and event propagation with stop() | ||
// on the keypress event, checking the parent doesn't receive the keypress | ||
// and then checking the input contents on a keyup, it should be empty. | ||
var txt = document.getElementById('txt') | ||
, parent = document.getElementById('stopper') | ||
, txtHandler = function (event) { | ||
event.stop() | ||
} | ||
, txtCheckHandler = function (event) { | ||
ok(!txt.value.length, 'input is has no text after keypress') | ||
} | ||
, parentHandler = function (event) { | ||
ok(true, 'parent should not receive event') | ||
bean.remove(parent) | ||
} | ||
// we should be able to prevent a keypress and event propagation with stop() | ||
// on the keypress event, checking the parent doesn't receive the keypress | ||
// and then checking the input contents on a keyup, it should be empty. | ||
var txt = document.getElementById('txt') | ||
, parent = document.getElementById('stopper') | ||
, txtHandler = function (event) { | ||
event.stop() | ||
} | ||
, txtCheckHandler = function (event) { | ||
ok(!txt.value.length, 'input is has no text after keypress') | ||
} | ||
, parentHandler = function (event) { | ||
ok(true, 'parent should not receive event') | ||
bean.remove(parent) | ||
} | ||
txt.value = '' | ||
bean.add(txt, 'keypress', txtHandler) | ||
bean.add(txt, 'keyup', txtCheckHandler) | ||
bean.add(parent, 'keypress', parentHandler) | ||
Syn.key(txt, 'f') | ||
}) | ||
} | ||
txt.value = '' | ||
bean.add(txt, 'keypress', txtHandler) | ||
bean.add(txt, 'keyup', txtCheckHandler) | ||
bean.add(parent, 'keypress', parentHandler) | ||
Syn.key(txt, 'f') | ||
}) | ||
test('event: should have keyCode', 1, function () { | ||
var el = document.getElementById('input'); | ||
var el = document.getElementById('input') | ||
bean.add(el, 'keypress', function (e) { | ||
bean.remove(el); | ||
ok(e.keyCode != null, 'has keycode'); | ||
}); | ||
Syn.key(el, 'f'); | ||
}); | ||
bean.remove(el) | ||
ok(e.keyCode != null, 'has keycode') | ||
}) | ||
Syn.key(el, 'f') | ||
}) | ||
@@ -342,3 +357,4 @@ // the idea here is that we have a whitelist in bean.js for properties to copy over from the original | ||
, contains = function (arr, e) { | ||
for (var i = arr.length; i--;) { | ||
var i = arr.length | ||
while (i--) { | ||
if (arr[i] === e) return true | ||
@@ -351,24 +367,24 @@ } | ||
var p, orig = event.originalEvent | ||
for (var p in orig) { | ||
if ( | ||
!event.hasOwnProperty(p) | ||
for (p in orig) { | ||
if ( !event.hasOwnProperty(p) | ||
&& !contains(ignorables, p) | ||
&& !/^[A-Z_\d]+$/.test(p) // STUFF_LIKE_THIS | ||
&& !/^moz[A-Z]/.test(p) // Mozilla prefixed properties | ||
) | ||
) { | ||
ok(true, 'additional, uncopied property: "' + p + '"') | ||
} | ||
} | ||
} | ||
var testMouseEvent = function (type, syn) { | ||
getEventObject( | ||
type | ||
, 'button' | ||
, function (el) { Syn[syn || type](el) } | ||
, function (event) { | ||
ok(!!event && !!event.originalEvent && event.type === type, 'got event object') | ||
verifyEventObject(event, clickIgnorables) | ||
} | ||
) | ||
} | ||
, testMouseEvent = function (type, syn) { | ||
getEventObject( | ||
type | ||
, 'button' | ||
, function (el) { Syn[syn || type](el) } | ||
, function (event) { | ||
ok(!!event && !!event.originalEvent && event.type === type, 'got event object') | ||
verifyEventObject(event, clickIgnorables) | ||
} | ||
) | ||
} | ||
@@ -401,21 +417,22 @@ test('click: has correct properties', 1, function () { testMouseEvent('click') }) | ||
test('remove: should return the element passed in', 1, function () { | ||
var el = document.getElementById('foo'); | ||
bean.remove(el); | ||
var handler = function () {}; | ||
bean.add(el, 'click', handler); | ||
var returned = bean.remove(el, 'click', handler); | ||
ok(el == returned, 'returns the element passed in'); | ||
}); | ||
var el = document.getElementById('foo') | ||
, handler = function () {} | ||
, returned | ||
bean.remove(el) | ||
bean.add(el, 'click', handler) | ||
returned = bean.remove(el, 'click', handler) | ||
ok(el == returned, 'returns the element passed in') | ||
}) | ||
test('remove: should be able to remove a single event', 1, function () { | ||
var el = document.getElementById('foo'); | ||
bean.remove(el); | ||
var handler = function () { | ||
ok(true, 'remove a single event'); | ||
bean.remove(el, 'click', handler); | ||
Syn.click(el); | ||
} | ||
bean.add(el, 'click', handler); | ||
var el = document.getElementById('foo') | ||
, handler = function () { | ||
ok(true, 'remove a single event') | ||
bean.remove(el, 'click', handler) | ||
Syn.click(el) | ||
} | ||
bean.remove(el) | ||
bean.add(el, 'click', handler) | ||
Syn.click(el) | ||
}); | ||
}) | ||
@@ -443,50 +460,50 @@ test('remove: should be able to remove mulitple events with an object literal', 2, function () { | ||
Syn.click(el) | ||
}); | ||
}) | ||
test('remove: should be able to remove all events of a specific type', 2, function () { | ||
var el = document.getElementById('input'); | ||
bean.remove(el); | ||
var handler1 = function () { | ||
ok(true, 'removes all events of a specific type 1'); | ||
}, | ||
handler2 = function () { | ||
ok(true, 'removes all events of a specific type 2'); | ||
bean.remove(el, 'click'); | ||
Syn.click(el); | ||
}; | ||
bean.add(el, 'click', handler1); | ||
bean.add(el, 'click', handler2); | ||
Syn.click(el); | ||
}); | ||
var el = document.getElementById('input') | ||
, handler1 = function () { | ||
ok(true, 'removes all events of a specific type 1') | ||
} | ||
, handler2 = function () { | ||
ok(true, 'removes all events of a specific type 2') | ||
bean.remove(el, 'click') | ||
Syn.click(el) | ||
} | ||
bean.remove(el) | ||
bean.add(el, 'click', handler1) | ||
bean.add(el, 'click', handler2) | ||
Syn.click(el) | ||
}) | ||
test('remove: should be able to remove all events of a specific type', 2, function () { | ||
var el = document.getElementById('input'); | ||
bean.remove(el); | ||
var handler1 = function () { | ||
ok(true, 'removes all events of a specific type 1'); | ||
}, | ||
handler2 = function () { | ||
ok(true, 'remove all events of a specific type 2'); | ||
bean.remove(el, 'mousedown mouseup'); | ||
Syn.click(el); | ||
}; | ||
bean.add(el, 'mousedown', handler1); | ||
bean.add(el, 'mouseup', handler2); | ||
Syn.click(el); | ||
}); | ||
var el = document.getElementById('input') | ||
, handler1 = function () { | ||
ok(true, 'removes all events of a specific type 1') | ||
} | ||
, handler2 = function () { | ||
ok(true, 'remove all events of a specific type 2') | ||
bean.remove(el, 'mousedown mouseup') | ||
Syn.click(el) | ||
} | ||
bean.remove(el) | ||
bean.add(el, 'mousedown', handler1) | ||
bean.add(el, 'mouseup', handler2) | ||
Syn.click(el) | ||
}) | ||
test('remove: should be able to remove all events', 1, function () { | ||
var el = document.getElementById('input'), | ||
handler1 = function () { | ||
ok(true, 'remove all events 1'); | ||
bean.remove(el); | ||
Syn.click(el).key('j'); | ||
}, | ||
handler2 = function () { | ||
ok(true, 'remove all events 2'); | ||
}; | ||
bean.add(el, 'click', handler1); | ||
bean.add(el, 'keydown', handler2); | ||
Syn.click(el); | ||
}); | ||
var el = document.getElementById('input') | ||
, handler1 = function () { | ||
ok(true, 'remove all events 1') | ||
bean.remove(el) | ||
Syn.click(el).key('j') | ||
} | ||
, handler2 = function () { | ||
ok(true, 'remove all events 2') | ||
} | ||
bean.add(el, 'click', handler1) | ||
bean.add(el, 'keydown', handler2) | ||
Syn.click(el) | ||
}) | ||
@@ -523,3 +540,3 @@ test('remove: should only remove events of specified type', 4, function () { | ||
ok(true, 'handled ' + e.type + ' event (2)') | ||
++c == 2 && bean.remove(el) | ||
if (++c == 2) bean.remove(el) | ||
} | ||
@@ -560,37 +577,36 @@ | ||
sink('clone', function (test, ok, before, after) { | ||
var el1 = document.getElementById('input') | ||
, el2 = document.getElementById('input2') | ||
var el1 = document.getElementById('input'); | ||
var el2 = document.getElementById('input2'); | ||
before(function () { | ||
bean.remove(el1); | ||
bean.remove(el2); | ||
bean.remove(el1) | ||
bean.remove(el2) | ||
}) | ||
after(function () { | ||
bean.remove(el1); | ||
bean.remove(el2); | ||
bean.remove(el1) | ||
bean.remove(el2) | ||
}) | ||
test('clone: should be able to clone events of a specific type from one element to another', 2, function () { | ||
bean.add(el2, 'click', function () {ok(true, 'clones events of a specific type from one element to another 1')}); | ||
bean.add(el2, 'click', function () {ok(true, 'clones events of a specific type from one element to another 1')}) | ||
bean.add(el2, 'click', function () { | ||
ok(true, 'clone events of a specific type from one element to another 2'); | ||
bean.remove(el1); | ||
}); | ||
ok(true, 'clone events of a specific type from one element to another 2') | ||
bean.remove(el1) | ||
}) | ||
bean.add(el2, 'keydown', function () { | ||
ok(true, 'clone events of a specific type from one element to another 3'); | ||
bean.remove(el1); | ||
}); | ||
bean.clone(el1, el2, 'click'); | ||
Syn.click(el1).key('j'); | ||
}); | ||
ok(true, 'clone events of a specific type from one element to another 3') | ||
bean.remove(el1) | ||
}) | ||
bean.clone(el1, el2, 'click') | ||
Syn.click(el1).key('j') | ||
}) | ||
test('clone: should be able to clone all events from one element to another', 3, function () { | ||
bean.add(el2, 'keypress', function () {ok(true, 'clones all events from one element to another 1');}); | ||
bean.add(el2, 'click', function () {ok(true, 'clones all events from one element to another 2');}); | ||
bean.add(el2, 'click', function () {ok(true, 'clonesall events from one element to another 3');}); | ||
bean.clone(el1, el2); | ||
Syn.click(el1).key('j'); | ||
}); | ||
bean.add(el2, 'keypress', function () {ok(true, 'clones all events from one element to another 1')}) | ||
bean.add(el2, 'click', function () {ok(true, 'clones all events from one element to another 2')}) | ||
bean.add(el2, 'click', function () {ok(true, 'clonesall events from one element to another 3')}) | ||
bean.clone(el1, el2) | ||
Syn.click(el1).key('j') | ||
}) | ||
@@ -603,3 +619,3 @@ test('clone: should firere cloned event in scope of new element', 1, function () { | ||
Syn.click(el2) | ||
}); | ||
}) | ||
@@ -622,6 +638,6 @@ test('clone: should work with delegated events', 3, function () { | ||
bean.clone(realfoo, foo); | ||
bean.clone(realfoo, foo) | ||
Syn.click(bang); | ||
}); | ||
Syn.click(bang) | ||
}) | ||
}) | ||
@@ -632,49 +648,115 @@ | ||
test('delegate: should be able to delegate on selectors', 6, function () { | ||
var el1 = document.getElementById('foo'); | ||
var el2 = document.getElementById('bar'); | ||
var el3 = document.getElementById('baz'); | ||
var el4 = document.getElementById('bang'); | ||
bean.remove(el1); | ||
bean.remove(el2); | ||
bean.remove(el3); | ||
var el1 = document.getElementById('foo') | ||
, el2 = document.getElementById('bar') | ||
, el3 = document.getElementById('baz') | ||
, el4 = document.getElementById('bang') | ||
bean.remove(el1) | ||
bean.remove(el2) | ||
bean.remove(el3) | ||
bean.add(el1, '.bar', 'click', function (e) { | ||
ok(true, 'delegation on selectors 1'); | ||
ok(this == el2, 'delegation on selectors, context was set to delegated element 2'); | ||
ok(true, 'delegation on selectors 1') | ||
ok(this == el2, 'delegation on selectors, context was set to delegated element 2') | ||
ok(e.currentTarget === el2, 'degated event has currentTarget property correctly set') | ||
}, qwery); | ||
Syn.click(el2); | ||
Syn.click(el3); | ||
Syn.click(el4); | ||
}); | ||
}, qwery) | ||
Syn.click(el2) | ||
Syn.click(el3) | ||
Syn.click(el4) | ||
}) | ||
test('delegate: should be able to delegate on arary', 4, function () { | ||
var el1 = document.getElementById('foo'); | ||
var el2 = document.getElementById('bar'); | ||
var el3 = document.getElementById('baz'); | ||
var el4 = document.getElementById('bang'); | ||
bean.remove(el1); | ||
bean.remove(el2); | ||
bean.remove(el3); | ||
var el1 = document.getElementById('foo') | ||
, el2 = document.getElementById('bar') | ||
, el3 = document.getElementById('baz') | ||
, el4 = document.getElementById('bang') | ||
bean.remove(el1) | ||
bean.remove(el2) | ||
bean.remove(el3) | ||
bean.add(el1, [el2], 'click', function () { | ||
ok(true, 'delegation on arary 1'); | ||
ok(this == el2, 'delegation on arary, context was set to delegated element 1'); | ||
}, qwery); | ||
Syn.click(el2); | ||
Syn.click(el3); | ||
Syn.click(el4); | ||
}); | ||
ok(true, 'delegation on arary 1') | ||
ok(this == el2, 'delegation on arary, context was set to delegated element 1') | ||
}, qwery) | ||
Syn.click(el2) | ||
Syn.click(el3) | ||
Syn.click(el4) | ||
}) | ||
test('delegate: should be able to remove delegated handler', 1, function () { | ||
var el1 = document.getElementById('foo'); | ||
var el2 = document.getElementById('bar'); | ||
bean.remove(el1); | ||
bean.remove(el2); | ||
var fn = function () { | ||
ok(true, 'degegated event triggered once'); | ||
bean.remove(el1, 'click', fn); | ||
} | ||
bean.add(el1, '.bar', 'click', fn, qwery); | ||
Syn.click(el2); | ||
Syn.click(el2); | ||
}); | ||
var el1 = document.getElementById('foo') | ||
, el2 = document.getElementById('bar') | ||
, fn = function () { | ||
ok(true, 'degegated event triggered once') | ||
bean.remove(el1, 'click', fn) | ||
} | ||
bean.remove(el1) | ||
bean.remove(el2) | ||
bean.add(el1, '.bar', 'click', fn, qwery) | ||
Syn.click(el2) | ||
Syn.click(el2) | ||
}) | ||
if (features.qSA) { | ||
test('delegate: should use qSA if available', 6, function () { | ||
var el1 = document.getElementById('foo') | ||
, el2 = document.getElementById('bar') | ||
, el3 = document.getElementById('baz') | ||
, el4 = document.getElementById('bang') | ||
bean.remove(el1) | ||
bean.remove(el2) | ||
bean.remove(el3) | ||
bean.add(el1, '.bar', 'click', function (e) { | ||
ok(true, 'delegation on selectors 1') | ||
ok(this == el2, 'delegation on selectors, context was set to delegated element 2') | ||
ok(e.currentTarget === el2, 'degated event has currentTarget property correctly set') | ||
}) | ||
Syn.click(el2) | ||
Syn.click(el3) | ||
Syn.click(el4) | ||
}) | ||
} else { | ||
test('delegate: should throw error when no qSA available and no selector engine set', 1, function () { | ||
var el1 = document.getElementById('foo') | ||
, el2 = document.getElementById('bar') | ||
bean.remove(el1) | ||
bean.remove(el2) | ||
bean.add(el1, '.bar', 'click', function (e) { | ||
ok(false, 'don\'t fire delegated event without selector engine or qSA') | ||
}) | ||
window.onerror = function (e) { | ||
ok(/Bean/.test(e.toString()), 'threw Error on delegated event trigger without selector engine or qSA') | ||
window.onerror = null | ||
} | ||
Syn.click(el2) | ||
}) | ||
} | ||
test('delegate: should be able to set a default selector engine', 3 * 2 + 2 * 6, function () { | ||
var el1 = document.getElementById('foo') | ||
, el2 = document.getElementById('bar') | ||
, el3 = document.getElementById('baz') | ||
, el4 = document.getElementById('bang') | ||
, selector = "SELECTOR? WE DON'T NEED NO STINKIN' SELECTOR!" | ||
// 2 assertions, expect them twice per click = 6 | ||
// TODO: findTarget() is called for setting event.currentTarget as well as checking for a match | ||
// fix this so it's only called once, otherwise it's a waste | ||
bean.setSelectorEngine(function (s, r) { | ||
ok(s === selector, 'selector engine passed correct selector string') | ||
ok(r === el1, 'selector engine passed correct root') | ||
return [ el2 ] | ||
}) | ||
bean.remove(el1) | ||
bean.remove(el2) | ||
bean.remove(el3) | ||
// 3 assertions, expect them twice | ||
bean.add(el1, selector, 'click', function (e) { | ||
ok(true, 'delegation on selectors 1') | ||
ok(this == el2, 'delegation on selectors, context was set to delegated element 2') | ||
ok(e.currentTarget === el2, 'degated event has currentTarget property correctly set') | ||
}) | ||
Syn.click(el2) | ||
Syn.click(el3) | ||
Syn.click(el4) | ||
}) | ||
}) | ||
@@ -685,65 +767,64 @@ | ||
test('namespace: should be able to name handlers', 1, function () { | ||
var el1 = document.getElementById('foo'); | ||
bean.remove(el1); | ||
bean.add(el1, 'click.fat', function () {ok(true, 'bubbles up dom')}); | ||
Syn.click(el1); | ||
}); | ||
var el1 = document.getElementById('foo') | ||
bean.remove(el1) | ||
bean.add(el1, 'click.fat', function () {ok(true, 'bubbles up dom')}) | ||
Syn.click(el1) | ||
}) | ||
test('namespace: should be able to add multiple handlers under the same namespace to the same element', 2, function () { | ||
var el1 = document.getElementById('foo'); | ||
bean.remove(el1); | ||
bean.add(el1, 'click.fat', function () {ok(true, 'bubbles up dom')}); | ||
bean.add(el1, 'click.fat', function () {ok(true, 'bubbles up dom')}); | ||
Syn.click(el1); | ||
}); | ||
var el1 = document.getElementById('foo') | ||
bean.remove(el1) | ||
bean.add(el1, 'click.fat', function () {ok(true, 'bubbles up dom')}) | ||
bean.add(el1, 'click.fat', function () {ok(true, 'bubbles up dom')}) | ||
Syn.click(el1) | ||
}) | ||
test('namespace: should be able to fire an event without handlers', 1, function () { | ||
var el1 = document.getElementById('foo'), succ; | ||
bean.remove(el1); | ||
var el1 = document.getElementById('foo'), succ = true | ||
bean.remove(el1) | ||
try { | ||
bean.fire(el1, 'click.fat'); | ||
succ = true; | ||
bean.fire(el1, 'click.fat') | ||
} catch (exc) { | ||
succ = false; | ||
succ = false | ||
} | ||
ok(succ, 'fire namespaced event with no handlers'); | ||
}); | ||
ok(succ, 'fire namespaced event with no handlers') | ||
}) | ||
test('namespace: should be able to target namespaced event handlers with fire', 1, function () { | ||
var el1 = document.getElementById('foo'); | ||
bean.remove(el1); | ||
bean.add(el1, 'click.fat', function () {ok(true, 'targets namespaced event handlers with fire (namespaced)')}); | ||
bean.add(el1, 'click', function () {ok(true, 'targets namespaced event handlers with fire (plain)')}); | ||
bean.fire(el1, 'click.fat'); | ||
}); | ||
var el1 = document.getElementById('foo') | ||
bean.remove(el1) | ||
bean.add(el1, 'click.fat', function () {ok(true, 'targets namespaced event handlers with fire (namespaced)')}) | ||
bean.add(el1, 'click', function () {ok(true, 'targets namespaced event handlers with fire (plain)')}) | ||
bean.fire(el1, 'click.fat') | ||
}) | ||
test('namespace: should be able to target multiple namespaced event handlers with fire', 2, function () { | ||
var el1 = document.getElementById('foo'); | ||
bean.remove(el1); | ||
bean.add(el1, 'click.fat', function () {ok(true, 'target multiple namespaced event handlers with fire')}); | ||
bean.add(el1, 'click.ded', function () {ok(true, 'targets multiple namespaced event handlers with fire')}); | ||
bean.add(el1, 'click', function () {ok(true, 'targets multiple namespaced event handlers with fire')}); | ||
bean.fire(el1, 'click.fat.ded'); | ||
}); | ||
var el1 = document.getElementById('foo') | ||
bean.remove(el1) | ||
bean.add(el1, 'click.fat', function () {ok(true, 'target multiple namespaced event handlers with fire')}) | ||
bean.add(el1, 'click.ded', function () {ok(true, 'targets multiple namespaced event handlers with fire')}) | ||
bean.add(el1, 'click', function () {ok(true, 'targets multiple namespaced event handlers with fire')}) | ||
bean.fire(el1, 'click.fat.ded') | ||
}) | ||
test('namespace: should be able to remove handlers based on name', 1, function () { | ||
var el1 = document.getElementById('foo'); | ||
bean.remove(el1); | ||
bean.add(el1, 'click.ded', function () {ok(true, 'removes handlers based on name')}); | ||
bean.add(el1, 'click', function () {ok(true, 'removes handlers based on name')}); | ||
bean.remove(el1, 'click.ded'); | ||
Syn.click(el1); | ||
}); | ||
var el1 = document.getElementById('foo') | ||
bean.remove(el1) | ||
bean.add(el1, 'click.ded', function () {ok(true, 'removes handlers based on name')}) | ||
bean.add(el1, 'click', function () {ok(true, 'removes handlers based on name')}) | ||
bean.remove(el1, 'click.ded') | ||
Syn.click(el1) | ||
}) | ||
test('namespace: should be able to remove multiple handlers based on name', 1, function () { | ||
var el1 = document.getElementById('foo'); | ||
bean.remove(el1); | ||
bean.add(el1, 'click.fat', function () {ok(true, 'removes multiple handlers based on name')}); | ||
bean.add(el1, 'click.ded', function () {ok(true, 'removes multiple handlers based on name')}); | ||
bean.add(el1, 'click', function () {ok(true, 'removes multiple handlers based on name')}); | ||
bean.remove(el1, 'click.ded.fat'); | ||
Syn.click(el1); | ||
}); | ||
var el1 = document.getElementById('foo') | ||
bean.remove(el1) | ||
bean.add(el1, 'click.fat', function () {ok(true, 'removes multiple handlers based on name')}) | ||
bean.add(el1, 'click.ded', function () {ok(true, 'removes multiple handlers based on name')}) | ||
bean.add(el1, 'click', function () {ok(true, 'removes multiple handlers based on name')}) | ||
bean.remove(el1, 'click.ded.fat') | ||
Syn.click(el1) | ||
}) | ||
}); | ||
}) | ||
@@ -750,0 +831,0 @@ sink('custom types', function (test, ok) { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
1
302
2
293640
18
6421