I'm using a bit of JS to limit the amount of checkboxes that a user can select in a form I am working on. With this JS, once the limit of 2 is reached, the remaining checkboxes are greyed out.
However, I am using other JS that removes the actual checkbox so that I can style the form anyway I like, so now when the limit is reached, there is no visual cue that the remaining choices cannot be selected.
I am hoping there is a way to style the text in the remaining choices to grey out when the limit of choices is reached.
Here is the JS I am using that greys out the checkboxes. Can I add a css style to this to do what I need?
$('input:checkbox[name="board_colors[]"]').on('change', function () {
var nightLifeLimit = $('input:checkbox[name="board_colors[]"]:checked').length;
if (nightLifeLimit == 2) {
$('input:checkbox[name="board_colors[]"]').each(function () {
if ($(this).is(':checked')) {
return;
}
else {
$(this).prop('disabled', true);
}
});
}
else {
$('input:checkbox[name="board_colors[]"]').each(function () {
$(this).prop('disabled', false);
});
}
});
HTML for the checkbox section of the form
<fieldset>
<legend>Choose color(s) <small class="fineprint">*choose up to two</small></legend>
<ul>
<li><input type="checkbox" class="checkbox" id="bright_green" value="Bright Green" name="board_colors[]" title="Please choose a color(s)" required minlength="1">
<label for="bright_green">Bright Green</label></li>
<li><input type="checkbox" class="checkbox" id="teal_blue" value="Teal Blue" name="board_colors[]">
<label for="teal_blue">Teal Blue</label></li>
<li><input type="checkbox" class="checkbox" id="sea_blue" value="Sea Blue" name="board_colors[]">
<label for="sea_blue">Sea Blue</label></li>
<li><input type="checkbox" class="checkbox" id="purple" value="Purple" name="board_colors[]">
<label for="purple">Purple</label></li>
<li><input type="checkbox" class="checkbox" id="magenta_dark_pink" value="Magenta Dark Pink" name="board_colors[]">
<label for="magenta_dark_pink">Magenta/Dark Pink</label></li>
<li><input type="checkbox" class="checkbox" id="watermelon_red" value="Watermelon Red" name="board_colors[]">
<label for="watermelon_red">Watermelon Red</label></li>
<li><input type="checkbox" class="checkbox" id="true_red" value="True Red" name="board_colors[]">
<label for="true_red">True Red</label></li>
<li><input type="checkbox" class="checkbox" id="orange" value="Orange" name="board_colors[]">
<label for="orange">Orange</label></li>
</ul>
<span><label for="board_colors[]" class="error"></label></span>
</fieldset>
I'd personally suggest adding a class to the parent <li> element and then styling the text of the <label> using CSS:
$('input:checkbox[name="board_colors[]"]').on('change', function () {
// cache your inputs for repeated access:
var inputs = $('input[type="checkbox"][name="board_colors[]"]'),
// using the cached jQuery object, filtering for the :checked elements:
nightLifeLimit = inputs.filter(':checked').length;
// iterating over each of the elements:
inputs.each(function () {
// 'this' is the current input:
$(this)
// disabling if it's not checked *and* if the limit is reached:
.prop('disabled', !this.checked && nightLifeLimit == 2)
// moving to the closest 'li' ancestor:
.closest('li')
// adding the class if the checkbox is disabled, removing if not:
.toggleClass('disabled', this.disabled);
});
});
JS Fiddle demo.
That said, if you move the <input /> elements before the <label> elements, giving:
<fieldset>
<legend>Choose color(s) <small class="fineprint">*choose up to two</small></legend>
<ul>
<li>
<input type="checkbox" class="checkbox" id="bright_green" value="Bright Green" name="board_colors[]" title="Please choose a color(s)" required="" minlength="1" />
<label for="bright_green">Bright Green</label>
</li>
<!-- others removed for brevity -->
</ul> <span><label for="board_colors[]" class="error"></label></span>
</fieldset>
You could simply use CSS to style the sibling <label> elements:
input[type=checkbox]:disabled + label {
color: #ccc;
}
JS Fiddle demo.
References:
closest().
each().
filter().
toggleClass().
One solution is you set a class to parent element that tells us that the amount of maximum allowable item is selected.
Then apply with css gray text. Example code
CSS
.max-element input:not(:checked) + label {color: lightgray;}
SJ
$('input:checkbox[name="board_colors[]"]').change(function () {
var nightLifeLimit = $('input:checkbox[name="board_colors[]"]:checked').length;
if (nightLifeLimit > 1) {
$('input:checkbox[name="board_colors[]"]').each(function () {
$(this).is(':checked') ? null : $(this).prop("disabled", true);
});
$(this).closest('ul').addClass('max-element');
}
else {
$('input:checkbox[name="board_colors[]"]').prop('disabled', false);
$(this).closest('ul').removeClass('max-element');
}
});
Note: Attribute minlength not allowed on element input. You can use data-minlength="1".
Related
I have been using the following script to check multiple checkboxes at a time, and all is going well:
<script type="text/javascript">
function toggle(source) {
var aInputs = document.getElementsByTagName('input');
for (var i=0;i<aInputs.length;i++) {
if (aInputs[i] != source && aInputs[i].className == source.className) {
aInputs[i].checked = source.checked;
}
}
}
</script>
Some general code where I use this is:
...
<li>surface analysis</li>
<input type="checkbox" id="checkbox_wpc_sfc00" class="wpc_sfc">00Z
<input type="checkbox" id="checkbox_wpc_sfc03" class="wpc_sfc">03Z
<input type="checkbox" id="checkbox_wpc_sfc06" class="wpc_sfc">06Z
<input type="checkbox" class="wpc_sfc" onClick="toggle(this)"> Toggle All surface
<li>upper air analysis</li>
<input type="checkbox" id="checkbox_wpc_ua00" class="wpc_ua">00Z
<input type="checkbox" id="checkbox_wpc_ua03" class="wpc_ua">03Z
<input type="checkbox" id="checkbox_wpc_ua06" class="wpc_ua">06Z
<input type="checkbox" class="wpc_ua" onClick="toggle(this)"> Toggle All upper air
...
This creates a list of 'surface analyses' checkboxes for 00Z, 03Z, 06Z, and an option to select all 3 of these boxes at once. There is another list of the same style but for 'upper air analysis'. This works great the way that this is.
The issue is I now want to create 00Z, 03Z, and 06Z checkboxes. In other words, the 00Z checkbox would mark the 'checkbox_wpc_sfc00' as well as the 'checkbox_wpc_ua00' text. However, I have run into a bit of a wall as I would figure a separate 'toggle' function would work where I use a str.contains('00'), but this seems to be failing. Any thoughts on this? I would like to try and keep this to either HTML or Javascript, if possible.
I think this should do the job:
function toggle(source, aux) {
var aInputs = document.getElementsByTagName('input');
if (aux != "surface and air"){
for (var i=0; i<aInputs.length; i++) {
if (aInputs[i] != source && aInputs[i].className == source.className) {
aInputs[i].checked = source.checked;
}
}
} else {
var sSelection = source.id;
var sType = sSelection.slice(-2);
var sCheckBox, sLast2;
for (var i=0; i<aInputs.length; i++) {
sCheckBox = aInputs[i].id;
sLast2 = sCheckBox.slice(-2);
if (sLast2 == sType) {
aInputs[i].checked = source.checked;
}
}
}
}
<li>surface analysis</li>
<input type="checkbox" id="checkbox_wpc_sfc00" class="wpc_sfc">00Z
<input type="checkbox" id="checkbox_wpc_sfc03" class="wpc_sfc">03Z
<input type="checkbox" id="checkbox_wpc_sfc06" class="wpc_sfc">06Z
<input type="checkbox" class="wpc_sfc" onClick="toggle(this, 'surface')"> Toggle All surface
<li>upper air analysis</li>
<input type="checkbox" id="checkbox_wpc_ua00" class="wpc_ua">00Z
<input type="checkbox" id="checkbox_wpc_ua03" class="wpc_ua">03Z
<input type="checkbox" id="checkbox_wpc_ua06" class="wpc_ua">06Z
<input type="checkbox" class="wpc_ua" onClick="toggle(this, 'air')"> Toggle All upper air
<li>general type selection</li>
<input type="checkbox" id="checkbox_wpc_00" class="wpc_00" onClick="toggle(this, 'surface and air')">00Z
<input type="checkbox" id="checkbox_wpc_03" class="wpc_03" onClick="toggle(this, 'surface and air')">03Z
<input type="checkbox" id="checkbox_wpc_06" class="wpc_06" onClick="toggle(this, 'surface and air')">06Z
Your current method is to pass the "master checkbox" as the sole argument, and use values extracted from it in the control function. This doesn't appear to be necessary. If it was not more than the most expedient manner you saw to accomplish your goal, please comment such that I might provide a better solution.
function toggle(selector, state) {
Array.from(
document.querySelectorAll(selector)
).forEach(
(element)=>element.checked = state
)
}
Contrasted with your current implementation, this expects values to be passed based on your "master checkbox," versus passing the checkbox itself. I'm also using an array function instead of an explicit loop, and I'm using an arrow function. If you're unfamiliar with either, I can provide references.
Use of this would be as follows:
<li>surface analysis</li>
<input type="checkbox" id="checkbox_wpc_sfc00" class="wpc_sfc">00Z
<input type="checkbox" id="checkbox_wpc_sfc03" class="wpc_sfc">03Z
<input type="checkbox" id="checkbox_wpc_sfc06" class="wpc_sfc">06Z
<input type="checkbox" class="wpc_sfc" onClick="toggle(`.${this.className}`,this.checked)"> Toggle All surface
<li>upper air analysis</li>
<input type="checkbox" id="checkbox_wpc_ua00" class="wpc_ua">00Z
<input type="checkbox" id="checkbox_wpc_ua03" class="wpc_ua">03Z
<input type="checkbox" id="checkbox_wpc_ua06" class="wpc_ua">06Z
<input type="checkbox" class="wpc_ua" onClick="toggle(`.${this.className}`,this.checked)"> Toggle All upper air
<li>Toggle Region</li>
<input type="checkbox" class="all_00Z" onClick="toggle(`[id$='00']`,this.checked)">
<input type="checkbox" class="all_03Z" onClick="toggle(`[id$='03']`,this.checked)">
<input type="checkbox" class="all_06Z" onClick="toggle(`[id$='06']`,this.checked)">
The above uses string templates and expression matching selectors. Again, if these are unfamiliar, I can help you find some references.
I have multiple radio buttons, each one inside a <span> with margin, so they seem like a button with a radio element inside. how can I check the radio button when I click anywhere inside the <span> parent element of the radio button
UX oriented
<span class="radio-box" id="white-box">
<input type="radio" id="white" name="colour"> White
</span>
<span class="radio-box" id="red-box">
<input type="radio" id="red" name="colour"> Red
</span>
<span class="radio-box" id="blue-box">
<input type="radio" id="blue" name="colour"> Blue
</span>
sorry, very noob at Javascript
thanks :)
This is exactly what label elements are for. Use those, rather than span elements:
<label class="radio-box" id="white-box">
<input type="radio" id="white" name="colour"> White
</label>
<label class="radio-box" id="red-box">
<input type="radio" id="red" name="colour"> Red
</label>
<label class="radio-box" id="blue-box">
<input type="radio" id="blue" name="colour"> Blue
</label>
When the label wraps the input like that, it's associated with that input. (If you couldn't use wrapping, you could use the for attribute to tell the label what the id of its associated input is.)
You could make it work with spans. Targeting just those spans:
$("span > input[type=radio][name=colour]").parent().on("click", function() {
$(this).find("input[type=radio][name=colour]").prop("checked", true);
});
or targeting any input[type=radio] inside a span.radio-box:
$("span.radio-box > input[type=radio]").parent().on("click", function() {
$(this).find("input[type=radio]").prop("checked", true);
});
But again, this is exactly what label is for, so best to use that.
If you want to do this without the <label> tag and without jquery and just vanilla JavaScript then here's a solution.
var radioBoxes = document.querySelectorAll("span.radio-box");
radioBoxes.forEach(function (box) {
var radioButton = box.querySelector("input[type='radio']");
box.addEventListener("click", function () {
radioButton.click();
});
});
I'm relatively new to JS and was looking for an article or method in which to accomplish the following - be it a form or just JS. (Would like to avoid PHP.)
I have a series of check boxes call them box 1 - 4, which when any one is checked should either show a div or post text to a particular div on the page.
Example: when box 1 is checked div A posts "Box one has been checked."
I'm not certain how to refine my searches to find an example of what I'm looking for but did find a jsfiddle with a similar technique this posts a textbox under the checkbox when activated.
DEMO
<input id="chk" type="checkbox" value="results" />Results
<div id="formContainer"></div>
var textboxId = 0;
function CreateTextbox() {
var textBox = document.createElement("input");
textBox.setAttribute("type", "textbox");
textBox.setAttribute("id", textboxId);
textboxId++;
return textBox;
}
document.getElementById("chk").onclick = function () {
if (textboxId == 0) {
document.getElementById("formContainer").appendChild(CreateTextbox(textboxId));
textboxId = 1;
} else if (textboxId == 1) {
document.getElementById("formContainer").innerHTML = '';
textboxId = 0;
//The code to remove the previosuly made textbox
}
}
Any direction or code ideas are appreciated. Thanks!
Hope this is what you are expecting.
$('.chkbox').on('click',function(){
if($(this).is(':checked')) //check if checkbox is checked or unchecked
{
$(this).next('.formContainer').html('<div class="new">'+$(this).data('detail')+'</div>');
//get detail to add from the clicked checkbox's data-* attribute
}
else
{
$(this).next('.formContainer').html('');
//just empty the html below it
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="chk" data-detail="Box one has been checked." class="chkbox" type="checkbox" value="results" />Results
<div class="formContainer"></div>
<input id="chk2" data-detail="Box two has been checked." class="chkbox" type="checkbox" value="results" />Results
<div class="formContainer"></div>
<input id="chk3" data-detail="Box three has been checked." class="chkbox" type="checkbox" value="results" />Results
<div class="formContainer"></div>
<input id="chk4" data-detail="Box four has been checked." class="chkbox" type="checkbox" value="results" />Results
<div class="formContainer"></div>
Add detail for each checkbox in its data-detail property. Refer html above
Extenal Demo
Update
To display all the text in a single div you can just refer the target element as below:
$('.chkbox').on('click',function(){
if($(this).is(':checked'))
{
$('.formContainer').html('<div class="new">'+$(this).data('detail')+'</div>'); //directly refer the element
}
else
{
$('.formContainer').html('');
}
});
Updated demo
Not sure if this is what you really need, but this should help you get started, It also requires jquery
HTML
<input class="mychk" type="checkbox" value="Box 1 is Check" />Box 1<br>
<input class="mychk" type="checkbox" value="Box 2 Box is Check" />Box 2<br>
<input class="mychk" type="checkbox" value="Box 3 Box is Check" />Box 3<br>
<input class="mychk" type="checkbox" value="Box 4 Box is Check" />Box 4
<div class="showcheck">I'll Be Overwritten When Checkbox is check</div>
jQuery
(function($) {
//run for each input box
$('.mychk').each( function() {
// detect change action
$(this).change( function() {
// if the checkbox is check
if( $(this).is(':checked') ) {
//insert checkbox value in showcontent div
$('.showcheck').html( $(this).val() );
} else {
// if uncheck, assign default value
$('.showcheck').html( 'Default Content' );
}
});
});
})(jQuery);
Demo here
Pure JavaScript answer:
HTML:
<div id="checkboxes">
<input id="one" type="checkbox"></input>
<input id="two" type="checkbox"></input>
<input id="three" type="checkbox"></input>
</div>
<div id="answer"></div>
JS:
[].forEach.call(document.getElementById("checkboxes").children, function(element) {
element.onclick = function () {
document.getElementById("answer").innerHTML = element.id + " " + element.checked;
}
});
JSfidle
I have a bit of code that checks a list if LI tags which contain radio button input's. I have some clever logic via the Chocolate Chip Javascript framework library to work out when an LI is clicked, it will apply a relevant class to display the radio button has been selected.
However, I want to expand that logic so that it digs deeper into the LI and finds which radio button input is the one that is already selected (prior to any user choosing anything) when the page loads and apply a class to it so that it instantly highlights what is already selected.
I'm a bit new to Prototype so I'm not sure what is the best approach to do this so would appreciate any help you can offer.
So in the case below, I want to pick out button 3.
JSFiddle Link: http://jsfiddle.net/Qw6KA/
HTML:
<ul class="radioList">
<li>
<input type="radio" id="radio1" name="radioButton" value="Button 1">
<label for="radio1">Button 1</label>
</li>
<li>
<input type="radio" id="radio2" name="radioButton" value="Button 2">
<label for="radio2">Button 2</label>
</li>
<li>
<input type="radio" id="radio3" name="radioButton" value="Button 3" checked="checked">
<label for="radio3">Button 3</label>
</li>
<li>
<input type="radio" id="radio4" name="radioButton" value="Button 4">
<label for="radio4">Button 4</label>
</li>
</ul>
JS (Prototype):
$.RadioButtons = function( viewSelector, callback ) {
var items = viewSelector + ".radioList li";
var radioButtons = $$(items);
radioButtons.forEach(function(item) {
item.bind("click", function() {
radioButtons.forEach(function(check) {
check.removeClass("selected");
});
this.addClass("selected");
this.last().checked = true;
if (callback) {
callback(item);
}
});
});
};
Thanks
-JaXL
$.RadioButtons = function( viewSelector, callback ) {
var items = viewSelector + ".radioList li";
var radioButtons = $$(items);
radioButtons.forEach(function(item) {
item.bind("click", function() {
radioButtons.forEach(function(check) {
check.removeClass("selected");
});
this.addClass("selected");
this.last().checked = true;
if (callback) {
callback(item);
}
});
// Add this bit
if (item.select('input[checked]').length) {
item.addClassName('selected');
}
});
};
Here's my HTML:
<ul>
<li>
<p><label><input type="checkbox" name="permission" value="1" class="permission_check" checked> Joe Schmoe</label></p>
<p class="radio_option"><label><input type="radio" name="viewpromote" value="1"> View and Promote</label></p>
<p class="radio_option"><label><input type="radio" name="createedit" value="1" checked> ...plus Create and Edit</label></p>
</li>
<li>
<p><label><input type="checkbox" name="permission" value="1" class="permission_check" checked> Bob Smith</label></p>
<p class="radio_option"><label><input type="radio" name="viewpromote" value="1" checked> View and Promote</label></p>
<p class="radio_option"><label><input type="radio" name="createedit" value="1"> ...plus Create and Edit</label></p>
</li>
</ul>
What I need to do is when a user checks/unchecks the permission_check input, then it should show/hide the radio_option elements for that list item.
$('.permission_check').change(function(){
$(this).closest('li').find('.radio_option').toggle(this.checked);
}).change();
Calling change() will trigger the callback once when the code is loaded to initialize the visibility correctly.
DEMO
Reference: change, closest, find, toggle
$('input[type="checkbox"]').change(function() {
$(this).closest('li').find('input[type="radio"]').toggle($(this).is(':checked'));
});
$(".permission_check").change(function() {
var $options = $(this).parents("li").find("p.radio_option");
if ($(this).is(":checked")) {
$options.show();
}
else {
$options.hide();
}
}
something like that:
$('.permission_check').change(function(){
$(this).parents('li').find('.radio_option').toggle();
});
Add the ID attributes to the radio button and then
Using Javascript, you can do:
function showhideOnClick() {
if(permission == true)
document.getElementById("radioControlID").style.display = "none";
else
document.getElementById("radioControlID").style.display = "block";
}