I have a click event handler attached to a group of radio inputs, and want to see if I am clicking on the radio button that is already selected (has property 'checked' set). I figured the event handler would act in a daisy chained fashion (first calling my event handler on the click and then continuing down the chain to the default behavior of the click). Apparently this is not the case, because when I evaluate if the property 'checked' is true on the radio button I just clicked, it always returns true in my click event handler.
The click has already been processed by the default behavior and has already applied the 'checked' property to the radio button I just clicked. Again, I figured my click event handler would be processed prior to that default behavior. What's even more odd is that even when I prevent the default behavior, it still returns true for the 'checked' property. I assume this is because the 'checked' property is being processed by the 'change' event, so preventing the default behavior on my click event handler is not affecting anything.
$("input[type='radio']").click(function(e) {
e.preventDefault();
alert($(this).prop("checked")); // always returns true; i want prop value immediately prior to click
});
How can I achieve what I'm after? That is, to see whether or not the radio button that was just clicked on was the one already checked. Thanks.
Based on the response of #Jeffman , I was able to get something to work for what I needed to do. I have custom buttons, only one of which can be selected (hence the use of radio buttons). However, if you click on the one that's already selected, it should deselect and select the default value instead.
Things I had to do. Handle mousedown events on the radio labels. If I am clicking on the already selected radio, set the default button to be 'checked'. Else I just select the button that has been clicked on. I had to disable the 'click' event on these buttons, as that would override my irregular handling of the radio buttons (for some reason the selection would snap back to the one that was clicked when I overrode it and chose the default one manually). This also meant I would need to manually trigger the change event, as I do the custom radio button styling there.
$(".radios > label").mousedown(function(e) {
var l = $(this); // label
var t = l.parent(); // container for radio group
var i = l.find("input"); // input element of this label
if(i.prop("checked")) { // clicking on the already selected button
t.find(".default_radio input").prop("checked", true).trigger("change");
} else {
i.prop("checked", true).trigger("change");
}
}).bind('click',false);
$("input[type='radio']").change(function(e) {
// style the buttons here
});
Save radio status before click via mousedown
var was_checked;
$( "#radio" ).mousedown(function() {
was_checked = $(this)[0].checked;
});
$( "#radio" ).click(function() {
$(this).attr('checked', !was_checked);
});
i think you should also return false. not only preventDefault
Here is a sample code that would do the trick
<script>
$(function() {
var radios = {};
$("input[type='radio']").each(function() {
radios[$(this).uniqueId().attr('id')] = false;
});
function resetRadioState() {
$("input[type='radio']").each(function() {
radios[$(this).attr('id')] = $(this).is(':checked');
});
}
resetRadioState();
$("input[type='radio']").click(function(e) {
alert(radios[$(this).attr('id')]);
resetRadioState();
});
})
</script>
<input type="radio" name="group[]"/>
<input type="radio" name="group[]" checked/>
Related
I have a checkbox in a sortable div where the click or changed event is triggered twice on touch devices but not on desktop (nor simulating touch on Firefox dev tools) for some obscure reason. The unwanted effect is the checkbox being toggled twice in a row leaving it at its original state. I mention the div is sortable because when they are made no longer sortable the checkbox works just fine. Here is the relevant part:
$sortable.sortable({
items: '.sortable',
cancel: 'input,textarea,button,select,option'
});
I have no idea why the sortable widget makes the click event be fired twice.
My attempts to handle this have been unsuccessful:
I've tried disabling the default behaviour of toggling a the checkbox and setting its value manually. However for some reason the checkbox won't be checked/unchecked. If I do it via console it does work:
// same with the "change" event
// the reason the event is bound to $sortable rather than the inputs themselves is that
// new sortable divs are added dynamically so otherwise they wouldn't have the event bound to them
$sortable.on('click', 'input[type="checkbox"]', function (e) {
e.stopImmediatePropagation();
// this does disable the default behaviour of checking/unchecking the box
e.preventDefault();
const $this = $(this);
// this doesn't check/uncheck the box at all, but setting a global variable to $this and doing it via console does work
$this.prop('checked', !$this.prop('checked'));
});
I have tried a more typical approach using a flag, however there seems to be some race condition (or whatever it's called because if I am not mistaken js is monothreaded) and the function is run twice anyway:
let checked = false;
$sortable.on('click', 'input[type="checkbox"]', function() {
if (checked) return;
// this is output twice, which is not what we are after
console.log('running');
checked = true;
// here ideally we would set the value of the checkbox
checked = false;
});
I have checked for any problematic events bound to the inputs using $._data($checkboxes[0], 'events') but other than a bootstrap tooltip (mouseover and mouseout events) and of course the change event there's nothing else fishy.
edit: Basically it seems that the sortable widget produces a separate click event when you click anywhere in the div or its children. That's the reason why click/change is fired twice.
My question is: how can I discriminate between the originator of the event so that if it's the sortable plugin the event can be ignored, while if it's the listener I set up the checkbox does change its value (and I perform any other actions I may want to perform when the checkbox is actually checked)?
try touchend and if it works for click as well use the following way , else separate it
$sortable.on("touchend click", 'input[type="checkbox"]', function(e) {
if(e.type == 'touchend'){
$(this).off('click');
// your function
}
});
else try this for both
let checked = false;
$sortable.on("touchend click", 'input[type="checkbox"]', function(e) {
if(e.type == "touchend") {
checked = true;
// your function
}
else if(e.type == "click" && !checked ) {
// your function
}
});
I currently have two buttons. I want when one button is clicked both of the buttons get disabled. I want to use only javascript without Jquery.
var button1=document.getElementById("button1").addEventListener('click',function(){
//I want to check if either of the buttons were clicked and disable both of them.//
if(button1||button2===true){
button1.disable=true;
button2.disable=true;
Alert("Button Disable property is in a true state.");
}
});
var button2=document.getElementById("button2").addEventListener('click',function(){
//I want to check if either of the buttons were clicked and disable both of them.//
if(button1||button2===true){
button1.disable=true;
button2.disable=true;
Alert("Button Disable property is in a true state.");
}
});
//I also tried to set the {once : true;} at the end of the event handler but it only works for one button.Which means that I have to press both of them tfor them both to disable.//
<button id="button1">Button1</button>
<button id="button2">button2</button>
You have a number of problems. Firstly, your variables are being set to the return value of addEventListener, not the document element. Secondly, to disable an element, you use element.disabled = true, not element.disable = true. Finally alert is all lowercase, not Alert. There are also optimisations that can be made to your code - for example there is no need to check if button1 or 2 was clicked since if the event listener is called then one of them must have been. Try this instead:
var button1=document.getElementById("button1");
var button2=document.getElementById("button2");
[button1,button2].map(b => b.addEventListener('click',function(){
button1.disabled=true;
button2.disabled=true;
alert("Button Disable property is in a true state.");
}));
<button id="button1">Button1</button>
<button id="button2">button2</button>
i'm confused about the behaviour from an addEventListener response.
In this jsFiddle you can see a Label for a checkbox called "My Profile" and a Popup, which is shown if the checkbox is checked, through the magic of CSS.
I'm trying to make it disappear if the popup is shown and the user clicks outside of the popup div...
But the reason i can't get it to work is, if you click on the label with the id 'header-profile-popup-toggler' first the Body.addEventListener, then bbb2.addEventListener(the checkbox) and afterwards once more the Body.addEventListener is called.
But if you click outside the Label Body.addEventListener is called only once, same as i click on bbb.addEventListener(the div).
Does someone know why the body.addEventListener is called after the bbb2.addEventListener??
For explanation.
Absolutely, i would only call
document.body.addEventListener('click', function(e){
if(bbb2.checked==true&&e.target!=bbb){
bbb2.checked=false;
}
});
Only if the Popup is shown (bbb2.checked==true) and you clicked outside the div (e.target!=bbb) uncheck the checkbox.
But since the body.addEventListener is called once more after bbb2.addEventListener and both statements are true - the checkbox is checked and the checkbox is outside of the popup div - the checkbox is unchecked instantaneous.
Thanks for any Support!
I got it!
Because of the constallation of a label for the checkbox the addEventListener is called for every Element, in this case for the Label and Checkbox with one click.
So, first of all the Label Event is called, then the Body. After that, the Checkbox Event and once more the Body Event are triggered.
I got it!
Because of the constallation of a label for the checkbox the addEventListener is called for every Element, in this case for the Label and Checkbox with one click.
So, first of all the Label Event is called, then the Body. After that, the Checkbox Event and once more the Body Event are triggered.
With the following Script i made a fully functional Popup-Menu, which also works if Javascript is deactivated:
var isOutSide = true,
bbb=document.getElementById('header-profile-popup'),
bbb2=document.getElementById('header-profile-popup-toggler'),
bbb3=document.getElementById('header-profile-popup-toggler-label');
document.body.addEventListener('click', function(){
if(isOutSide){
document.getElementById("header-profile-popup-toggler").checked = false;
}
isOutSide = true;
});
bbb.addEventListener('click', function(){
isOutSide = false;
});
bbb2.addEventListener('click', function(){
isOutSide = false;
});
bbb3.addEventListener('click', function(){
isOutSide = false;
});
On this Fiddle you can test it in Action
Let's say I have a group of two radio buttons:
<input type="radio" name="radioButtonGroup" value="button1" checked="true"/>
<input type="radio" name="radioButtonGroup" value="button2"/>
It seems that clicking the second button triggers an event handler on that button only. However, the first button does become deselected, and visually does change. Can anyone verify that events are fired only on the button that was selected, and not any of the other buttons in the group which become deselected as a result of the click? Any clever ways to watch a radio button for a deselecting event?
Although it cannot be confirmed, but the event change triggers don't happen on the entire group.
If you want that to happen, you can do it using various JS libraries like jQuery, YUI, etc. or even plain javascript, as follows:
function buttonGroupChange(){
var radioElements = document.getElementsByName("radio_group_name");
for(var i = 0; i < radioElements.length; i++){
if(radioElements[i].checked == true){
//do something
}
else{
//do something
}
}
}
This function can be called on the onClick or the onChange event.
I hope that solves your problem.
Firstly, it is important to note that a "Click" event on any of the radios fires AFTER the "checked" value is already updated. This is important - because it means you can't detect the previous item once the event is already fired. If you Cancel the event, you are actually changing the value BACK - not stopping it initially. This is important to how you approach the problem.
Example:
<input type="radio" name="radioButtonGroup" value="button1" checked="true"/>
<input type="radio" name="radioButtonGroup" value="button2"/>
// At this point, the ':checked' item is button1.
$('input[type=radio]').bind('click', function (ev) {
// If you click on button2 - by this point, the ':checked' item is already button2.
ev.preventDefault(); // These two lines will stop the radio from actually
ev.stopPropagation(); // changing selection.
// At this point, the ':checked' item is set BACK to button1.
});
Because of this, the easiest solution is to track the "last" selected item in a closure alongside your event handlers, as follows:
<input type="radio" name="radioButtonGroup" value="button1" checked="true"/>
<input type="radio" name="radioButtonGroup" value="button2"/>
<script type="text/javascript">
var $last = $('[name=radioButtonGroup]:checked');
// Select the radio buttons as a group.
var $radios = $('[name=radioButtonGroup]').bind('change', function (ev) {
// Click event handler
var $clicked = $(ev.target); // This is the radio that just got clicked.
$last.trigger('unclick'); // Fire the "unclick" event on the Last radio.
$last = $('[name=radioButtonGroup]:checked'); // Update the $last item.
// Should see the clicked item's "Value" property.
console.log("Clicked " + $clicked.attr('value'), $clicked, ev);
}).bind('unclick', function (ev) {
// Handler for our new "unclick" event.
// - fires whenever a radio loses focus.
var $unclicked = $(ev.target); // The radio losing it's checked status.
// Should see the unclicked item's "Value" property.
console.log("Unclicked " + $unclicked.attr('value'), $unclicked, ev);
});
</script>
For a working example, see:
http://jsfiddle.net/TroyAlford/wvrtC/
I can't confirm that an event is only fired for the selected button, but if you needed to do something with the button that was just deselected, the following would work:
$(document).ready(function(){
var selectedRadio = null;
$("input:radio").change(function(){
if(selectedRadio != null){
alert(selectedRadio.val());
}
selectedRadio = $(this);
});
});
In action here.
If you need to keep track of multiple groups of radio buttons, you could do it with an array of currently selected buttons and match within that array when a change is detected.
The simple nature of the radio button set is that only one button can be selected at a time. Selecting a button automatically means the others are not selected, but there is no specific action for deselecting. Therefore, you only need to worry about the one event, because it affects all the buttons in the set at one time.
If you would like to use an element that allows for multiple selections try checkboxes.
I have a page with a set of checkbox's, that I want to run a Javascript function on when there is a change (I have done something very similar with dropdown's - and that worked)
However with the checkbox's I have three problems:
my onChange event only runs "sometimes" (you have to change the focus between the different checkbox controls
when it does run it is returning the result of the previous checkbox (not the one just clicked on)
the jQuery always return the value true
Checkbox creation
<%= Html.CheckBox("sl-" + row.Id, value, new { onChange = "SuitabilityChecked("+row.Id+", "+key+")"})%>
Javascript
function SuitabilityChecked(providerId, parentRecordId) {
var params = {};
params.providerId = providerId;
params.parentRecordId = parentRecordId;
var value = $("#sl-" + providerId).val();
params.value = value;
$.getJSON("SuitabilityChecked", params, null);
};
Browsers are funny about radio buttons and check boxes and can delay the onchange until focus change. Try adding an onclick event to blur or call the change event directly.
Maybe something like this using jQuery Live (untested, off the top of my head):
$(':checkbox').live('click', function() { $(this).change(); });
What's happening:
Checkbox A clicked
Checkbox B clicked
Checkbox A has lost focus and fires onChange
Which makes it seem as if Checkbox B is returning the result of Checkbox A. If you were to press Tab after clicking Checkbox B in this scenario, you'd notice that its onChange would fire.