Reputation: 10407
This is a code with jQuery 1.7:
<div class="test">
<div class="bu">
<a>
bu here
</a>
</div>
</div>
<script src="http://code.jquery.com/jquery-1.7.js"></script>
<script>
$(document).on('click', '.test', function () { alert(0); return false; });
$(document).on('click', '.bu', function () { alert(1); return false; });
$(document).on('click', '.bu', function () { alert(2); return false; });
</script>
Xlicking on .test > .bu will alert "1" and alert "2", but not alerts "0"
My question is: how to do the same WITHOUT jQuery (on native DOM API)? Seems, I can't do it with Native DOM API without implementing my own library...
Upvotes: 2
Views: 4966
Reputation: 3461
Here is a prototype based version
Document.prototype.on = function(event, target = null, callBack){
this.addEventListener(event, function(event){
let len = target.length, i = 0;
while(i < len){
if(event.target === target[i]){
callBack.call(target[i], event);
}
i ++;
}
}, false);
};
Usage is like jQuery has:
let btns = document.getElementsByTagName('button');
document.on('click', btns, function(event){
console.log(this.innerText)
});
And a live example is below:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body bgcolor="#000">
<button>hello1</button>
<button>hello2</button>
<script type="text/javascript">
Document.prototype.on = function(event, target = null, callBack = function(){}){
this.addEventListener(event, function(event){
let len = target.length, i = 0;
while(i < len){
if(event.target === target[i]){
callBack.call(target[i], event);
}
i ++;
}
}, false);
};
//example of usage
let btns = document.getElementsByTagName('button');
document.on('click', btns, function(t){
alert(this.innerText);
})
//add elements after delegating an event
let newBtn = document.createElement('button');
newBtn.innerText = 'btnNew';
document.body.appendChild(newBtn);
//delay to create
setTimeout(function(){
let newBtn = document.createElement('button');
newBtn.innerText = 'another btnNew';
document.body.appendChild(newBtn);
},2000);
</script>
</body>
</html>
Upvotes: 0
Reputation: 185933
Here you go:
document.addEventListener( 'click', function ( e ) {
if ( hasClass( e.target, 'bu' ) ) {
// .bu clicked
// do your thing
} else if ( hasClass( e.target, 'test' ) ) {
// .test clicked
// do your other thing
}
}, false );
where hasClass
is
function hasClass( elem, className ) {
return elem.className.split( ' ' ).indexOf( className ) > -1;
}
Live demo: http://jsfiddle.net/Nrxp5/30/
Upvotes: 14
Reputation: 10407
<div class="a">
<div class="b">
<div class="c" style="border: 1px solid silver; width: 80px; text-align: center;line-height: 80px;">
click me!
</div>
</div>
</div>
<script>
// Element.prototype.matchesSelector
(function (x) {
var i;
if (!x.matchesSelector) {
for (i in x) {
if (/^\S+MatchesSelector$/.test(i)) {
x.matchesSelector = x[i];
break;
}
}
}
}(Element.prototype));
Document.prototype.on =
Element.prototype.on = function (eventType, selector, handler) {
this.addEventListener(eventType, function listener(event) {
var t = event.target,
type = event.type,
x = [];
if (event.detail && event.detail.selector === selector && event.detail.handler === handler) {
return this.removeEventListener(type, listener, true);
}
while (t) {
if (t.matchesSelector && t.matchesSelector(selector)) {
t.addEventListener(type, handler, false);
x.push(t);
}
t = t.parentNode;
}
setTimeout(function () {
var i = x.length - 1;
while (i >= 0) {
x[i].removeEventListener(type, handler, false);
i -= 1;
}
}, 0);
}, true);
};
Document.prototype.off =
Element.prototype.off = function (eventType, selector, handler) {
var event = document.createEvent('CustomEvent');
event.initCustomEvent(eventType, false, false, {selector: selector, handler: handler});
this.dispatchEvent(event);
};
document.on('click', '.b', function () {
alert(2);
});
document.on('click', '.a', function () {
alert(1);
});
document.on('click', '.b', function (event) {
alert(3);
event.stopPropagation();
});
</script>
Upvotes: 3