I have a table with a row. The row has a TD(with a checkbox in it) and on the TD I have a click function. So that when the TD is clicked the checkbox will get checked/unchecked.
It works fine when I click on the TD , but when clicking on the checkbox the (visual) value of the checkbox does not change( It does not get checked/unchecked )
The wanted situation is:
When I click the checkbox, the (visual) value of the checkbox changes and I can call a function.( for example to make an AJAX call )
When I click on the TD, the (visual) value of the checkbox changes and I can call a function. ( for example to make an AJAX call )
How can we achieve this?
Sample Code
The problem is that the click handler for the TD fires also when you click the checkbox, which means the checkbox gets changed by both the default click handler for the checkbox and your custom click handler for the TD (they counteract each other). The solution is to prevent clicks on the checkbox from bubbling to the TD. You can do this in Knockout with this binding: click:function(){return true}, clickBubble:false.
Here it is in action: http://jsfiddle.net/mbest/Eatdh/12/
I do think, however, that using a label is a better approach (see my other answer).
To avoid the click event issues, use the label element to make a larger area clickable. Here I've made the label a block element so it takes up the whole td:
<td>
<label style="display: block">
<input type="checkbox" data-bind="checked: checkBox" />
</label>
</td>
See http://jsfiddle.net/mbest/LsxSh/
Td Event seems to be overriding the the input's check click event
clicking the check box invokes the click hander code for the td:
self.checkBox(!self.checkBox());
this removes the check.
This isn't quite DRY, but its quick and functional: fiddle
<td data-bind="click:tdClick">
<input type="checkbox" data-bind="checked: checkBox, click:tdClick" />
</td>
Related
I have a simple list:
<li onClick={handleRowClick}>
<input type="checkbox" onClick={handleCheckboxClick} />
...
</li>
When I click in any place on the li (except its checkbox child), handleRowClick executes.
When I click on the checkbox, it always executes in this order:
row
row
checkbox
Here's what I've tried
using onClickCapture on each: checkbox, li, and both
calling e.stopPropagation() on each: checkbox, li, and both
calling e.nativeEvent.stopPropagation() on each: checkbox, li, and both
calling e.nativeEvent.stopImmediatePropagation() on each: checkbox, li, and both
calling e.nativeEvent.preventDefault() on each: checkbox, li, and both
With the code above, at some point the order became
row
checkbox
But the row is always executed BEFORE the checkbox, so I can't see how make them not overlap.
Also worth mentioning that both handlers have logic, that need to happen, so making the row never execute any code is not an option.
This seems like a trivial thing, like I should know the answer to this. What am I missing?
Edit
Here's the minimal reproducible example: https://codesandbox.io/s/shy-shape-u1me4?file=/src/App.js
In the example above I stripped a lot of things like CSS classes. While doing that, I realised that what I'm actually clicking is a label for the checkbox, and the checkbox is "hidden" in my app.
I solved the problem by moving the event handler to the label instead of the checkbox, and running:
e.stopPropagation() to prevent propagation to the parent li.
e.preventDefault() to prevent the label to trigger the checkboxes o'clock, which would also cause the event to propagate to the li above.
The problem seem to be that my UI library hides the actual input, and the visible area where I was clicking was actually the label. These 2 elements are siblings related by the id and htmlFor attributes respectively.
As I was attaching the event handler on the input, but the label was the one actually being clicked, the propagation was not properly being stopped.
I solved the problem by moving the event handler to the label instead of the checkbox, and running:
e.stopPropagation() to prevent propagation to the parent li.
e.preventDefault() to prevent the label to trigger the checkboxes o'clock, which would also cause the event to propagate to the li above.
<li onClick={handleRowClick}>
<input id="c-1" type="checkbox" />
<label htmlFor="c-1" onClick={handleCheckboxClick}>Foo</label>
...
</li>
const handleCheckboxClick = () => {
e.stopPropagation()
e.preventDefault()
}
In the following snippet, why does divClicked() trigger twice when the <label> is clicked, but only once when <input> is clicked?
function divClicked(_index) {
console.log("div click event");
}
function inputClicked(_index) {
console.log("input click event");
}
<div class="option" onclick="divClicked(1)">
<input id="1_1" name="group_1" type="radio" value="1" onclick="inputClicked(1)" />
<label for="1_1">label</label>
</div>
Note: I want to know why this happens, not a "quick fix" like: put onclick() on label.
This happens because of what the HTML spec describes at 4.10.4:
For example, on platforms where clicking a checkbox label checks the
checkbox, clicking the label in the following snippet could trigger
the user agent to run synthetic click activation steps on the input
element, as if the element itself had been triggered by the user:
<label><input type=checkbox name=lost> Lost</label>
On other platforms, the behavior might be just to focus the control,
or do nothing.
This means that when a <label> is clicked, the browser creates a second "synthetic" click event on the associated <input> element, in order to toggle its state.
The reason divClicked is triggered twice, is because the first event which comes from the <label> bubbles up to the <div>, and also the second, synthetic click event bubbles up to the <div>.
This is usually be cause of the bubbling principle of click event:
When an event happens on an element, it runs on it, its associated elements,its parent and other ancestors.
Now, The relation is when you click on label there a are two events which bubbles up here:
1) Click on div (which you expect)
2) Click on input (which is also expected)
2.1) When click on input is triggered then a click on div is also triggered again here
You can confirm this behavior by using event.bubbles prop.
EDIT:
The reason for the connection between label and input: (I know this is absolutely not required, as it's present all over the place yet)
A <label> can be associated with a control either by placing the control element inside the <label> element, or by using the for attribute. Such a control is called the labeled control of the label element. One input can be associated with multiple labels.
Taken from: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label
Which means placing for on label referencing id of an input element will stimulate the behavior as if the element is inside the label. This would bubble a event on input onto label like any event on child to parent
At some moments, check also if the javascript file asset isn't loaded twice .... it shouldn't happen, but you never know.
I have a strange problem, that i have a <table> and on <td> there is a text box and on the next <td> there is an add button. In the text box, there is an onblur function which will hide the textbox and create a <span> for the textbox value. the span has a lesser width than textbox .
Also there is an add button Onclick event, My problem is that when we type something on text box and then click on add button, `onblur' event works first and click is not working because the click button position changes when the text box hides.
Anyone help me what I have to do get the both event works and i want these event should work separately
<Table>
<tr>
<td><Span>bla<Span><input type="text" onblur="hideTextboxCreateNewSpan()"/></td>
<td><a onclick="AddNewTextBox()">Add</a></td>
</tr>
</Table>
This is my table structure Sample and i have tons of code in these both function i cant copy here any one please help me
Try using setTimeout, then the button will be clicked before the hideTextBoxCreateNewSpan is called:
onblur="setTimeout(hideTextboxCreateNewSpan, 0);"
I'm using labels for my form, like this :
<label for="foo" id="bar">Label</label>
<input type="checkbox" id="foo" />
I want to hide an element when the user uncheck the box, and show it otherwise.
The problem is, if I bind the click event to "foo", it'll only works when the user clicks on the checkbox itself and not on the label. Therefore, do I also need to bind a click event on the label ? Or should I enclose both elements within a span ?
My HTML already contains 2344 elements, so I'd like to do it without adding anything, and without doubling the JavaScript code or the selector, if possible.
Instead of binding with the click() event, you should bind using the change() event, then however this change is triggered the outcome will be the same:
$('#foo').change(
function(){
// do whatever
});
References:
change().
The change event should fire for the input whether the label or input is clicked:
$("#foo").change(function () { ... });
Example http://jsfiddle.net/andrewwhitaker/6LMXW/
I have a checkbox inside a <label> and i want that checkbox, when checked or unchecked, to trigger a function.
I attached a onchange trigger to the checkbox but in IE6 the trigger only fires after the focus is turned away from the checkbox, while in FF3 and Chrome it fires right away.
I removed the onchange trigger and attached a onclick trigger to the <label> but now the trigger fires twice when the label is clicked once (does enyone know why?)...
My question is: how can i make the checkbox fire a function when it is checked or unchecked by a click on it or on it's label.
Thanks.
Assuming you don't want a fancy ASP / JQuery solution, just attaching the function to the onClick of the checkbox itself should work fine.
(Of course, you'll need to inspect the current state of the checkbox in the function if you want to have the function behave differently based on if the checkbox is checked or not.)
As "Electrons_Ahoy" says, you should be able to simply attach an onclick handler to the checkbox element. This handler should also get called when the user clicks on the label instead of the checkbox.
HTML:
<label><input type="checkbox" id="myCheckbox" />My Checkbox</label>
JavaScript:
document.getElementById("myCheckbox").onclick = function() {
if (this.checked) {
alert("Checkbox was checked.");
}
else {
alert("Checkbox wasn't checked.");
}
};
The above code seems to work correctly in Safari 4 and Firefox 3 (I'm not sure how it would work in IE).
Steve
not sure if using Prototype is an option for you, but if so you'd do it this way (this assumes Prototype 1.6. Code written against earlier versions will be slightly different):
HTML:
<label><input type="checkbox" id="myCheckbox" />My Checkbox</label>
JS:
$('myCheckbox').observe('click', function(cbox)
{
var cbox = $('myCheckbox');
//do work in here.
//cbox is the DOM element that represents your checkbox
}
);
Doing it this way is slightly nicer than the "naked" JS approach (in my opinion), and it's a bit safer too.
Thank you for all your responses.
#Electrons_Ahoy and #Steve: You are tight. My problem was that i was putting the checkbox inside the labe, so i did the folowing:
I took the checkbox outside the label, put the onclick trigger on the checkbox only and it works fine.
I also figured out why the trgger fired twice when the checkbox was inside the label and the onclick trigger was on the label :
It was because when i clicked the label a click on the checkbox was simulated and the checkbox being inside the label the click was simulated on the label, duuuuuhhh :)
You probably need to turn on the autopostback property:
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.checkbox.autopostback.aspx
<asp:CheckBox id="checkbox1" runat="server"
AutoPostBack="True"
Text="Include 8.6% sales tax"
TextAlign="Right"
OnCheckedChanged="Check_Clicked"/>