Reputation: 127
I am trying to make a click event listener that listens to a HTML event recently made. The whole selector thing is confusing me. Here is my code:
var counter = 0;
$("#button").click(function() {
$(".slick").last().after("<div class='box'></div><div class='slick'></div>")
});
// With on():
$(".slick").on("click", function() {
$(".box").css("background-color", "blue");
});
.box {
background-color: red;
padding: 3px;
margin: 4px;
height: 20px;
width: 60px;
}
.slick {
background-color: #B2B2B2;
padding: 3px;
margin: 4px;
height: 10px;
width: 40px;
}
#button, #button1 {
background-color: #BCBCBC;
padding: 3px;
width: 90px;
margin: 7px;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box"></div>
<div class="slick"></div>
<div class="box"></div>
<div class="slick"></div>
<div id="button">New Tab</div>
As you can see here the New Tab button adds two new elements exactly same to the ones that were there before. The only problem is that when I click the .slick
element of the newly generated elements, the background color doesn't change like the first two .slick
do.
I do not want to have to put the elements inside of each other. Their tree order should stay the same.
Upvotes: 1
Views: 168
Reputation: 66228
That is because $(".slick").on("click", function() {...});
is functionally identical to $(".slick").click(...)
. Remember that event binding is done at runtime, this means that the newly added .slick
element does not have the click event bound to it. To ensure that you capture the click event from newly added elements, you have to rely on to event bubbling.
In other words, you want to listen to the click event bubbling up from any .slick
element, at the level of a parent that is present at runtime. An example will be the document object:
$(document).on("click", ".slick", function() {
$(".box").css("background-color", "blue");
});
This code above basically does this: it instructs the document
object to listen to a click event that has originated/bubbled up from any child element with the class of slick
. Since the document object is already present at runtime, this will mean your callback is always fired, no matter at which time a new .slick
element is added and clicked on.
Ideally, you do not want to bind that to the document
object due to performance issue. Binding it to the closest parent that is available at runtime will do just as fine. Let's say all your .slick
elements are added in a parent called <div class="slick-wrapper">
that is present in the markup at runtime, then using $('.slick-wrapper').on('click', '.slick', function() {...});
will also work.
Proof-of-concept:
var counter = 0;
$("#button").click(function() {
$(".slick").last().after("<div class='box'></div><div class='slick'></div>")
});
$(document).on("click", ".slick", function() {
$(".box").css("background-color", "blue");
});
.box {
background-color: red;
padding: 3px;
margin: 4px;
height: 20px;
width: 60px;
}
.slick {
background-color: #B2B2B2;
padding: 3px;
margin: 4px;
height: 10px;
width: 40px;
}
#button, #button1 {
background-color: #BCBCBC;
padding: 3px;
width: 90px;
margin: 7px;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box"></div>
<div class="slick"></div>
<div class="box"></div>
<div class="slick"></div>
<div id="button">New Tab</div>
Upvotes: 1
Reputation: 431
If you click on the "New Tab" button, js add new box and slick, the first 2 slick will change the color of all boxes, but the newer ones are not. The reason of this, you add event to the slick elements first, and after it you create a new one. This code will add event for the new ones as well:
$("body").on("click", ".slick", function() {
$(".box").css("background-color", "blue");
});
Upvotes: 0
Reputation: 3879
You can add a style tag to affect future created elements. Something like this:
var counter = 0;
$("#button").click(function() {
$(".slick").last().after("<div class='box'></div><div class='slick'></div>")
});
// With on():
$(".slick").on("click", function() {
$('<style>.box { background-color: blue !important; }</style>').appendTo('head');
});
.box {
background-color: red;
padding: 3px;
margin: 4px;
height: 20px;
width: 60px;
}
.slick {
background-color: #B2B2B2;
padding: 3px;
margin: 4px;
height: 10px;
width: 40px;
}
#button, #button1 {
background-color: #BCBCBC;
padding: 3px;
width: 90px;
margin: 7px;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box"></div>
<div class="slick"></div>
<div class="box"></div>
<div class="slick"></div>
<div id="button">New Tab</div>
Upvotes: 0