How to select check box without selecting the whole row (see body)? - javascript

Say, I have an html:
<div class="row">
<input type="checkbox">
</div>
When user clicks on the whole row, it becomes highlighted (selected class added by an onClick event). I attach onClick event to elements with class .row.
When user clicks on checkbox (which is inside .row), this checkbox becomes selected. But row should not be highlighted.
Is it possible to exclude the area of the checkbox from the area of the .row for an onClick event?
UPDATE
Here is what I have now: http://jsfiddle.net/saAGU/
I don't want class to be toggled when I click exactly on checkbox.
UPDATE 2
Here is the working solution with jQuery for future use: http://jsfiddle.net/saAGU/2/

Yes, it's possible. The right way to do it is putting a onclick event on the checkbox, capture the event and stop its propagation.
Something like this:
function checkboxClick (e) {
e.stopPropagation();
}
Please tell me if it worked

add click event to every checkbox and stop its propogation .this should work -
e.stopPropagation in event handler for checkbox click
http://jsfiddle.net/saAGU/3/

If you capture the event, and look at the event.toElement, you can see if they clicked on the .row or something else.
http://jsfiddle.net/saAGU/1/
$('.row').click(function(event){
if (event.toElement !== this) // Did the user click on the row directly?
return;
$(this).toggleClass('selected');
});

Related

Can't check radio button programmatically with preventDefault()

I have some elements (for example divs with class .label) with radio buttons inside of each. When user clicks this "labels" I programmatically set radio in it as selected. But if I use preventDefault() for click event, the radio didn't selected if user clicked exactly on radio.
Please help me to understand this strange behaviour. I know the solution, I know why preventDefault() on parent element disallows to check radio, but I want to understand, why click event on radio can disallow to set its state programmatically. You will see that click on radio button will say that radio is checked, but it's not.
$(function () {
$('.label').on('click', function(e) {
var $radio = $(this).find(':radio')
console.log('before prevent', `checked=${$radio.prop('checked')}`, `prevented=${e.isDefaultPrevented()}`);
e.preventDefault();
if (!$(this).hasClass('checked')) {
$('.checked').removeClass('checked');
$(this).addClass('checked');
}
$radio.prop('checked', true);
console.log('after prevent', `checked=${$radio.prop('checked')}`, `prevented=${e.isDefaultPrevented()}`);
setTimeout(function () {
console.log('after timeout', `checked=${$radio.prop('checked')}`);
}, 500);
});
$(':radio').on('click', function (e) {
console.log('click', `prevented=${e.isDefaultPrevented()}`);
});
});
.label {
padding: 10px;
margin-bottom: 10px;
border: 1px solid #000;
}
.label.checked {
background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="label">
Label 1 <input type="radio" name="radio" value="1">
</div>
<div class="label">
Label 2 <input type="radio" name="radio" value="2">
</div>
UPDATE. How do I see this situation:
User clicks on radio
Firstly event triggered on radio and input setted as checked.
Then event is bubbling up and triggered on .label
Calling preventDefault() sets up an internal cancelled flag.
div getting class '.checked' and radio setted as checked again, now programmatically.
Event bubbles on, but nothing happens any more.
Since the event was cancelled, the default action should not occur and the checkbox is reset to its previous state.
Am I right?
How do I see this situation (inspired by https://stackoverflow.com/a/15767580/11357125):
You click on the radio
It gets checked
The event is dispatched on the document root
Capture phase, nothing happens with your handlers
The event arrives at the <input>
…and begins to bubble
On the <div>, it is handled. Event listener calls the preventDefault method, setting an internal cancelled flag. <div> getting class '.checked' and radio setted as checked again, now programmatically.
Event bubbles on, but nothing happens any more.
Since the event was cancelled, the default action should not occur and the checkbox is reset to its previous state even after it was checked programmatically.
Using preventDefault() on parent elements prevent the original event to be fired, but does not stop propagation. Understanding hierarchy and event propagation is crucial.
You have part of the solution in your code snippet. If you comment out that particular line, the code works properly, like you would expect.
But if you use
e.stopPropagation();
it also works.
In order not to repeat information already on the web, I found a very similar case here (Why does preventDefault() on a parent element's click 'disable' a checkbox?) which may help you understand better event propagation and bubbling.
You can also find an even better explanation here (https://medium.freecodecamp.org/a-simplified-explanation-of-event-propagation-in-javascript-f9de7961a06e).
MDN documentation also rarely fails to impress (https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault).
You just need to add e.stopPropagation() to return the default functionality for radio button again which is checked
The behaviour is that You have radio is a child to the div and you click listener is based on the parent div and when you preventDefault then the children inherit the prevention as well.
check that
If the button is pressed on one element and released on a different one, the event is fired on the most specific ancestor element that contained both.

How to prioritize Nested JavaScript events?

I have an edit button inside a table cell.
The table cell event has an "click" event, And the edit button who is inside a cell has another click event set to it.
Is there a way to prioritize the button event over the table cell event?
I tried using a different z-index for the button, but it didn't work.
The button cannot go outside the the table as its closest tr holds id data which is crucial for the proper event to function.
You can call event.stopPropagation() as part of the click handler for the button, to prevent the click event from bubbling up to the table cell. Documentation: http://api.jquery.com/event.stopPropagation/
Inside the click handler on the button, you just need to call event.stopPropagation().
element.onclick= function(event) {
// ...
event.stopPropagation();
// ...
}
Look into a tutorial on bubbling and capturing events, such as http://javascript.info/tutorial/bubbling-and-capturing

Checkbox not working before using script

I was asked to mark as checked the checkbox on the table line click, the script below is working but now when I click directly on the checkbox, it doesn't work, works only if I click the table line.
I have this html:
<tr class="linha_tela" id="4">
<td>Profile</td>
<td>Clientes</td>
<td>
<input type="checkbox" checked="checked" id="controller_4" name="controllers[]" value="4" />
</td>
</tr>
And this is my script:
$('.linha_tela').click(function(){
var checkbox = $(this).find(':checkbox');
checkbox.attr('checked', !checkbox.attr('checked'));
});
Thanks
What's happening is that the checkbox is toggling when you click on it, then the event handler is triggered causing it to become unchecked. This is basically occurring instantaneously, which is why it appears to just not work at all.
Try this:
$('.linha_tela').click(function(event) {
if (!$(event.target).is(':checkbox')) {
var checkbox = $(this).find(':checkbox');
checkbox.attr('checked', !checkbox.attr('checked'));
}
});
Edit: Here's a jsfiddle demo of it working.
This is happening because the checkbox is in the table row, so when you are clicking it, it's changing it's status (because that's what checkboxes do).
Then the click is bubbling up to your tr, and running the script, which is changing it status back.
you need to check the event target, and if it's not an input, do your thing, if it is, then don't.
here's the modified script:
$('.linha_tela').click(function(event) {
if (event.target.nodeName != 'INPUT') {
var checkbox = $(this).find(':checkbox');
checkbox.attr('checked', !checkbox.attr('checked'));
}
});
and a link to a jsfiddle to try it out:
http://jsfiddle.net/yDEyC/
$(":checkbox").click(function(event) {
event.stopPropagation();
});
This should work.
Here is a jsfiddle that demonstrates your code scenario:
http://jsfiddle.net/sAfTT/
The problem you're running into is a common one with events in HTML. When events are fired, they are fired on every element to which they can be applied in order from closest to furthest away. This is called bubbling(theres also capturing which works in reverse). http://www.quirksmode.org/js/events_order.html
So, in reality, when you are clicking on the checkbox, you are also clicking on the row, so the handler call looks like this.(assuming the box is unchecked to start with. reverse check/uncheck as applicable)
Checkbox clicked: check the box
Can I bubble up? Yes
Row clicked. Is there an event handler? Yes
Fire event handler (yours). This determines if the checkbox is checked. It is.
Because the box is checked, uncheck it.
Can I bubble up? Yes
Table Clicked. Is there an event handler? no
Document Clicked. Is there an event handler? No.
you can attach an event handler to the checkbox directly to prevent bubbling
$(':checkbox').click(function(e){
e.preventDefault();
e.stopPropagation();
})​
edit: I could never get the prevent default to work just right in jsfiddle, but the concept provided by the other answers work nicely too.

Disable mouse double click using javascript or jquery

I have a form in which i have some text boxes and below to it there is a table.When i double click on table row it takes me to another page.
Now the problem is if i double click on text boxes also it is going to another page so,i need to disable mouse clicks on this text boxes and also used tr for header and another tr for data.when i click tr header also it should n't work.
Note:
i have many text boxes so making each one double click mouse disabling is n't good solut.If i click row with data alone that double click should work.
it should be like this
$('.myTextBox').dblclick(function(e){
e.preventDefault();
})
add a class='myClickDisabledElm' to all DOM elements whose clicks you want to stop.
<input type="text" class="myClickDisabledElm" />
now javascript
jQuery('.myClickDisabledElm').bind('click',function(e){
e.preventDefault();
})
Edit
Since you are more concerned abt double click you may use dblclick in place of click
As said here, use a capture phase event listener:
document.addEventListener( 'dblclick', function(event) {  
alert("Double-click disabled!");  
event.preventDefault();  
event.stopPropagation(); 
},  true //capturing phase!!
);
Got the following code from here
jQuery code to disable double click event on the webpage.
$(document).ready(function(){
$("*").dblclick(function(e){
e.preventDefault();
});
});
Above jQuery code will disable double click event for all the controls on the webpage. If you want to disable for specific control, let's say a button with ID "btnSubmit" then,
$(document).ready(function(){
$('#btnSubmit').dblclick(function(e){
e.preventDefault();
});
});
If you want to disable any mouse click action use addEventListener(event, function, useCapture) .
Onclick ,call this function.
For more refer here.:
https://www.w3schools.com/jsref/met_element_addeventlistener.asp

Why can't this checkbox, created dynamically with jQuery, be clicked?

jsFiddle
I'm using a jQuery plugin that allows the user to draw boxes in an area. I use jQuery to put a checkbox (along with a dropdown list) in the box that appears when the user lets go of the mouse button (this is towards the bottom of the javascript in the jsFiddle). The problem is, the checkbox is unclickable.
I do have some click checking code in the _mouseStart, _mouseDrag and _mouseStop events to stop another box from being created when you click in an existing box, but I don't think this is causing the problem because the dropdown list that is created can be clicked, and furthermore if you remove the click checking code the checkbox remains unclickable.
What is causing the checkbox to be unclickable? Thanks for reading.
EDIT:
Thanks to VinayC's answer, I can now see that the click reaches the checkbox, with this code:
$('#box').click(function(e){
alert('clicked');
$(this).attr('checked', true);
});
But the $(this).attr('checked', true); line doesn't make the checkbox checked. Can anyone tell me why? I've updated the jsFiddle
EDIT 2:
Harmen noticed that the code assigns the same id to each checkbox. In the actual code there's a counter appended to the id, so each one is unique, but I've taken that out because I think this is just a jQuery issue. I'd change the jsFiddle, but if you just create one box (thus one checkbox), the same problem occurs.
I've got no idea why, but while fiddling around (yes, on fiddlejs), this seems to do the trick
$('#box', ui.box).click(
function(evt){
evt.stopPropagation();
}
);
when setting up the box. See: http://jsfiddle.net/BBh3r/9/
I was actually trying to intercept the event and manually set it checked, but if there's no need to set it then hey.. Perhaps there's an extra event generated somewhere negating the first..? Click's only triggered once though.
Might be related to building jquery checkbox - can't set checked value
PS. Only tested on Chrome for Linux
You're creating multiple checkboxes with the same id.
It appears that top level event handlers are cancelling the click event. Add onclick event handler on check-box element alerting and you will see that click reaches to the checkbox.
Actually it is checked while the alert is visible, but it becomes unchecked afterwards. I'm guessing that after your event handler sets it to checked, the default event for the click (which is to toggle the check mark) happens, and since it is checked at the moment, it becomes unchecked again. Try calling preventDefault from the click handler.
You can also try this for a more universal approach
This worked for me.
$(document).click(function (e) {
if (element.tagName == 'INPUT') {
if ($(element).attr("type") == 'checkbox') {
e.stopPropagation();
e.preventBubble();
return;
}
}
});

Categories