Limit number of boxes checked when arrays are involved - javascript

I'm pretty amateurish when it comes to JavaScript stuff, so I apologize if this question comes off as a bit dumb.
I'm currently trying to code something that involves forms with a limit on how many checkboxes can be selected. The method I've come across that has worked best for my purposes so far is the one detailed here:
http://www.javascriptkit.com/script/script2/checkboxlimit.shtml
It works for the most part but I run into an issue when checkboxes need to output an array. For example, if I write the input line as:
<input type="checkbox" name="choice[]" value="One" /> One<br />
<input type="checkbox" name="choice[]" value="Two" /> Two<br />
<input type="checkbox" name="choice[]" value="Three" /> Three<br />
I've tried quite a few things but I can't figure out how to change the code so that it works with the brackets in the input's name field.

Couple things here:
The tutorial references checkboxlimit(document.forms.world.countries, 2). This will not work with []. You can use getElementsByClassName
It doesn't look like this will work as expected if you uncheck a box because it works on 'onclick', and never increases the number of checked boxes.
I've adapted the code in this fiddle: https://jsfiddle.net/ad8t5sju/
What I changed:
var elems = form.getElementsByClassName('checkbox');
I used getElementsByClassName here so that we can easily fetch the checkboxes that are the particular form's children. HTMLElement only has getElementsByTagName and getElementsByClassName unfortunately, so we can't easily use names here.
for (var i = 0; i < elems.length; i++) {
if (elems[i].checked) {
++count;
}
You'll see here that I take into account the already checked boxes. That way if you have 1 checked by default, you can check another 4 if your limit is 5.
elems[i].addEventListener('click', function() {
if (this.checked) {
if (count + 1 > limit) {
alert ("no more than " + limit + " must be checked");
this.checked = false;
return false;
}
++count;
} else {
--count;
if (count < 0) {
count = 0;
}
}
});
Here, instead of adding 0 when a box is being unchecked, we reduce the count. That's so the same box won't count twice if we untick and tick again.

Using that script above, you can change it into using .elements to get the group of elements and applying that same custom function:
<script type="text/javascript">
// Syntax: checkboxlimit(checkbox_reference, limit)
var world_form = document.forms.choices; // the form
var my_checkboxes = world_form.elements['choice[]']; // check boxes
checkboxlimit(my_checkboxes, 2);
</script>
Fiddle

Simple and easy way
<form id="world" name="world">
<input type="checkbox" name="countries[]" /> USA<br />
<input type="checkbox" name="countries[]" /> Canada<br />
<input type="checkbox" name="countries[]" /> Japan<br />
<input type="checkbox" name="countries[]" /> China<br />
<input type="checkbox" name="countries[]" /> France<br />
<input type="submit" />
</form>
<script type="text/javascript">
$('input:checkbox').change(function() {
var limit = 2;
if($("[type='checkbox']:checked").length > limit)
{
alert("You can only select a maximum of "+limit+" checkboxes")
this.checked=false;
}
});
</script>

Related

Automatically checking / unchecking parent inputs

I'm hoping someone can help me out here.
I'm trying to automatically check parent items in an input list, but also uncheck children if the parent is unchecked.
The great thing is I found some code that replicates the desired functionality perfectly: http://jsfiddle.net/3y3Pb/14/
EDIT: To clarify - the functionality required is this: Check mark a child input & all of the parent items get checked. Uncheck a Parent - all child inputs get unchecked. See the above example.
However, this doesn't seem to be working with my particular code (it's output from a WordPress plugin - Advanced Custom Fields) so I don't want to modify it).
I've narrowed it down to what I BELIEVE is the problem. ACF wraps each input with a <label></label>. I don't know why, but this breaks the functionality:
http://jsfiddle.net/3y3Pb/223/
When I remove the <label></label> it works fine:
http://jsfiddle.net/3y3Pb/225/
Changing the markup isn't really an option here, I would REALLY appreciate it if someone could assist me in making this work!
This should work, its simple and only uses divs and a few lines of jquery:
$('[type="checkbox"]').change(function () {
var kids = $(this).next().next();
if (kids.is('div') && !$(this).prop('checked'))
{
kids.children().each(function(){$(this).prop('checked',false)});
}
var thisChecked = $(this).prop('checked');
var master = $(this).parent().prevAll('[type="checkbox"]:first');
master.prop('checked', thisChecked ? true : master.prop('checked'));
});
div {
margin-left: 25px;
}
div div {
margin-left: 25px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="checkbox" />Master Check
<br />
<div>
<input type="checkbox" />Slave Check 1
<br />
<input type="checkbox" />Slave Check 2
<br />
<input type="checkbox" />Slave Check 3
<br />
<div>
<input type="checkbox" />Slave 2 Check 1
<br />
<input type="checkbox" />Slave 2 Check 2
<br />
<input type="checkbox" />Slave 2 Check 3</div>
</div>
I have improved the javascript code.
$(document).ready(function() {
$('input[type=checkbox]').click(function(){
// if is checked
if($(this).is(':checked')){
$(this).parents('ul').children('li').children('label').find('input').prop('checked', true);
} else {
// uncheck all children
$(this).closest('li').find('input').prop('checked', false);
}
});
});
Children travels a single level down the DOM tree, whereas find goes for multiple levels down looking into descendants.
It was the label - here is the solution:
$('input[type=checkbox]').click(function(){
// if is checked
if($(this).is(':checked')){
$(this).parents('li').children('label').find('input[type=checkbox]').prop('checked', true);
} else {
// uncheck all children
$(this).closest('li').find('input[type=checkbox]').prop('checked', false);
}
});

onclick() action is not responding

I'm creating a survey-like page. I use three basic JavaScript functions, goNext(i) which hides a certain div tags and shows the next, goPrevious(i), which pretty much does the same but backwards, and answerExists(questionNumber) which checks if all radio buttons are checked. From the point I created answerExists(), goNext() and I suppose goPrevious() too, stopped responding. Maybe it's something to do with the onsubmit() function, but I can't figure it out. These are the JavaScript functions:
function goNext(i) {
document.getElementById("div" + i).style.display = 'none';
document.getElementById("div" + (i + 1)).style.display = 'block';
}
function goPrevious(i) {
document.getElementById("div" + i).style.display = 'none';
document.getElementById("div" + (i - 1)).style.display = 'block';
}
function checkAnswers(questions) {
var answers = new Array(questions);
for(var i = 1; i <= questions; i++){
answers[i-1] = false;
var radio = document.getElementsByClassName('Radio' + i);
for (var j=0; j < radio.length; j++) {
if(radio[j].checked == true)
alert(radio[j].value)answers[i-1] = true;
}
for (var i = 0; i < questions; i++){
if(answers[i] == false){
alert("Please answer all questions.");
return false;
}
}
return true;
}
And this is the HTML form:
<form id="content" action="getresults.jsp" method="post" onsubmit="return checkAnswers(2);">
<div id="div1" style="display: block;">
<strong>1. Question 1</strong><br><br>
<input id="radio1" class="radio1" name="radio1" onclick="if (this.__chk) this.checked = false" onmousedown="this.__chk = this.checked" type="radio" value="Answer1" />
Answer1<br><br><br><br>
<div class="auto-style1">
<input name="next" onclick="goNext(1);" type="button" value="Next" />
</div>
</div>
<div id="div2" style="display: none;">
<strong>2. Question 2</strong><br><br>
<input id="radio2" class="radio2" name="radio2" onclick="if (this.__chk) this.checked = false" onmousedown="this.__chk = this.checked" type="radio" value="Answer 2" />
Answer 2<br><br>
<input id="radio2" class="radio2" name="radio2" onclick="if (this.__chk) this.checked = false" onmousedown="this.__chk = this.checked" type="radio" value="dfgdgfdgf" />
dgfgddgf<br><br><br><br>
<div class="auto-style1">
<input name="previous" onclick="goPrevious(2);" type="button" value="Previous" />
<input name="submit" type="submit" value="Submit" />
</div>
</div>
</form>
It is actually all created dynamically, but still, it worked before I added the checkAnswers() function.
The problem is that you have syntax errors in your checkAnswers function, and the interpreter discards any scripts that contain syntax errors, so all your other functions get discarded, too.
These are the two syntax errors:
alert(radio[j].value)answers[i-1] = true; is not a valid statement. (I'm guessing that you intended to delete the alert(radio[j].value) part, but highlighted the wrong thing?)
You have more left-curly-braces { than right-curly-braces }.
Once you fix both of these issues, the script should at least run (though you may still have some debugging to do).
You are calling checkAnswers with a 2 as parameter and build an array with it. ????
The code below will show the mistake.
try{
//your code
}catch(er){
alert(er);
}
I like to answer you step by step....
1) Why do you really need to check whether answers for all questions are checked?
I asked you this because radio buttons will have selected an option by default... or you can make an "active" thing for a particular option... By doing this you really don't need to check whether all questions are answered... since by default one answer is selected...
2) The click event doesnt work because it seems you don't have any "id" for input tags "next","previous","submit"... Have separate id's for each and capture the click event of that particular tag by using jquery...
eg. Have an id for next <input id="next">
$("#next").click(function() {
//perform the action you need
}
Do this for all click events....
3) Finally... don't use input tags for elements you like to click... Try using button tags...
Hope it ll help you :)...

How to know which radio is checked from a fieldset

I have the following code:
<fieldset id="dificuldade">
<legend>Dificuldade:</legend>
<input type="radio" name="dificuldade" value="facil"> Fácil </input>
<input type="radio" name="dificuldade" value="medio"> Médio </input>
<input type="radio" name="dificuldade" value="dificil"> Difícil </input>
</fieldset>
<fieldset id="tipo">
<legend>Tipo de jogo:</legend>
<input type="radio" name="Tipodejogo" value="somar"> Somar </input>
<input type="radio" name="Tipodejogo" value="subtrair"> Subtrair </input>
<input type="radio" name="Tipodejogo" value="dividir"> Dividir </input>
<input type="radio" name="Tipodejogo" value="multiplicar"> Multiplicar </input>
</fieldset>
<input type="button" value="Começa" id="button" ></input>
</form>
and here is the jsfiddle with both the html and the js http://jsfiddle.net/3bc9m/15/ . I need to store the values of the 2 fieldset so I, depending on the values picked can generate a game, but my javascript isn't returning any of them. What is wrong? I've been told that JQuery is much easier but i can't use it.
Your code on jsFiddle seems to be working fine for the most part. The only thing was that the elements output and output2 don't exist on the page.
So this code that was supposed to display the selected values wasn't working:
document.getElementById('output').innerHTML = curr.value;
document.getElementById('output2').innerHTML = tdj.value;
The part that actually retrieves the selected values is working fine.
Just add those two elements to the page, like this:
<p>Selected Values:</p>
<div id="output"></div>
<div id="output2"></div>
An updated jsFiddle can be found here.
EDIT
If a radio button from only one of the sets is selected, the code fails. You could use this code to find the selected values instead:
document.getElementById('button').onclick = function() {
var dif = document.getElementsByName('dificuldade');
var tip = document.getElementsByName('Tipodejogo');
var difValue;
for (var i = 0; i < dif.length; i++) {
if (dif[i].type === "radio" && dif[i].checked) {
difValue = dif[i].value;
}
}
var tipValue;
for (var i = 0; i < tip.length; i++) {
if (tip[i].type === "radio" && tip[i].checked) {
tipValue = tip[i].value;
}
}
document.getElementById('output').innerHTML = difValue;
document.getElementById('output2').innerHTML = tipValue;
};​
An updated jsFiddle is here.
Consider this post that adresses the issue. It shows a few javascript methods as well as how you would use it in jQuery.
How can I check whether a radio button is selected with JavaScript?
Is there a specific reason you want to break it down by fieldset instead of directly accessing the radio buttons by name?

Check to see if none of the checkboxes was checked in jquery

I have two checkboxes and one of the checkboxes must be checked. I can see that it's right, no syntax errors. What should be made to my code to check if none of the checkboxes were checked?
HTML :
<input type="checkbox" value="aa" class="first" name="a"> Yes<br/>
<input type="checkbox" value="bb" class="second" name="b"> No <br/>
<button type="submit">Go!</button>
<p class="error"></p>
JavaScript:
$('button').on('click',function(){
if( $(".first:not(:checked)") && $(".second:not(:checked)") ){
$('.error').text('You must select atleast one!');
}else
$('.error').hide();
});
Example : http://jsfiddle.net/ptbTq/
Check this fiddle: http://jsfiddle.net/692Dx/
Checking code:
if($('input[type="checkbox"]:checked').length == 0) {
alert('none checked');
}
You are using selectors which do not return boolean values which is what you need when writing an if condition. Here's what you could do:
$('button').on('click',function() {
if(!$(".first").is(":checked") && !$(".second").is(":checked")) {
$('.error').text('You must select atleast one!').show();
} else {
$('.error').hide();
}
});
or if you prefer and think it could be more readable you could invert the condiciton:
$('button').on('click',function() {
if($(".first").is(":checked") || $(".second").is(":checked")) {
$('.error').hide();
} else {
$('.error').text('You must select atleast one!').show();
}
});
Also notice that you need to .show() the error message in the first case as you are hiding it in the second.
And here's a live demo.
Short:
$("input[type=checkbox]").is(":checked")
returns true if:
one of your checkboxes - from the selector ("input[type=checkbox]") - is checked.
else return false
and in your case:
$(".first, .second").is(":checked")
Do something at least one of your checkboxes is checked
Put the same class on both checkboxes and you can do something like
if ($(':checkbox.the_class:checked').length > 0) {
// at least one checkbox is checked
// ...
}
The best would be to put your checkboxes inside a div with an unique ID so you can verify all the checkboxes in there, so your code will work in all cases. Even when adding new checkboxes to the div later on.
<div id="cb">
<input type="checkbox" value="aa" class="first" name="a" /> Yes<br/>
<input type="checkbox" value="bb" class="second" name="b" /> No <br/>
<button type="submit">Go!</button>
<p class="error"></p>
</div>
Your JQuery:
$('button').click(function() {
var checked_one = $('div#cb input[type="checkbox"]').is(':checked');
if (!checked_one )
$('.error').text('You must select atleast one!');
else
$('.error').hide();
});
Live demo can be seen here: http://jsfiddle.net/ptbTq/15/

how to change color of text following function in javascript

Ok before i make spaghetti of this code i thought id ask around here. ive made a quiz for an online site.
The answers are stored in an array, and ive a function that checks the answers array to what youve clicked. then it counts them and gives you your score.
but i want to change the clor of the right answer wen the user clicks the score button. so the correct answers are highlighted. something like this https://www.shutterpoint.com/Home-Quiz.cfm (just hit submit at the bottom, no need to do the quiz).
the little answer icon at the side looks flashy but id rather just have the text change color. heres how my questions are formatted
<p>Film speed refers to:</p>
<p id = "question1">
<input type="radio" name="question1" id="Wrong" value = "a" onClick = "recordAnswer(1,this.value)"/>How long it takes to develop film. <br/>
<input type="radio" name="question1" id="Wrong" value = "b" onClick = "recordAnswer(1,this.value)"/>How fast film moves through film-transport system. <br/>
<input type="radio" name="question1" id="Answer" value = "c" onClick = "recordAnswer(1,this.value)"/> How sensitive the film is to light. <br/>
<input type="radio" name="question1" id="Wrong" value = "d" onClick = "recordAnswer(1,this.value)"/> None of these makes sense. <br/></p>
and these are the two functions that are called throughout. record answer is called every time the user clicks a button
function recordAnswer(question,answer)
{
answers[question-1] = answer;
}
this is the final button which calculates the score
function scoreQuiz()
{
var totalCorrect = 0;
for(var count = 0; count<correctAnswers.length;count++)
{
if(answers[count]== correctAnswers[count])
totalCorrect++;
}
<!--
alert("You scored " + totalCorrect + " out of 12 correct!");
-->
}
another function is best i think. ive already made attempts at it and know i have to set the color using
document.getElementById('Answer').style.color = '#0000ff';
onyl problem is 'Answer' doesnt seem to be registering. anyone shed some light?
ok so i cant have two or more of the same ids.
what about
if(value == correctAnswers[])
{
// change the color.
}
QUICK RESPONCE:
USE <P>
<p>
<input type="radio" name="question_1" class="wrong" value="a" />
How long it takes to develop film.
</p>
THEN
if(value == correctAnswers[])
{
YOUR_ELEMENT.parentNode.style.color = 'green';
}
IMPROVEMENT
DEMO: http://jsbin.com/aceze/26
hi Overtone!
first of all you need to restyle a litte your HTML schema!
you have multiple id="Wrong" instead of class="Wrong"
then here how your code should look:
var answers = { 1:'a' , 2:'f' , 3:'h' };
function checkQuestions() {
var form_elements = document.question_form.elements.length;
for ( var i = 0; i < form_elements; i++ )
{
var type = question_form.elements[i].type;
if ( type == "radio" ){
var quest = question_form.elements[i];
//if ( quest.checked ) {
var question_index = parseInt(quest.name.split('_')[1]);
//}
if ( quest.value == answers[question_index] ) {
quest.parentNode.style.border = '1px solid green';
quest.parentNode.style.color = 'green';
} else {
//quest.parentNode.style.border = '1px solid red';
quest.parentNode.style.color = 'red';
}
}
}
}
USE a FORM and one time SUBMIT BUTTON instead of adding onclick to each RADIO like this
<form name="question_form" id="question_form" method="POST" action='#'>
<div id="question_1"> <H4>QUESTIONS TIME 1</H4>
</div>
<p>
<input type="radio" name="question_1" class="wrong" value="a" />
How long it takes to develop film.
</p>
<p>
<input type="radio" name="question_1" class="wrong" value="b" />
How fast film moves through film-transport system.
</p>
<p>
<input type="radio" name="question_1" class="answer" value="c" />
How sensitive the film is to light.
</p>
<p>
<input type="radio" name="question_1" class="wrong" value="d" />
None of these makes sense.
</p>
...
...
<input type="radio" name="question_2" class="wrong" value="h" />
<span>None of these makes sense.
</span>
</p>
<input type="submit" name="submit" onclick="checkQuestions();return false;" value="submit"/>
</form>
PS: demo example updated with style... for sake!
You should format your ids in a more usable way.. I'd suggest something similar to questionNUMBER_answerVALUE.
Then it'd be a simple matter of...
for (var i=0; i<correctAnswers;i++) {
document.getElementById("question" + (i+1) + "_answer" + correctAnswers[i].toUpperCase()).style.color = "#0000FF";
};
Just check I've got your zero/non-zero indexing correct with regard to question/ answer numbers.
Instead of using a <p> I would consider using a <label for='question1_answerA'>How long it takes to develop film.</label>. You can still use a jQuery selector to find it and it feels more semantically correct. You will then also be able to select the option by clicking the text.
Although your other HTML isn't semantically correct. You need to give each radio a unique ID.
Obligatory jquery solution:
var highlightCorrect = function(){
$(".Answer").css("color", "#00FF00");
}
This is all assuming that you fix your HTML to use classes rather than IDs for "Wrong" and "Answer".

Categories

Resources