First of all, i am new to jQuery. It is no rocket science to create a simple program, but the effect of the following code doesn't make any sense to me. My intention is that after an element with a class ".button" was clicked a new class should be added to that element. Otherwise - clicking somewhere else - the present new class should be removed. Unfortunately, the code in else is executed, even though the condition is true. What are the flaws of my idea? Could you provide a solution to that problem.
$(function() {
$("*").click(function() {
var ret = $(this).hasClass("button");
if (ret) {
$(".button").addClass("newclass");
} else {
$(".button").removeClass("newclass");
}
});
$("form").on("submit", function() {
return false;
})
});
.newclass {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<form method="get" action="">
<input type="text" name="">
<input type="submit" name="" class="button">
</form>
click
events bubble from the element that was clicked up through to the document, passing through all elements en route.
So what happens when you click your button is that while the class gets added (because the button has the class button
), the click bubbles to the form
(which doesn't) and then to body
(which doesn't) and then to html
(which doesn't). Your handler is called at each level, because you've attached it to all elements, and so the last one (html
) wins.
So the minimal change to your code is to stop propagation (tell the event to stop bubbling) when you handle the click:
$("*").click(function(e) {
// Note --------------^
e.stopPropagation(); // <===
var ret = $(this).hasClass("button");
if (ret) {
$(".button").addClass("newclass");
} else {
$(".button").removeClass("newclass");
}
});
Example:
$(function() {
$("*").click(function(e) {
e.stopPropagation();
var ret = $(this).hasClass("button");
if (ret) {
$(".button").addClass("newclass");
} else {
$(".button").removeClass("newclass");
}
});
$("form").on("submit", function() {
return false;
})
});
.newclass {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<form method="get" action="">
<input type="text" name="">
<input type="submit" name="" class="button">
</form>
But, I would change your approach entirely. Instead of having a handler on every element in the DOM, I would just attach to document
and then inspect e.target
:
$(document).click(function(e) {
// ^^^^^^ --- note --------^
var ret = $(e.target).hasClass("button");
// Note ------^^^^^^^^
if (ret) {
$(".button").addClass("newclass");
} else {
$(".button").removeClass("newclass");
}
});
That waits for the click to bubble up to document.body
, and then looks at where it bubbled from (e.target
).
Example:
$(function() {
$(document).click(function(e) {
// Note ------------------------^
var ret = $(e.target).hasClass("button");
if (ret) {
$(".button").addClass("newclass");
} else {
$(".button").removeClass("newclass");
}
});
$("form").on("submit", function() {
return false;
})
});
.newclass {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<form method="get" action="">
<input type="text" name="">
<input type="submit" name="" class="button">
</form>
If you were using an element that could have child elements (like button
instead of input
), you'd have the situation where the click might originate in a child or descendant of the button. In that case, you might use closest
to figure out whether the click passed through a .button
element en route to document
:
var ret = $(e.target).closest(".button").length;
if (ret) {
// The element clicked or an ancestor of it has the class...
(There we're relying on the fact that 0
is falsy but all other non-NaN
numbers aren't.)
Example:
$(function() {
$(document).click(function(e) {
// Note ------------------------^
var ret = $(e.target).closest(".button").length;
if (ret) {
$(".button").addClass("newclass");
} else {
$(".button").removeClass("newclass");
}
});
$("form").on("submit", function() {
return false;
})
});
.newclass {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<form method="get" action="">
<input type="text" name="">
<button class="button">
Direct <strong>Child</strong>
</button>
</form>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With