I'm trying to uncheck a radio button wrapped with a label in a button group like this:
<div>
<label class="btn btn-primary">
<input type="radio" name="radio1" class="radio1" />
Radio1
</label>
</div>
<div>
<label class="btn btn-primary">
<input type="radio" name="radio2" class="radio2" />
Radio2
</label>
</div>
$('.btn').on('click', function(e) {
// Check if another option was previously checked
if ($(this).parent().parent().find(':radio:checked').length == 1) {
inner_input = $(this).find('input');
if (inner_input.prop('checked')) {
e.stopImmediatePropagation();
e.preventDefault();
inner_input.prop('checked', false);
$(this).removeClass('active');
}
});
Unfortunately it doesn't work and the label is still active even after the second click.
The solution in current answer works well for radio inputs. But it didn't work for button groups. To save other searchers of trouble, following code might be helpful:
$('label').click(function(e) {
e.preventDefault();
var radio = $(this).find('input[type=radio]');
if (radio.is(':checked')) {
e.stopImmediatePropagation();
$(this).removeClass("active");
radio.prop('checked', false);
} else {
radio.prop('checked', true);
}
});
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<div class="btn-group btn-group-toggle" data-toggle="buttons">
<label class="btn btn-outline-secondary active">
<input type="radio" name="options" id="option1" autocomplete="off" checked>
option 1
</label>
<label class="btn btn-outline-secondary">
<input type="radio" name="options" id="option2" autocomplete="off">
option 2
</label>
<label class="btn btn-outline-secondary">
<input type="radio" name="options" id="option3" autocomplete="off">
option 3
</label>
</div>
Why this happens?
Let's first see what are click, mouseup and mousedown events :
mousedown
Fires when the user depresses the mouse button.
mouseup
Fires when the user releases the mouse button.
click
Fires when a mousedown and mouseup event occur on the same element.
Fires when the user activates the element that has the keyboard focus
(usually by pressing Enter or the space bar).
So When using click event, the radio button is checked, it means that radio.is(':checked') will always return true unless you disable default behavior. So you can do what you want in 2 ways :
1- With Mouseup event, in this case you can determine the state of radio button wether it's checked or not.But in this way you need one little extra code to disable the default behvaior of click event
$('label').on('mouseup', function(e){
var radio = $(this).find('input[type=radio]');
if( radio.is(':checked') ){
radio.prop('checked', false);
} else {
radio.prop('checked', true);
}
});
// Disable default behavior
$('label').click(function(e){
e.preventDefault();
});
Fiddle
And 2 , You can wrap it all together, disable click's default behavior and do the rest in one event:
$('label').click(function(e) {
e.preventDefault();
var radio = $(this).find('input[type=radio]');
if (radio.is(':checked')) {
radio.prop('checked', false);
} else {
radio.prop('checked', true);
}
});
Fiddle
I did answer this question using 2 different events with a purpose, sometimes in more complex problems you may be forced to use the mouseup event instead of click
Related
I have this simple script: it reads the value of quantity input and if it's greater than 5, jQuery will automatically select radio button #2. If the value of quantity is lesser than 5, it will select radio button #1.
Now my problem is that this script makes radio buttons unclickable, because their state is strictly tied to the script. But I would like it if clicking on radio button #2 would change value of the input to 5 and click on the radio button #1 would change it to 1.
In other words, I would like this script to work both ways and to not lock my buttons.
$('.mycontainer').on('click', function() {
if (parseInt($('#quantity').val(), 10) >= '5') {
$('#2radio').prop('checked', true);
}
else {
$('#1radio').prop('checked', true);
}
}).click();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="mycontainer">
<input type="number" id="quantity" name="quantity" value="1"><br><br>
<input type="radio" id="1radio" name="radio"><label for="1radio">radio button #1</label><br><br>
<input type="radio" id="2radio" name="radio"><label for="2radio">radio button #2</label>
<div>
Whenever you check a radio, the event is bubbling up and triggering the .mycontainer function, and since the value isn't changed, it reselects the other radio.
You just have to implement the new handlers for the radios. Since they will change the input number, when the function triggers the radio that the condition would select will be already selected.
If you want to prevent the event from bubbling and trigger the other function altoghether you can call stopPropagation.
Another option is to target #quantity directly instead of .mycontainer, and the function won't fire, since it's a sibling and not an ancestor element.
$('.mycontainer').on('click', function() {
if (parseInt($('#quantity').val(), 10) >= '5') {
$('#2radio').prop('checked', true);
} else {
$('#1radio').prop('checked', true);
}
})
$('[type=radio]').click(function(e) {
e.stopPropagation();
$('#quantity').val($(this).val());
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="mycontainer">
<input type="number" id="quantity" name="quantity" value="1"><br><br>
<input type="radio" id="1radio" name="radio" value="1"><label for="1radio">radio button #1</label><br><br>
<input type="radio" id="2radio" name="radio" value="5"><label for="2radio">radio button #2</label>
<div>
Not sure why the script doesn't work. Want it to uncheck one box when you try to select more than two. For example if you select CHEAP and FAST and then try and select GOOD, FAST is then unchecked.
document.querySelector('body').className = 'has-js';
var checked = [];
[].forEach.call(document.querySelectorAll('input[type="checkbox"]'), function (checkbox) {
checkbox.addEventListener('change', function (e) {
ga('send', 'event', 'checkbox', 'trigger');
if (checkbox.checked && checked.length === 2) {
var uncheckTarget = checked[Math.floor(Math.random() * checked.length)];
uncheckTarget.checked = false;
}
checked = document.querySelectorAll('input[type="checkbox"]:checked');
});
});
<div class="container">
<input type="checkbox" id="fast">
<label class="red" for="fast">FAST</label>
<input type="checkbox" id="good">
<label class="green" for="good">GOOD</label>
<input type="checkbox" id="cheap">
<label class="blue" for="cheap">CHEAP</label>
</div>
Your solution seems to be overly complicated. Also, you should use the click event instead of the change event for your callback because by the time change occurs, the checkmark is already present in the checkbox, so now you'd have to remove it. With click, you can just cancel the event, which occurs prior to the checkmark going into the checkbox.
var boxes = Array.prototype.slice.call(document.querySelectorAll('input[type="checkbox"]'));
boxes.forEach(function(chk) {
chk.addEventListener('click', function (e) {
if (document.querySelectorAll("input[type=checkbox]:checked").length > 2) {
e.preventDefault();
alert("You already have 2 checkboxes checked. Uncheck one and try again!");
}
});
});
<div class="container">
<input type="checkbox" id="fast"><label class="red" for="fast">FAST</label>
<input type="checkbox" id="good"><label class="green" for="good">GOOD</label>
<input type="checkbox" id="cheap"><label class="blue" for="cheap">CHEAP</label>
</div>
I have a boostrap toggle with the code below. It is visually working right
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-primary active">
<input type="radio" name="options" id="showBuildQuantity" autocomplete="off" checked>Build Quantity
</label>
<label class="btn btn-primary">
<input type="radio" name="options" id="showNumberOfScreens" autocomplete="off" onclick="showBuildQuantity()">Number of Screens
</label>
</div>
Below it I have some code to handle click events:
$(document).ready(function () {
$('#showBuildQuantity').on('click', function () {
<code here>
});
$('#showNumberOfScreens').on('click', function () {
<code here>
});
});
The issue I am having is that the click event's are never run when I click the toggle buttons.
I have other buttons on the same page using the same kind of jQuery click event and they do not have an issue.
After some research I found I need to use change instead of click. So the code should look like this:
$('#showBuildQuantity').on('change', function () {
if (myChart != null) {
myChart.destroy();
}
setChart(getBuildQuantityData);
});
$('#showNumberOfScreens').on('change', function () {
if (myChart != null) {
myChart.destroy();
}
setChart(getNumScreensData);
});
I'm working on a little script that will disable a form field if certain radio button are ticked or if the input filed has characters to disable the radio buttons
So what I'm wanting my code to do is when the User enters the text field and adds at least one character of any type to disable the radio buttons and if that field is cleared to re-enable the radio buttons
For some reason when I'm doing either or, my "Enabled" alert keeps showing and the radio buttons aren't being disabled
to get the alert to pop, need to click outside of the input field, I would like this to be a mouseout if possible but I can work on that later
If the value is entered within the form directly, the radio buttons are disabled but I can't get them enabled once the filed is cleared
Steps:
Enter text in text field, if value isn't set in the form. Radio buttons stay disabled
Enter Value within the form, the text buttons stay disabled when the text field is cleared
Working Parts:
If radio btn "Yes" is ticked display "test" string and disable text field
If Radio btn "No" is ticked then enable text field
jQuery version in use: 1.9
Below is my JavaScript and below that is the HTML
Script:
$(function() {
var tlHeader = 'Test';
var f2 = $('#field_2').val();
// This function controls inpput box toggling on/off radio buttons
$( '#field_2' ).change(function() {
if(f2.length != 0) {
alert( "Disabled" )
$("input[name=toggle]").prop('disabled', true)
} else if(f2.length == 0) {
alert( "Enabled" )
$("input[name=toggle]").removeProp('disabled')
};
});
window.invalidate_input = function() {
// This function controls radio btn actions
if ($('input[name=toggle]:checked').val() == "Yes") {
$('#field_2').attr('disabled', 'disabled'),
$('#thgtLdr').html( tlHeader );
$('#thgtLdr').not("No").show();
} else if ($('input[name=toggle]:checked').val() == "No") {
$('#field_2').removeAttr('disabled'),
$('#thgtLdr').not("Yes").hide();
}
};
$("input[name=toggle]").change(invalidate_input);
invalidate_input();
});
</script>
HTML:
<body>
<div id=rdTest>
<div class="inputField">
<label>Focal Image:</label>
<input name="FocalImage" type="text" id="field_2" class='textbox' value="" />
</div> <!-- End input field -->
<div class="radioGroup">
<label>Test Page:</label>
<input type='radio' name='toggle' value='Yes' id="tglyes"/>Yes
<input type='radio' name='toggle' value='No' id="tglno"/>No
</div>
<div id="thgtLdr">
</div>
</div>
</body>
Your use case isnt entirely clear but I'll show you how to achieve the basic goal.
First, I would avoid the mouse events and use keyup with a timer so that my function is only called when the user stops typing and not after each typed letter. Then it's just a mater of checking the text and acting to enable or disable the elements. Here is an example:
var keyupDelay = (function(){
var timer = 0;
return function(callback, ms){
clearTimeout (timer);
timer = setTimeout(callback, ms);
};
})();
$('#field_2').keyup(function() {
var $this=$(this);
keyupDelay(function(){
var val=$this.val();
console.log(val);
if(val=='') $('#tglyes, #tglno').prop('disabled',true);
else $('#tglyes, #tglno').prop('disabled',false);
}, 400 ); // triggered after user stops typing for .4 seconds, adjust value as needed
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id=rdTest>
<div class="inputField">
<label>Focal Image:</label>
<input name="FocalImage" type="text" id="field_2" class='textbox' value="" />
</div>
<!-- End input field -->
<div class="radioGroup">
<label>Test Page:</label>
<input type='radio' name='toggle' value='Yes' id="tglyes" disabled="true"/>Yes
<input type='radio' name='toggle' value='No' id="tglno" disabled="true"/>No
</div>
<div id="thgtLdr">
</div>
</div>
Try this
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<script>
$(document).ready(function(){
$(document).on('click','.choice',function(){
if($(this).val() == 'yes')
{
$('.textfield').prop('disabled',true);
$('#string').html('Test Welcome');
}
else
{
$('.textfield').prop('disabled',false);
$('#string').html('');
}
});
$(document).on('keyup','.textfield',function(){
if($(this).val().length > 0)
{
$('.choice').each(function()
{
if($(this).is(':checked'))
{
$(this).attr('checked',false);
}
$(this).prop('disabled',true);
});
}
else
{
$('.choice').prop('disabled',false);
}
});
});
</script>
<body>
<form>
<input type="text" class="textfield" placeholder="enter text"/>
Yes<input type="radio" name="choice" class="choice" value="yes" />
No<input type="radio" name="choice" class="choice" value="no" />
<p id="string" ></p>
</form>
</body>
You can simplify your code in many ways.
The keyup event will be triggered every time the user releases a key on the text field. Inside the callback, you can get the value of the text field with this.value. From experience, it is best to use .prop() method when toggling certain input-related attributes like disabled and checked. You can enable/disable these attributes using booleans.
// cache the elements to avoid having retrieve the same elements many times
var $textbox = $('#field_2'),
$radios = $('input[name=toggle]'),
$div = $('#thgtLdr');
// everytime user presses a key...
$textbox.on('keyup', function() {
// check if a value was entered or not
// if so, disabled the radio buttons; otherwise enable the radio buttons
$radios.prop('disabled', this.value);
});
// when radio buttons change...
$radios.on('change', function () {
// check if value is Yes or No
if (this.value === 'Yes') {
$textbox.prop('disabled', true);
$div.text(this.value);
} else {
$textbox.prop('disabled', false);
$div.empty();
}
});
<div id=rdTest>
<div class="inputField">
<label>Focal Image:</label>
<input name="FocalImage" type="text" id="field_2" class="textbox" value="">
</div>
<div class="radioGroup">
<label>Test Page:</label>
<input type="radio" name="toggle" value="Yes" id="tglyes">Yes
<input type="radio" name="toggle" value='No' id="tglno">No
</div>
<div id="thgtLdr"></div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script> // place code here </script>
Also, get into the habit of caching your jQuery objects.
How can I disable Bootstrap 3 radio buttons? If I start with the BS3 example and add disabled="disabled" to each input element, there are no changes in appearance or behavior:
<div class="container">
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-primary active">
<input type="radio" name="options" id="option1" autocomplete="off" checked disabled="disabled">Radio 1 (preselected)</label>
<label class="btn btn-primary">
<input type="radio" name="options" id="option2" autocomplete="off" disabled="disabled">Radio 2</label>
<label class="btn btn-primary">
<input type="radio" name="options" id="option3" autocomplete="off" disabled="disabled">Radio 3</label>
</div>
Demo: JSFiddle.
I guess this is because the disabled attribute is only applied to the now-invisible button and not the clickable text label, but I don't see anything in the BS3 docs about this.
Add disabled class to the label like this
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-primary disabled">
<input type="checkbox" autocomplete="off"> Checkbox 1 (pre-checked)
</label>
<label class="btn btn-primary active disabled">
<input type="checkbox" autocomplete="off"> Checkbox 2
</label>
<label class="btn btn-primary disabled">
<input type="checkbox" autocomplete="off"> Checkbox 3
</label>
</div>
Here is a demo
As mentioned by #giammin in the comments to the accepted answer, setting 'disabled' on the input elements doesn't work in 3.3.6 of bootstrap. (Current version at time of publication of this answer).
I was having exactly the same issue, and my solution was to use the CSS property "pointer events". This makes sure the element and children are never a target of click events. However this is not a foolproof solution - users can still tab in and use space to click the hidden elements on a desktop browser.
.disabled-group
{
pointer-events: none;
}
If you set this on your '.btn-group' element, you'll completely disable
<div class="btn-group disabled-group" data-toggle="buttons">
<label class="btn btn-primary disabled">
<input type="checkbox" autocomplete="off"> Checkbox 1 (pre-checked)
</label>
<label class="btn btn-primary disabled">
<input type="checkbox" autocomplete="off"> Checkbox 2
</label>
<label class="btn btn-primary disabled">
<input type="checkbox" autocomplete="off"> Checkbox 3
</label>
</div>
The '.disabled' class is then optional - use it for graying out and 'cursor: not-allowed;' property.
The discussion of the fix solution is at this source:
https://github.com/twbs/bootstrap/issues/16703
For radio button groups, add class disabled to the one you wish disabled.
Make sure you have something like this code:
$('.btn-group').on("click", ".disabled", function(event) {
event.preventDefault();
return false;
});
This will get all your .disabled classed buttons inside the button groups also disabled. This works also for radio type button groups.
You can use the above to disable an input[type='radio'] that is inside a label (bootstrap 3 style),
$("input[name='INPUT_RADIO_NAME']").prop("disabled", true);
$("input[name='INPUT_RADIO_NAME']").closest("div").css("pointer-events", "none");
The above to enable again,
$("input[name='INPUT_RADIO_NAME']").prop("disabled", false);
$("input[name='INPUT_RADIO_NAME']").closest("div").css("pointer-events", "auto");
You can also extend JQuery and create a dummy disable method (that you could upgrade with more functionality) like this,
(function ($) {
$.fn.disableMe = function () {
// Validate.
if ($.type(this) === "undefined")
return false;
// Disable only input elements.
if ($(this).is("input") || $(this).is("textarea")) {
// In case it is a radio inside a label.
if ($(this).is("[type='radio']") && $(this).parent().is("label.btn")) {
$("input[name='safeHtml']").closest("label").addClass("disabled");
$(this).closest("div").css("pointer-events", "none");
}
// General input disable.
$(this).prop("disabled", true);
}
};
$.fn.enableMe = function () {
// Validate.
if ($.type(this) === "undefined")
return false;
// Enable only input elements.
if ($(this).is("input") || $(this).is("textarea")) {
// In case it is a radio inside a label.
if ($(this).is("[type='radio']") && $(this).parent().is("label.btn")) {
$("input[name='safeHtml']").closest("label").removeClass("disabled");
$(this).closest("div").css("pointer-events", "auto");
}
// General input enable.
$(this).prop("disabled", false);
}
};
$.fn.toggleDisable = function () {
if ($.type(this) === "undefined")
return false;
// Toggle only input elements.
if ($(this).is("input") || $(this).is("textarea")) {
var isDisabled = $(this).is(":disabled");
// In case it is a radio inside a label.
if ($(this).is("[type='radio']") && $(this).parent().is("label.btn")) {
$("input[name='safeHtml']").closest("label").toggleClass("disabled");
$(this).closest("div").css("pointer-events", isDisabled ? "auto" : "none");
}
// General input enale.
$(this).prop("disabled", !isDisabled);
}
};
}(jQuery));
Usage example,
$("input[name='INPUT_RADIO_NAME']").disableMe();
$("input[name='INPUT_RADIO_NAME']").enableMe();
$("input[name='INPUT_RADIO_NAME']").toggleDisable();
In bootstrap if you want to disabled any input type or button, You just have to add bootstrap's .disabled class then your button become disabled.
Like this
<input type="radio" class="btn btn-primary disabled">Primary Button</button>