How to stop event bubbling in jquery? - javascript

I'm using some JQ stuff on check box, even if the parent div is clicked. I am toggling the value of check box. Clicking on div is working perfectly but when you click on checkbox the function is called twice. Is there any way to solve this problem? following is my code(Fiddle)
HTML:
<div class="check-unit">
<input type="checkbox" class="check" />
<p class="brandList">Model</p>
</div>
JQ:
$('.check').on('change',function(e){
e.stopImmediatePropagation();
if($(this).is(':checked')){
console.log("checked");
}else{
console.log("unchecked");
}
});
$('.check-unit').on('click',function(e){
var checkbox = $(this).children('.check'),
chhhk= checkbox.attr('checked') ? false : true;
checkbox.attr('checked',chhhk);
$(this).children('.check').change();
});
I've seen eventbubbling problem on stackoverflow, but still confused how to do this. FIDDLE

Only execute the callback on the parent element if the target is not the input
$('.check').on('change',function(e){
if(this.checked){
console.log("checked");
}else{
console.log("unchecked");
}
});
$('.check-unit').on('click',function(e){
if ( ! $(e.target).hasClass('check')) {
$(this).children('.check').prop('checked', function(_,state) {
return !state;
}).trigger('change');
}
});
FIDDLE
As a sidenote, this is what label elements are for!

You need to use .prop() instead of .attr() to set the checked property.
$('.check').on('change', function (e) {
if (this.checked) {
console.log("checked");
} else {
console.log("unchecked");
}
}).click(function (e) {
//prevent clicks in the checksboxes from bubbling up otherwise when you click on the checkbox the state will get toggled again the event will be bubbled to check-unit which will again toggle the state negating the click
e.stopPropagation()
});
$('.check-unit').on('click', function () {
var checkbox = $(this).children('.check'),
//use .is() and checked-selector to check whether the checkbox is checked
chhhk = checkbox.is(':checked');
//use .prop() instead of .attr() & toggle the checked state
checkbox.prop('checked', !chhhk).change();
});
Demo: Fiddle

You can check if you are clicking the checkbox before changing.
$('.check-unit').on('click', function (e) {
if (!($(e.target).hasClass('check'))) {
var checkbox = $(this).children('.check'),
chhhk = checkbox.prop('checked');
checkbox.prop('checked', !chhhk).change();
}
});
Also note that the code is using prop instead of attr because when you are using boolean attribute values you should use .prop()
DEMO

Related

jquery uncheck and check and vise versa checkbox of child element

Here is my html
#This will be generated throught loop
<li class="selector">
<a>
<input type="checkbox" value="test" /> test
</a>
</li>
Here is my jquery click event
$('.selector').on('click', function() {
if($(this).find('input').is(':checked')){
#uncheck the checkbox
}else{
#check the checkbox
}
});
How do I uncheck if checked and check if unchecked
Try
$(document).on('click', '.selector', function (e) {
if (!$(e.target).is('input')) {
$(this).find('input').prop('checked', function () {
return !this.checked;
});
}
});
Demo: Fiddle
Another way
$(document).on('click', '.selector', function (e) {
$(this).find('input').prop('checked', function () {
return !this.checked;
});
});
$(document).on('click', '.selector input', function (e) {
e.stopPropagation();
});
Demo: Fiddle
Try this
$('.selector').on('click', function() {
var checkbox = $(this).find(':checkbox');
if($(checkbox).is(':checked')){
$(checkbox).prop('checked', false);
}else{
#check the checkbox
$(checkbox).prop('checked', true);
}
});
I don't understand why you are trying to do this with JavaScript. If the user clicks directly on the checkbox it will automatically check/uncheck itself, but if you add code to check/uncheck it in JS that would cancel out the default behaviour so in your click handler you'd need to test that the click was elsewhere within the .selector.
Anwyay, the .prop() method has you covered:
$('.selector').on('click', function(e) {
if (e.target.type === "checkbox") return; // do nothing if checkbox clicked directly
$(this).find("input[type=checkbox]").prop("checked", function(i,v) {
return !v; // set to opposite of current value
});
});
Demo: http://jsfiddle.net/N4crP/1/
However, if your goal is just to allow clicking on the text "test" to click the box you don't need JavaScript because that's what a <label> element does:
<li class="selector">
<label>
<input type="checkbox" value="test" /> test
</label>
</li>
As you can see in this demo: http://jsfiddle.net/N4crP/2/ - clicking on the text "test" or the checkbox will toggle the current value without any JavaScript.

How do you propagate a click to child elements if the parent element has preventDefault?

UPDATE:
this doesn't work in the latest version of firefox (15.0.1):
http://jsfiddle.net/DerNalia/NdrNV/5/
clicking the checkbox navigates to google... but it shouldn't :(
it appears that adding e.stopPropagation() doesn't help / doesn't work.
playarea: http://jsfiddle.net/DerNalia/NdrNV/1/
What I'm trying to do:
When I click the checkbox that is next to (but actually is a child element of) the anchor, it should change states, and also change the state of the "other" checkbox.
But because the anchor has e.preventDefault() invoked, the checkbox never gets checked.
Here is my markup
Link Name <input class="home" type="checkbox"/>
<br />
Sync'd checkbox: <input class="other" type="checkbox" />​
Here is some the troubled jquery
$(function() {
$("input.home").click(function() {
$("input.other").click();
});
$("a").click(function(e) {
e.preventDefault();
// prevent default so we can do some ajaxy things instead of follow the href
});
})​
So, how do I change the jQuery click action on the anchor tag such that clicks propagate to child elements (but I can still do ajaxy things without the browser following the href of the anchor tag)?
Is there a way to do this without changing the markup? (the way it is now makes semantic sense for my web application)
It doesn't work because event.preventDefault would cancel the event.
Using e.preventDefault on click on the checkbox which is wrapped inside <a> would not let you change the checkbox state.
A workaround I could think of is to set the checkbox state in a different context so that the e.preventDefault code is ineffective.
DEMO: http://jsfiddle.net/NdrNV/10/
$(function() {
$("input.home").click(function() {
$("input.other").click();
});
$("a").click(function(e) {
e.preventDefault();
var setCheckbox = function() {
var checkbox = $(e.target)[0];
checkbox.checked = checkbox.checked?false:true;
}
if ($(e.target).is(':checkbox')) {
setTimeout(setCheckbox, 0);
}
});
})
Note: This is a workaround.
You can put condition e.target.tagName like this,
if(e.target.tagName == 'A')
e.preventDefault();
Live Demo
$(function() {
$("input.home").click(function() {
$("input.other").click();
});
$("a").click(function(e) {
if(e.target.tagName == 'A')
e.preventDefault();
// prevent default so we can do some ajaxy things instead of follow the href
});
})​
$(function() {
$("input.home").click(function() {
if($(this).attr('checked') == 'checked')
$(this).removeAttr('checked');
else
$(this).attr('checked', 'checked');
$("input.other").click();
});
$("a").click(function(e) {
e.preventDefault();
// prevent default so we can do some ajaxy things instead of follow the href
var target = e.target; // object that triggers the event
$(target).children().trigger('click');
});
});

How to bind to a click to toggle a checkbox?

Given a list of LIs each LI includes a checkbox like so:
<li class="contact">
<input type="checkbox" class="checkbox" name="checkableitems[]" value="1333">
<div class="content">
<cite>Baby James</cite>
</div>
</li>
I would like to be able to toggle the checkbox on LI click, not just on checkbox click. I got this work which you can see here:
http://jsfiddle.net/xgB5X/2/
The problem is, while clicking on the LI toggles the checkbox, click on the checkbox directly is no broken. Clicking on the checkbox no longer toggles. Any suggestions to get this working? Thanks
Why not using label tags?
<li class="contact">
<input id='input1' type="checkbox" class="checkbox" name="checkableitems[]" value="1333">
<label for='input1'>Baby James</label>
</li>
DEMO
http://jsfiddle.net/xgB5X/3/ Check this.
I've added a little bit of code to stop the propagation. This will prevent the event to reach to the li tag.
$('input[type=checkbox]').on('click', function(e) {
e.stopPropagation();
});
Your problem was when the checkbox was clicked it was changing its state, but when the event reach to the li tag as it contains the check box once again it was changing its state.
A couple of notes:
use .prop() instead of .attr() (it's also easier to tell true/false on it, must each other through all browsers.
You can check the e.srcElement for your classname of checkbox within the click().
$('.listview li').on('click', function(e) {
if (e.srcElement.className === 'checkbox') {
e.stopPropagation();
return;
}
checkbox = $(this).find(':checkbox');
// Toggle Checkbox
if (checkbox.prop('checked')) {
checkbox.prop('checked', false);
} else {
checkbox.prop('checked', true);
}
});
jsFiddle
You can try something like this jsFiddle
$('.listview li > *').children().bind({
click: function(e) {
checkbox = $(this).closest('li').find('.checkbox');
checkbox.attr('checked', !checkbox.is(':checked'));
}
});​
$('.listview li').on('click', function(e) {
var c = $('.checkbox', this);
c.prop('checked', !c[0].checked);
}).find('.checkbox').on('click', function(e) {e.stopPropagation();});​​​​​
FIDDLE
Even though I think you should use a label for this here is method working
$('.listview li').bind({
click: function(e) {
var checkbox = $(this).find('.checkbox').get(0);
if (e.target == checkbox) return;
checkbox.click();
}
});
FIDDLE

toggle checkbox attribute with jquery [duplicate]

I've used a hover function where you do x on mouseover and y and mouseout. I'm trying the same for click but it doesn't seem to work:
$('.offer').click(function(){
$(this).find(':checkbox').attr('checked', true );
},function(){
$(this).find(':checkbox').attr('checked', false );
});
I want the checkbox to be checked when clicking on a div, and unchecked if clicked again - a click toggle.
This is easily done by flipping the current 'checked' state of the checkbox upon each click. Examples:
$(".offer").on("click", function () {
var $checkbox = $(this).find(':checkbox');
$checkbox.attr('checked', !$checkbox.attr('checked'));
});
or:
$(".offer").on("click", function () {
var $checkbox = $(this).find(':checkbox');
$checkbox.attr('checked', !$checkbox.is(':checked'));
});
or, by directly manipulating the DOM 'checked' property (i.e. not using attr() to fetch the current state of the clicked checkbox):
$(".offer").on("click", function () {
var $checkbox = $(this).find(':checkbox');
$checkbox.attr('checked', !$checkbox[0].checked);
});
...and so on.
Note: since jQuery 1.6, checkboxes should be set using prop not attr:
$(".offer").on("click", function () {
var $checkbox = $(this).find(':checkbox');
$checkbox.prop('checked', !$checkbox[0].checked);
});
Another approach would be to extended jquery like this:
$.fn.toggleCheckbox = function() {
this.attr('checked', !this.attr('checked'));
}
Then call:
$('.offer').find(':checkbox').toggleCheckbox();
Warning: using attr() or prop() to change the state of a checkbox does not fire the change event in most browsers I've tested with. The checked state will change but no event bubbling. You must trigger the change event manually after setting the checked attribute. I had some other event handlers monitoring the state of checkboxes and they would work fine with direct user clicks. However, setting the checked state programmatically fails to consistently trigger the change event.
jQuery 1.6
$('.offer').bind('click', function(){
var $checkbox = $(this).find(':checkbox');
$checkbox[0].checked = !$checkbox[0].checked;
$checkbox.trigger('change'); //<- Works in IE6 - IE9, Chrome, Firefox
});
You could use the toggle function:
$('.offer').toggle(function() {
$(this).find(':checkbox').attr('checked', true);
}, function() {
$(this).find(':checkbox').attr('checked', false);
});
Why not in one line?
$('.offer').click(function(){
$(this).find(':checkbox').attr('checked', !$(this).find(':checkbox').attr('checked'));
});
I have a single checkbox named chkDueDate and an HTML object with a click event as follows:
$('#chkDueDate').attr('checked', !$('#chkDueDate').is(':checked'));
Clicking the HTML object (in this case a <span>) toggles the checked property of the checkbox.
jQuery: Best Way, delegate the actions to jQuery (jQuery = jQuery).
$( "input[type='checkbox']" ).prop( "checked", function( i, val ) {
return !val;
});
try changing this:
$(this).find(':checkbox').attr('checked', true );
to this:
$(this).find(':checkbox').attr('checked', 'checked');
Not 100% sure if that will do it, but I seem to recall having a similar problem. Good luck!
$('.offer').click(function(){
if ($(this).find(':checkbox').is(':checked'))
{
$(this).find(':checkbox').attr('checked', false);
}else{
$(this).find(':checkbox').attr('checked', true);
}
});
In JQuery I don't think that click() accepts two functions for toggling. You should use the toggle() function for that: http://docs.jquery.com/Events/toggle
$('.offer').click(function() {
$(':checkbox', this).each(function() {
this.checked = !this.checked;
});
});
Easiest solution
$('.offer').click(function(){
var cc = $(this).attr('checked') == undefined ? false : true;
$(this).find(':checkbox').attr('checked',cc);
});
<label>
<input
type="checkbox"
onclick="$('input[type=checkbox]').attr('checked', $(this).is(':checked'));"
/>
Check all
</label>
Another alternative solution to toggle checkbox value:
<div id="parent">
<img src="" class="avatar" />
<input type="checkbox" name="" />
</div>
$("img.avatar").click(function(){
var op = !$(this).parent().find(':checkbox').attr('checked');
$(this).parent().find(':checkbox').attr('checked', op);
});
$('controlCheckBox').click(function(){
var temp = $(this).prop('checked');
$('controlledCheckBoxes').prop('checked', temp);
});

Check/Uncheck checkbox with JavaScript

How can a checkbox be checked/unchecked using JavaScript?
Javascript:
// Check
document.getElementById("checkbox").checked = true;
// Uncheck
document.getElementById("checkbox").checked = false;
jQuery (1.6+):
// Check
$("#checkbox").prop("checked", true);
// Uncheck
$("#checkbox").prop("checked", false);
jQuery (1.5-):
// Check
$("#checkbox").attr("checked", true);
// Uncheck
$("#checkbox").attr("checked", false);
Important behaviour that has not yet been mentioned:
Programmatically setting the checked attribute, does not fire the change event of the checkbox.
See for yourself in this fiddle:
http://jsfiddle.net/fjaeger/L9z9t04p/4/
(Fiddle tested in Chrome 46, Firefox 41 and IE 11)
The click() method
Some day you might find yourself writing code, which relies on the event being fired. To make sure the event fires, call the click() method of the checkbox element, like this:
document.getElementById('checkbox').click();
However, this toggles the checked status of the checkbox, instead of specifically setting it to true or false. Remember that the change event should only fire, when the checked attribute actually changes.
It also applies to the jQuery way: setting the attribute using prop or attr, does not fire the change event.
Setting checked to a specific value
You could test the checked attribute, before calling the click() method. Example:
function toggle(checked) {
var elm = document.getElementById('checkbox');
if (checked != elm.checked) {
elm.click();
}
}
Read more about the click method here:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click
to check:
document.getElementById("id-of-checkbox").checked = true;
to uncheck:
document.getElementById("id-of-checkbox").checked = false;
We can checked a particulate checkbox as,
$('id of the checkbox')[0].checked = true
and uncheck by ,
$('id of the checkbox')[0].checked = false
Try This:
//Check
document.getElementById('checkbox').setAttribute('checked', 'checked');
//UnCheck
document.getElementById('chk').removeAttribute('checked');
I would like to note, that setting the 'checked' attribute to a non-empty string leads to a checked box.
So if you set the 'checked' attribute to "false", the checkbox will be checked. I had to set the value to the empty string, null or the boolean value false in order to make sure the checkbox was not checked.
Using vanilla js:
//for one element:
document.querySelector('.myCheckBox').checked = true //will select the first matched element
document.querySelector('.myCheckBox').checked = false//will unselect the first matched element
//for multiple elements:
for (const checkbox of document.querySelectorAll('.myCheckBox')) {
//iterating over all matched elements
checkbox.checked = true //for selection
checkbox.checked = false //for unselection
}
function setCheckboxValue(checkbox,value) {
if (checkbox.checked!=value)
checkbox.click();
}
<script type="text/javascript">
$(document).ready(function () {
$('.selecctall').click(function (event) {
if (this.checked) {
$('.checkbox1').each(function () {
this.checked = true;
});
} else {
$('.checkbox1').each(function () {
this.checked = false;
});
}
});
});
</script>
For single check try
myCheckBox.checked=1
<input type="checkbox" id="myCheckBox"> Call to her
for multi try
document.querySelectorAll('.imChecked').forEach(c=> c.checked=1)
Buy wine: <input type="checkbox" class="imChecked"><br>
Play smooth-jazz music: <input type="checkbox"><br>
Shave: <input type="checkbox" class="imChecked"><br>
If, for some reason, you don't want to (or can't) run a .click() on the checkbox element, you can simply change its value directly via its .checked property (an IDL attribute of <input type="checkbox">).
Note that doing so does not fire the normally related event (change) so you'll need to manually fire it to have a complete solution that works with any related event handlers.
Here's a functional example in raw javascript (ES6):
class ButtonCheck {
constructor() {
let ourCheckBox = null;
this.ourCheckBox = document.querySelector('#checkboxID');
let checkBoxButton = null;
this.checkBoxButton = document.querySelector('#checkboxID+button[aria-label="checkboxID"]');
let checkEvent = new Event('change');
this.checkBoxButton.addEventListener('click', function() {
let checkBox = this.ourCheckBox;
//toggle the checkbox: invert its state!
checkBox.checked = !checkBox.checked;
//let other things know the checkbox changed
checkBox.dispatchEvent(checkEvent);
}.bind(this), true);
this.eventHandler = function(e) {
document.querySelector('.checkboxfeedback').insertAdjacentHTML('beforeend', '<br />Event occurred on checkbox! Type: ' + e.type + ' checkbox state now: ' + this.ourCheckBox.checked);
}
//demonstration: we will see change events regardless of whether the checkbox is clicked or the button
this.ourCheckBox.addEventListener('change', function(e) {
this.eventHandler(e);
}.bind(this), true);
//demonstration: if we bind a click handler only to the checkbox, we only see clicks from the checkbox
this.ourCheckBox.addEventListener('click', function(e) {
this.eventHandler(e);
}.bind(this), true);
}
}
var init = function() {
const checkIt = new ButtonCheck();
}
if (document.readyState != 'loading') {
init;
} else {
document.addEventListener('DOMContentLoaded', init);
}
<input type="checkbox" id="checkboxID" />
<button aria-label="checkboxID">Change the checkbox!</button>
<div class="checkboxfeedback">No changes yet!</div>
If you run this and click on both the checkbox and the button you should get a sense of how this works.
Note that I used document.querySelector for brevity/simplicity, but this could easily be built out to either have a given ID passed to the constructor, or it could apply to all buttons that act as aria-labels for a checkbox (note that I didn't bother setting an id on the button and giving the checkbox an aria-labelledby, which should be done if using this method) or any number of other ways to expand this. The last two addEventListeners are just to demo how it works.
I agree with the current answers, but in my case it does not work, I hope this code help someone in the future:
// check
$('#checkbox_id').click()

Categories

Resources