Browse files

fix multi namespaced events for backbone views

  • Loading branch information...
1 parent c325113 commit 1ea0de773dbb5139b6d6fc67fec371bc56054920 @fat committed Aug 25, 2011
Showing with 52 additions and 30 deletions.
  1. +21 −14 bean.js
  2. +1 −1 bean.min.js
  3. +1 −1 make/build.js
  4. +21 −14 src/bean.js
  5. +8 −0 tests/tests.js
View
35 bean.js
@@ -8,7 +8,9 @@
* the entire mootools team: github.com/mootools/mootools-core
*/
!function (context) {
- var __uid = 1, registry = {}, collected = {},
+ var __uid = 1,
+ registry = {},
+ collected = {},
overOut = /over|out/,
namespace = /[^\.]*(?=\..*)\.|.*/,
stripName = /\..*/,
@@ -32,7 +34,7 @@
},
retrieveUid = function (obj, uid) {
- return (obj.__uid = uid || obj.__uid || __uid++);
+ return (obj.__uid = uid && (uid + '::' + __uid++) || obj.__uid || __uid++);
},
retrieveEvents = function (element) {
@@ -102,7 +104,9 @@
function destroyHandler(uid) {
handler = events[type][uid];
- if (!handler) return;
+ if (!handler) {
+ return;
+ }
delete events[type][uid];
if (element[eventSupport]) {
type = customEvents[type] ? customEvents[type].base : type;
@@ -111,8 +115,8 @@
}
}
- destroyHandler(names) //get combos
- for (i = uids.length; i--; destroyHandler(uids[i])); //get singles
+ destroyHandler(names); //get combos
+ for (i = uids.length; i--; destroyHandler(uids[i])) {} //get singles
return element;
},
@@ -146,9 +150,10 @@
},
remove = function (element, orgEvents, fn) {
- var k, type, events, i,
+ var k, m, type, events, i,
isString = typeof(orgEvents) == 'string',
names = isString && orgEvents.replace(namespace, ''),
+ names = names && names.split('.'),
rm = removeListener,
attached = retrieveEvents(element);
if (isString && /\s/.test(orgEvents)) {
@@ -158,12 +163,12 @@
return element;
}
events = isString ? orgEvents.replace(stripName, '') : orgEvents;
- if (!attached || (isString && !attached[events])) {
- if (attached && names) {
- for (k in attached) {
- if (attached.hasOwnProperty(k)) {
- for (i in attached[k]) {
- attached[k].hasOwnProperty(i) && new RegExp('^' + names + '(\\..*)?$').test(i) && rm(element, [k, i].join('.'));
+ if (!attached || names || (isString && !attached[events])) {
+ for (k in attached) {
+ if (attached.hasOwnProperty(k)) {
+ for (i in attached[k]) {
+ for (m = names.length; m--;) {
+ attached[k].hasOwnProperty(i) && new RegExp('^' + names[m] + '::\\d*(\\..*)?$').test(i) && rm(element, [k, i].join('.'));
}
}
}
@@ -189,7 +194,7 @@
},
fire = function (element, type, args) {
- var evt, k, i, types = type.split(' ');
+ var evt, k, i, m, types = type.split(' ');
for (i = types.length; i--;) {
type = types[i].replace(stripName, '');
var isNative = nativeEvents[type],
@@ -198,7 +203,9 @@
if (isNamespace) {
isNamespace = isNamespace.split('.');
for (k = isNamespace.length; k--;) {
- handlers && handlers[isNamespace[k]] && handlers[isNamespace[k]].apply(element, [false].concat(args));
+ for (m in handlers) {
+ handlers.hasOwnProperty(m) && new RegExp('^' + isNamespace[k] + '::\\d*(\\..*)?$').test(m) && handlers[m].apply(element, [false].concat(args));
+ }
}
} else if (!args && element[eventSupport]) {
fireListener(isNative, type, element);
View
2 bean.min.js
@@ -7,4 +7,4 @@
* dperini: https://github.com/dperini/nwevents
* the entire mootools team: github.com/mootools/mootools-core
*/
-!function(a){function F(a){var b=a.relatedTarget;return b?b!=this&&b.prefix!="xul"&&!/document/.test(this.toString())&&!p(this,b):b===null}var b=1,c={},d={},e=/over|out/,f=/[^\.]*(?=\..*)\.|.*/,g=/\..*/,h="addEventListener",i="attachEvent",j="removeEventListener",k="detachEvent",l=a.document||{},m=l.documentElement||{},n=m[h],o=n?h:i,p=function(a,b){var c=b.parentNode;while(c!==null){if(c==a)return!0;c=c.parentNode}},q=function(a,c){return a.__uid=c||a.__uid||b++},r=function(a){var b=q(a);return c[b]=c[b]||{}},s=n?function(a,b,c,d){a[d?h:j](b,c,!1)}:function(a,b,c,d,e){e&&d&&(a["_on"+e]=a["_on"+e]||0),a[d?i:k]("on"+b,c)},t=function(b,c,d){return function(e){e=D(e||((this.ownerDocument||this.document||this).parentWindow||a).event);return c.apply(b,[e].concat(d))}},u=function(a,b,c,d,e){return function(f){(d?d.apply(this,arguments):n?!0:f&&f.propertyName=="_on"+c||!f)&&b.apply(a,Array.prototype.slice.call(arguments,f?0:1).concat(e))}},v=function(a,b,c,e){var h=b.replace(g,""),i=r(a),j=i[h]||(i[h]={}),k=c,l=q(c,b.replace(f,""));if(j[l])return a;var m=G[h];m&&(c=m.condition?u(a,c,h,m.condition):c,h=m.base||h);var p=E[h];c=p?t(a,c,e):u(a,c,h,!1,e),p=n||p;if(h=="unload"){var v=c;c=function(){w(a,h,c)&&v()}}a[o]&&s(a,p?h:"propertychange",c,!0,!p&&h),j[l]=c,c.__uid=l,c.__originalFn=k;return h=="unload"?a:d[q(a)]=a},w=function(a,b,c){function l(b){c=j[k][b];if(!!c){delete j[k][b];if(a[o]){k=G[k]?G[k].base:k;var d=n||E[k];s(a,d?k:"propertychange",c,!1,!d&&k)}}}var d,e,h,i,j=r(a),k=b.replace(g,"");if(!j||!j[k])return a;e=b.replace(f,""),h=e?e.split("."):[c.__uid],l(e);for(i=h.length;i--;l(h[i]));return a},x=function(a,b,c){return function(d){var e=typeof a=="string"?c(a,this):a;for(var f=d.target;f&&f!=this;f=f.parentNode)for(var g=e.length;g--;)if(e[g]==f)return b.apply(f,arguments)}},y=function(a,b,c,d,e){if(typeof b=="object"&&!c)for(var f in b)b.hasOwnProperty(f)&&y(a,f,b[f]);else{var g=typeof c=="string",h=(g?c:b).split(" ");c=g?x(b,d,e):c;for(var i=h.length;i--;)v(a,h[i],c,Array.prototype.slice.call(arguments,g?4:3))}return a},z=function(a,b,c){var d,e,h,i,j=typeof b=="string",k=j&&b.replace(f,""),l=w,m=r(a);if(j&&/\s/.test(b)){b=b.split(" "),i=b.length-1;while(z(a,b[i])&&i--);return a}h=j?b.replace(g,""):b;if(!m||j&&!m[h]){if(m&&k)for(d in m)if(m.hasOwnProperty(d))for(i in m[d])m[d].hasOwnProperty(i)&&(new RegExp("^"+k+"(\\..*)?$")).test(i)&&l(a,[d,i].join("."));return a}if(typeof c=="function")l(a,h,c);else if(k)l(a,b);else{l=h?l:z,e=j&&h,h=h?c||m[h]||h:m;for(d in h)h.hasOwnProperty(d)&&(l(a,e||d,h[d]),delete h[d])}return a},A=function(a,b,c){var d,e,h,i=b.split(" ");for(h=i.length;h--;){b=i[h].replace(g,"");var j=E[b],k=i[h].replace(f,""),l=r(a)[b];if(k){k=k.split(".");for(e=k.length;e--;)l&&l[k[e]]&&l[k[e]].apply(a,[!1].concat(c))}else if(!c&&a[o])B(j,b,a);else for(e in l)l.hasOwnProperty(e)&&l[e].apply(a,[!1].concat(c))}return a},B=n?function(b,c,d){evt=document.createEvent(b?"HTMLEvents":"UIEvents"),evt[b?"initEvent":"initUIEvent"](c,!0,!0,a,1),d.dispatchEvent(evt)}:function(a,b,c){a?c.fireEvent("on"+b,document.createEventObject()):c["_on"+b]++},C=function(a,b,c){var d=r(b),e,f,g=q(a);e=c?d[c]:d;for(f in e)e.hasOwnProperty(f)&&(c?y:C)(a,c||b,c?e[f].__originalFn:f);return a},D=function(a){var b={};if(!a)return b;var c=a.type,d=a.target||a.srcElement;b.preventDefault=D.preventDefault(a),b.stopPropagation=D.stopPropagation(a),b.target=d&&d.nodeType==3?d.parentNode:d;if(~c.indexOf("key"))b.keyCode=a.which||a.keyCode;else if(/click|mouse|menu/i.test(c)){b.rightClick=a.which==3||a.button==2,b.pos={x:0,y:0};if(a.pageX||a.pageY)b.clientX=a.pageX,b.clientY=a.pageY;else if(a.clientX||a.clientY)b.clientX=a.clientX+document.body.scrollLeft+document.documentElement.scrollLeft,b.clientY=a.clientY+document.body.scrollTop+document.documentElement.scrollTop;e.test(c)&&(b.relatedTarget=a.relatedTarget||a[(c=="mouseover"?"from":"to")+"Element"])}for(var f in a)f in b||(b[f]=a[f]);return b};D.preventDefault=function(a){return function(){a.preventDefault?a.preventDefault():a.returnValue=!1}},D.stopPropagation=function(a){return function(){a.stopPropagation?a.stopPropagation():a.cancelBubble=!0}};var E={click:1,dblclick:1,mouseup:1,mousedown:1,contextmenu:1,mousewheel:1,DOMMouseScroll:1,mouseover:1,mouseout:1,mousemove:1,selectstart:1,selectend:1,keydown:1,keypress:1,keyup:1,orientationchange:1,touchstart:1,touchmove:1,touchend:1,touchcancel:1,gesturestart:1,gesturechange:1,gestureend:1,focus:1,blur:1,change:1,reset:1,select:1,submit:1,load:1,unload:1,beforeunload:1,resize:1,move:1,DOMContentLoaded:1,readystatechange:1,error:1,abort:1,scroll:1},G={mouseenter:{base:"mouseover",condition:F},mouseleave:{base:"mouseout",condition:F},mousewheel:{base:/Firefox/.test(navigator.userAgent)?"DOMMouseScroll":"mousewheel"}},H={add:y,remove:z,clone:C,fire:A},I=function(a){var b=z(a).__uid;b&&(delete d[b],delete c[b])};a[i]&&y(a,"unload",function(){for(var b in d)d.hasOwnProperty(b)&&I(d[b]);a.CollectGarbage&&CollectGarbage()});var J=a.bean;H.noConflict=function(){a.bean=J;return this},typeof module!="undefined"&&module.exports?module.exports=H:a.bean=H}(this)
+!function(a){function F(a){var b=a.relatedTarget;return b?b!=this&&b.prefix!="xul"&&!/document/.test(this.toString())&&!p(this,b):b===null}var b=1,c={},d={},e=/over|out/,f=/[^\.]*(?=\..*)\.|.*/,g=/\..*/,h="addEventListener",i="attachEvent",j="removeEventListener",k="detachEvent",l=a.document||{},m=l.documentElement||{},n=m[h],o=n?h:i,p=function(a,b){var c=b.parentNode;while(c!==null){if(c==a)return!0;c=c.parentNode}},q=function(a,c){return a.__uid=c&&c+"::"+b++||a.__uid||b++},r=function(a){var b=q(a);return c[b]=c[b]||{}},s=n?function(a,b,c,d){a[d?h:j](b,c,!1)}:function(a,b,c,d,e){e&&d&&(a["_on"+e]=a["_on"+e]||0),a[d?i:k]("on"+b,c)},t=function(b,c,d){return function(e){e=D(e||((this.ownerDocument||this.document||this).parentWindow||a).event);return c.apply(b,[e].concat(d))}},u=function(a,b,c,d,e){return function(f){(d?d.apply(this,arguments):n?!0:f&&f.propertyName=="_on"+c||!f)&&b.apply(a,Array.prototype.slice.call(arguments,f?0:1).concat(e))}},v=function(a,b,c,e){var h=b.replace(g,""),i=r(a),j=i[h]||(i[h]={}),k=c,l=q(c,b.replace(f,""));if(j[l])return a;var m=G[h];m&&(c=m.condition?u(a,c,h,m.condition):c,h=m.base||h);var p=E[h];c=p?t(a,c,e):u(a,c,h,!1,e),p=n||p;if(h=="unload"){var v=c;c=function(){w(a,h,c)&&v()}}a[o]&&s(a,p?h:"propertychange",c,!0,!p&&h),j[l]=c,c.__uid=l,c.__originalFn=k;return h=="unload"?a:d[q(a)]=a},w=function(a,b,c){function l(b){c=j[k][b];if(!!c){delete j[k][b];if(a[o]){k=G[k]?G[k].base:k;var d=n||E[k];s(a,d?k:"propertychange",c,!1,!d&&k)}}}var d,e,h,i,j=r(a),k=b.replace(g,"");if(!j||!j[k])return a;e=b.replace(f,""),h=e?e.split("."):[c.__uid],l(e);for(i=h.length;i--;l(h[i]));return a},x=function(a,b,c){return function(d){var e=typeof a=="string"?c(a,this):a;for(var f=d.target;f&&f!=this;f=f.parentNode)for(var g=e.length;g--;)if(e[g]==f)return b.apply(f,arguments)}},y=function(a,b,c,d,e){if(typeof b=="object"&&!c)for(var f in b)b.hasOwnProperty(f)&&y(a,f,b[f]);else{var g=typeof c=="string",h=(g?c:b).split(" ");c=g?x(b,d,e):c;for(var i=h.length;i--;)v(a,h[i],c,Array.prototype.slice.call(arguments,g?4:3))}return a},z=function(a,b,c){var d,e,h,i,j,k=typeof b=="string",l=k&&b.replace(f,""),l=l&&l.split("."),m=w,n=r(a);if(k&&/\s/.test(b)){b=b.split(" "),j=b.length-1;while(z(a,b[j])&&j--);return a}i=k?b.replace(g,""):b;if(!n||l||k&&!n[i]){for(d in n)if(n.hasOwnProperty(d))for(j in n[d])for(e=l.length;e--;)n[d].hasOwnProperty(j)&&(new RegExp("^"+l[e]+"::\\d*(\\..*)?$")).test(j)&&m(a,[d,j].join("."));return a}if(typeof c=="function")m(a,i,c);else if(l)m(a,b);else{m=i?m:z,h=k&&i,i=i?c||n[i]||i:n;for(d in i)i.hasOwnProperty(d)&&(m(a,h||d,i[d]),delete i[d])}return a},A=function(a,b,c){var d,e,h,i,j=b.split(" ");for(h=j.length;h--;){b=j[h].replace(g,"");var k=E[b],l=j[h].replace(f,""),m=r(a)[b];if(l){l=l.split(".");for(e=l.length;e--;)for(i in m)m.hasOwnProperty(i)&&(new RegExp("^"+l[e]+"::\\d*(\\..*)?$")).test(i)&&m[i].apply(a,[!1].concat(c))}else if(!c&&a[o])B(k,b,a);else for(e in m)m.hasOwnProperty(e)&&m[e].apply(a,[!1].concat(c))}return a},B=n?function(b,c,d){evt=document.createEvent(b?"HTMLEvents":"UIEvents"),evt[b?"initEvent":"initUIEvent"](c,!0,!0,a,1),d.dispatchEvent(evt)}:function(a,b,c){a?c.fireEvent("on"+b,document.createEventObject()):c["_on"+b]++},C=function(a,b,c){var d=r(b),e,f,g=q(a);e=c?d[c]:d;for(f in e)e.hasOwnProperty(f)&&(c?y:C)(a,c||b,c?e[f].__originalFn:f);return a},D=function(a){var b={};if(!a)return b;var c=a.type,d=a.target||a.srcElement;b.preventDefault=D.preventDefault(a),b.stopPropagation=D.stopPropagation(a),b.target=d&&d.nodeType==3?d.parentNode:d;if(~c.indexOf("key"))b.keyCode=a.which||a.keyCode;else if(/click|mouse|menu/i.test(c)){b.rightClick=a.which==3||a.button==2,b.pos={x:0,y:0};if(a.pageX||a.pageY)b.clientX=a.pageX,b.clientY=a.pageY;else if(a.clientX||a.clientY)b.clientX=a.clientX+document.body.scrollLeft+document.documentElement.scrollLeft,b.clientY=a.clientY+document.body.scrollTop+document.documentElement.scrollTop;e.test(c)&&(b.relatedTarget=a.relatedTarget||a[(c=="mouseover"?"from":"to")+"Element"])}for(var f in a)f in b||(b[f]=a[f]);return b};D.preventDefault=function(a){return function(){a.preventDefault?a.preventDefault():a.returnValue=!1}},D.stopPropagation=function(a){return function(){a.stopPropagation?a.stopPropagation():a.cancelBubble=!0}};var E={click:1,dblclick:1,mouseup:1,mousedown:1,contextmenu:1,mousewheel:1,DOMMouseScroll:1,mouseover:1,mouseout:1,mousemove:1,selectstart:1,selectend:1,keydown:1,keypress:1,keyup:1,orientationchange:1,touchstart:1,touchmove:1,touchend:1,touchcancel:1,gesturestart:1,gesturechange:1,gestureend:1,focus:1,blur:1,change:1,reset:1,select:1,submit:1,load:1,unload:1,beforeunload:1,resize:1,move:1,DOMContentLoaded:1,readystatechange:1,error:1,abort:1,scroll:1},G={mouseenter:{base:"mouseover",condition:F},mouseleave:{base:"mouseout",condition:F},mousewheel:{base:/Firefox/.test(navigator.userAgent)?"DOMMouseScroll":"mousewheel"}},H={add:y,remove:z,clone:C,fire:A},I=function(a){var b=z(a).__uid;b&&(delete d[b],delete c[b])};a[i]&&y(a,"unload",function(){for(var b in d)d.hasOwnProperty(b)&&I(d[b]);a.CollectGarbage&&CollectGarbage()});var J=a.bean;H.noConflict=function(){a.bean=J;return this},typeof module!="undefined"&&module.exports?module.exports=H:a.bean=H}(this)
View
2 make/build.js
@@ -1,4 +1,4 @@
-materequire('smoosh').config({
+require('smoosh').config({
"JAVASCRIPT": {
"DIST_DIR": "./",
"bean": [
View
35 src/bean.js
@@ -1,5 +1,7 @@
!function (context) {
- var __uid = 1, registry = {}, collected = {},
+ var __uid = 1,
+ registry = {},
+ collected = {},
overOut = /over|out/,
namespace = /[^\.]*(?=\..*)\.|.*/,
stripName = /\..*/,
@@ -23,7 +25,7 @@
},
retrieveUid = function (obj, uid) {
- return (obj.__uid = uid || obj.__uid || __uid++);
+ return (obj.__uid = uid && (uid + '::' + __uid++) || obj.__uid || __uid++);
},
retrieveEvents = function (element) {
@@ -93,7 +95,9 @@
function destroyHandler(uid) {
handler = events[type][uid];
- if (!handler) return;
+ if (!handler) {
+ return;
+ }
delete events[type][uid];
if (element[eventSupport]) {
type = customEvents[type] ? customEvents[type].base : type;
@@ -102,8 +106,8 @@
}
}
- destroyHandler(names) //get combos
- for (i = uids.length; i--; destroyHandler(uids[i])); //get singles
+ destroyHandler(names); //get combos
+ for (i = uids.length; i--; destroyHandler(uids[i])) {} //get singles
return element;
},
@@ -137,9 +141,10 @@
},
remove = function (element, orgEvents, fn) {
- var k, type, events, i,
+ var k, m, type, events, i,
isString = typeof(orgEvents) == 'string',
names = isString && orgEvents.replace(namespace, ''),
+ names = names && names.split('.'),
rm = removeListener,
attached = retrieveEvents(element);
if (isString && /\s/.test(orgEvents)) {
@@ -149,12 +154,12 @@
return element;
}
events = isString ? orgEvents.replace(stripName, '') : orgEvents;
- if (!attached || (isString && !attached[events])) {
- if (attached && names) {
- for (k in attached) {
- if (attached.hasOwnProperty(k)) {
- for (i in attached[k]) {
- attached[k].hasOwnProperty(i) && new RegExp('^' + names + '(\\..*)?$').test(i) && rm(element, [k, i].join('.'));
+ if (!attached || names || (isString && !attached[events])) {
+ for (k in attached) {
+ if (attached.hasOwnProperty(k)) {
+ for (i in attached[k]) {
+ for (m = names.length; m--;) {
+ attached[k].hasOwnProperty(i) && new RegExp('^' + names[m] + '::\\d*(\\..*)?$').test(i) && rm(element, [k, i].join('.'));
}
}
}
@@ -180,7 +185,7 @@
},
fire = function (element, type, args) {
- var evt, k, i, types = type.split(' ');
+ var evt, k, i, m, types = type.split(' ');
for (i = types.length; i--;) {
type = types[i].replace(stripName, '');
var isNative = nativeEvents[type],
@@ -189,7 +194,9 @@
if (isNamespace) {
isNamespace = isNamespace.split('.');
for (k = isNamespace.length; k--;) {
- handlers && handlers[isNamespace[k]] && handlers[isNamespace[k]].apply(element, [false].concat(args));
+ for (m in handlers) {
+ handlers.hasOwnProperty(m) && new RegExp('^' + isNamespace[k] + '::\\d*(\\..*)?$').test(m) && handlers[m].apply(element, [false].concat(args));
+ }
}
} else if (!args && element[eventSupport]) {
fireListener(isNative, type, element);
View
8 tests/tests.js
@@ -398,6 +398,14 @@ sink('namespaces', function (test, ok) {
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);
+ });
+
test('namespace: should be able to fire an event without handlers', 1, function () {
var el1 = document.getElementById('foo'), succ;
bean.remove(el1);

0 comments on commit 1ea0de7

Please sign in to comment.