This is in jQuery we have on
, any element <a>
with class test
e without the foo
class will fire the function when clicked, even though you create the element after the event is already added:
$("#new").click(function () {
$('<p><a class="test" href="#">Novo: (' + (new Date) + ')</a></p>').appendTo("#container");
});
$("#container").on("click", "a.test:not(.foo)", function () {
console.log("Funcionou!");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><buttonid="new">Adicionar novo</button><br>
<div id="container">
<p><a href="#">Oi (não funciona)</a></p>
</div>
Note that in testing only the elements added later work, ie things like document.querySelector().forEach
will not work, unless you use MutationObserver , but then this would still be a third behavior .
At first I thought jQuery used MutationObserver , but after a few tests I realized that actually the event is actually in document
and #foobar
, so how I have to use Vanilla.js I started trying recreate this, I used Element.addEventListener
+ Event.target
, it looked something like:
var container = document.getElementById("container");
var newBtn = document.getElementById("new");
on(container, "click", "a.test:not(.foo)", function () {
console.log("achou:", this);
});
newBtn.onclick = function () {
var n = document.createElement("p");
n.innerHTML = '<a class="test" href="#">Novo: (' + (new Date) + ')</a>';
container.appendChild(n);
};
function on(target, type, selector, callback)
{
target.addEventListener(type, function (e)
{
var el = e.target,
els = document.querySelectorAll(selector);
for (var i = 0, j = els.length; i < els.length; i++) {
if (els[i] === el) {
callback.call(el, e); //Passa o elemento como this e o event como primeiro argumento
break;
}
}
});
}
<button id="new">Adicionar novo</button><br>
<div id="container">
<p><a href="#">Oi (não funciona)</a></p>
</div>
However this does not seem very performative, the doubt is as follows:
- Is there any way to test a specific element with a queryselector ?