In short, if a user selects yes to a radio option, I'm trying to obtain the data-name attribute from that input and push it to an array called accepted_array.
If a user selects no, then store data-name to declined_array.
Here is a visual to the markup:
<div class="guest__options-group">
<input id="attending-yes-0" type="radio" name="attendance-0" value="yes" data-name="John" required />
<label for="attending-yes-0">Yes</label>
</div>
<div class="guest__options-group">
<input id="attending-no-0" type="radio" name="attendance-0" value="no" data-name="John" required />
<label for="attending-no-0">No</label>
</div>
<!-- options for Alex -->
<div class="guest__options-group">
<input id="attending-yes-1" type="radio" name="attendance-1" value="yes" data-name="Alex" required />
<label for="attending-yes-1">Yes</label>
</div>
<div class="guest__options-group">
<input id="attending-no-1" type="radio" name="attendance-1" value="no" data-name="Alex" required />
<label for="attending-no-1">No</label>
</div>
Here are 2 approaches I've experimented with:
First approache.
(function ($) {
$( ".guest__attendance-input" ).each(function(index) {
$(this).on("click", function(){
var $this = $(this);
var checkedVal = $this.val();
var accepted_array = [];
var declined_array = [];
if( checkedVal == "yes" ) {
var name = $this.data("name");
accepted_array.push(name);
} else {
declined_array.push(name);
}
console.log("accepted " + accepted_array.join(","));
console.log("declined " + accepted_array.join(","));
});
});
}) (jQuery);
This only executes for the selected user and adds the name to both arrays.
Second approache.
(function ($) {
$( ".guest__attendance-input" ).each(function(index) {
$(this).on("click", function(){
var $this = $(this);
var data = [];
var checked = $this.is(':checked');
var name = $this.attr('data-name');
if (checked) {
if (!data[name]) {
data[name] = []
}
data[name].push($this.val())
}
console.log(data);
});
});
}) (jQuery);
Which only adds the user to a single array.
If both select yes, I need both names in the accepted_array. If someone selects yes initially and then selects no I need to remove them from the accepted_array and vice versa.
You can use splice with inArray to remove value from array if someone selects yes initially and then selects no and vice versa.
Example:
var accepted_array = [];
var declined_array = [];
$('.guest__options-group > input[type=radio]').on('change', function() {
var $this = $(this);
var name = $this.data("name");
var checkedVal = $this.val();
var name = $this.data("name");
if (checkedVal == "yes") {
accepted_array.push(name);
declined_array.splice($.inArray(name, declined_array), 1);
} else {
declined_array.push(name);
accepted_array.splice($.inArray(name, accepted_array), 1);
}
console.log("accepted " + accepted_array.join(","));
console.log("declined " + declined_array.join(","));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- options for John -->
<div class="guest__options-group">
<input id="attending-yes-0" type="radio" name="attendance-0" value="yes" data-name="John" required />
<label for="attending-yes-0">Yes</label>
</div>
<div class="guest__options-group">
<input id="attending-no-0" type="radio" name="attendance-0" value="no" data-name="John" required />
<label for="attending-no-0">No</label>
</div>
<!-- options for Alex -->
<div class="guest__options-group">
<input id="attending-yes-1" type="radio" name="attendance-1" value="yes" data-name="Alex" required />
<label for="attending-yes-1">Yes</label>
</div>
<div class="guest__options-group">
<input id="attending-no-1" type="radio" name="attendance-1" value="no" data-name="Alex" required />
<label for="attending-no-1">No</label>
</div>
I am trying to make a Js to search & filter items in JSON
so I use many radio in the "form" , the result will be [X,X,X,X,X,X]
I will set 50tags x 3(choose), I can feel my function will be large.
What ways can I change my function to be simpler?
function myFunction() {
var elements1 = document.getElementsByName("chair"),
elements2 = document.getElementsByName("car"),
elements3 = document.getElementsByName("house"),
elements4 = document.getElementsByName("tree"),
elements5 = document.getElementsByName("flower"),
elements6 = document.getElementsByName("grass");
var i;
for (var a = "", i = elements1.length; i--;) {
if (elements1[i].checked) {
var a = elements1[i].value;
break;
}
};
for (var b = "", i = elements2.length; i--;) {
if (elements2[i].checked) {
var b = elements2[i].value;
break;
}
};
for (var c = "", i = elements3.length; i--;) {
if (elements3[i].checked) {
var c = elements3[i].value;
break;
}
};
for (var d = "", i = elements4.length; i--;) {
if (elements4[i].checked) {
var d = elements4[i].value;
break;
}
};
for (var e = "", i = elements5.length; i--;) {
if (elements5[i].checked) {
var e = elements5[i].value;
break;
}
};
for (var f = "", i = elements6.length; i--;) {
if (elements6[i].checked) {
var f = elements6[i].value;
break;
}
};
var o2 = document.getElementById("output2");
o2.value = "[" + a + "," + b + "," + c + "," + d + "," + e + "," + f + "]";
o2.innerHTML = o2.value;
}
<form><input type="radio" id="chair1" name="chair" class="chair" value="1">
<input type="radio" id="chair0" name="chair" class="chair" value="0" checked>
<input type="radio" id="chair-1" name="chair" class="chair" value="-1">
<input type="radio" id="car1" name="car" class="car" value="1">
<input type="radio" id="car0" name="car" class="car" value="0" checked>
<input type="radio" id="car-1" name="car" class="car" value="-1">
<input type="radio" id="house1" name="house" class="house" value="1">
<input type="radio" id="house0" name="house" class="house" value="0" checked>
<input type="radio" id="house-1" name="house" class="house" value="-1">
<input type="radio" id="tree1" name="tree" class="tree" value="1">
<input type="radio" id="tree0" name="tree" class="tree" value="0" checked>
<input type="radio" id="tree-1" name="tree" class="tree" value="-1">
<input type="radio" id="flower1" name="flower" class="flower" value="1">
<input type="radio" id="flower0" name="flower" class="flower" value="0" checked>
<input type="radio" id="flower-1" name="flower" class="flower" value="-1">
<input type="radio" id="grass1" name="grass" class="grass" value="1">
<input type="radio" id="grass0" name="grass" class="grass" value="0" checked>
<input type="radio" id="grass-1" name="grass" class="grass" value="-1">
<div> <input type="button" value="Search" id="filter" onclick="myFunction()" /> </div>
</form>
<div id="output2"></div>
Give the form an id, and you can refer to it as an object.
function myFunction() {
var form = document.getElementById("myForm");
var parts = [
form.chair.value,
form.car.value,
form.house.value,
form.tree.value,
form.flower.value,
form.grass.value
];
var o2 = document.getElementById("output2");
o2.innerHTML = '[' + parts.join(',') + ']';
}
And this is an even simpler solution using a FormData object. It supports an arbitrary number of named form fields without having to actually name them in the function:
function myFunction() {
var myForm = document.getElementById('myForm');
var formData = new FormData(myForm);
var parts = Array.from(formData.values());
var o2 = document.getElementById("output2");
o2.innerHTML = '[' + parts.join(',') + ']';
}
Use document.querySelector() to directly select the value of the checked radio button based on element names.
function myFunction() {
var chair = document.querySelector('input[name="chair"]:checked').value;
var car = document.querySelector('input[name="car"]:checked').value;
var house = document.querySelector('input[name="house"]:checked').value;
var tree = document.querySelector('input[name="tree"]:checked').value;
var flower = document.querySelector('input[name="flower"]:checked').value;
var grass = document.querySelector('input[name="grass"]:checked').value;
var o2 = document.getElementById("output2");
o2.value = "[" + chair + "," + car + "," + house + "," + tree + "," + flower + "," + grass + "]";
o2.innerHTML = o2.value;
}
Use arrays!
function myFunction() {
var elem_ids = [ "chair", "car", "house", "tree", "flower", "grass"];
var elems = elem_ids.map(id => document.getElementById(id));
var elems_check_values = elems.map(el => {
// el is kind of an array so
for(var i = 0; i < el.length; ++i)
if(el[i].checked)
return el[i].value;
return undefined;
}).filter(value => value == undefined) // to filter undefined values;
var output = "[" + elems_check_values.join(",") + "]";
var o2 = document.getElementById("output2");
o2.innerHTML = output
}
Your issue can be generalized to: how can I aggregate values for all fields in a given form?
The solution is a function that can be merely as long as 5 lines, and work for any amount of inputs with any type. The DOM model for <form> elements provides named keys (eg, myform.inputName) which each have a value property. For radio buttons, eg myform.tree.value will automatically provide the value of the selected radio button.
With this knowledge, you can create a function with a simple signature that takes a form HTMLElement, and an array of field names for the values that you need, like below: (hit the search button for results, and feel free to change the radio buttons).
function getFormValues(form, fields) {
var result = [];
for (var i = 0; i < fields.length; i++) {
result.push(form[fields[i]].value);
}
return result;
}
document.getElementById('filter').addEventListener('click', function(e) {
var o2 = document.getElementById("output2");
o2.innerHTML = getFormValues(document.forms[0], ['chair','car','house','tree','flower','grass']);
});
<form><input type="radio" id="chair1" name="chair" class="chair" value="1">
<input type="radio" id="chair0" name="chair" class="chair" value="0" checked>
<input type="radio" id="chair-1" name="chair" class="chair" value="-1">
<input type="radio" id="car1" name="car" class="car" value="1">
<input type="radio" id="car0" name="car" class="car" value="0" checked>
<input type="radio" id="car-1" name="car" class="car" value="-1">
<input type="radio" id="house1" name="house" class="house" value="1">
<input type="radio" id="house0" name="house" class="house" value="0" checked>
<input type="radio" id="house-1" name="house" class="house" value="-1">
<input type="radio" id="tree1" name="tree" class="tree" value="1">
<input type="radio" id="tree0" name="tree" class="tree" value="0" checked>
<input type="radio" id="tree-1" name="tree" class="tree" value="-1">
<input type="radio" id="flower1" name="flower" class="flower" value="1">
<input type="radio" id="flower0" name="flower" class="flower" value="0" checked>
<input type="radio" id="flower-1" name="flower" class="flower" value="-1">
<input type="radio" id="grass1" name="grass" class="grass" value="1">
<input type="radio" id="grass0" name="grass" class="grass" value="0" checked>
<input type="radio" id="grass-1" name="grass" class="grass" value="-1">
<div> <input type="button" value="Search" id="filter"/> </div>
</form>
<div id="output2"></div>
The thing you need to do is break the code up into reusable chunks. So make a method to get the value. That will reduce a lot of code. After than, you should look at a way to reduce how many elements you need to list. Finally, find an easy way to fetch all the values.
So below is code that does this. It uses a helper method to get the elements, find the value. Than it uses an array to know what element groups to look for. And finally it uses map to iterate over the list so you do not have to code multiple function calls.
function getSelected (radioBtnGroup) {
// get the elements for the radio button group
var elms = document.getElementsByName(radioBtnGroup)
// loop over them
for(var i=0; i<elms.length; i++) {
// if checked, return value and exit loop
if (elms[i].checked) {
return elms[i].value
}
}
// if nothing is selected, return undefined
return undefined
}
// list the groups you want to get the values for
var groups = ['rb1', 'rb2', 'rb3', 'rb4']
// call when you want to get the values
function getValues () {
// use map to get the values of the rabio button groups.
// map passes the index value as the first argument.
// code is map(function(k){return getSelected(k)})
var results = groups.map(getSelected)
//displat the results
console.log(results);
}
document.querySelector('#btn').addEventListener('click', getValues);
<form>
<fieldset>
<legend>Item 1</legend>
<label><input type="radio" name="rb1" value="1-1"> One</label>
<label><input type="radio" name="rb1" value="1-2"> Two</label>
<label><input type="radio" name="rb1" value="1-3"> Three</label>
</fieldset>
<fieldset>
<legend>Item 2</legend>
<label><input type="radio" name="rb2" value="2-1"> One</label>
<label><input type="radio" name="rb2" value="2-2"> Two</label>
<label><input type="radio" name="rb2" value="2-3"> Three</label>
</fieldset>
<fieldset>
<legend>Item 3</legend>
<label><input type="radio" name="rb3" value="3-1"> One</label>
<label><input type="radio" name="rb3" value="3-2"> Two</label>
<label><input type="radio" name="rb3" value="3-3"> Three</label>
</fieldset>
<fieldset>
<legend>Item 4</legend>
<label><input type="radio" name="rb4" value="4-1"> One</label>
<label><input type="radio" name="rb4" value="4-2"> Two</label>
<label><input type="radio" name="rb4" value="4-3"> Three</label>
</fieldset>
<button type="button" id="btn">Get Results</button>
</form>
Personally I would not store the values in an array, I would use an object with key value pairs.
var results = groups.reduce(function (obj, name) {
obj[name] = getSelected(name)
return obj
}, {});
I have 3 input checkboxes. Each of them displays a div if checked. Because the three has the same JS I have decided to have just one JS including 3 variables (one per input) but it is not working. Before I had three independent JS and it worked fine.
CODE
document.getElementById()
var cb1 = document.getElementById('checkbox1'); checkbox1.onchange = {
if (checkbox1.checked) {
course1.style.display = 'block';
} else {
course1.style.display = 'none';
};
var cb2 = document.getElementById('checkbox2'); checkbox2.onchange = {
if (checkbox2.checked) {
course2.style.display = 'block';
} else {
course2.style.display = 'none';
};
var cb3 = document.getElementById('checkbox3'); checkbox3.onchange = {
if (checkbox3.checked) {
course3.style.display = 'block';
} else {
course3.style.display = 'none';
};
<form>
<label class="switch">
<input type="checkbox" id="checkbox1"> Course 1
</label>
</form>
<form>
<label class="switch">
<input type="checkbox" id="checkbox2"> Course 2
</label>
</form>
<form>
<label class="switch">
<input type="checkbox" id="checkbox3"> Course 3
</label>
</form>
<br>
<div id ="course1">
Text course 1
</div>
<br>
<div id ="course2">
Text course 2
</div>
<br>
<div id ="course3">
Text course 3
</div>
Fiddle: https://codepen.io/antonioagar1/pen/YOwBeE?editors=1010
After fixing your syntax errors (identation is very imporant, if it was correct in your code you would had see that you have many if statements not closing correclty)
Well, besides those errors, I managed a way to you that you only need a single function to achieve your desired result.
If you see in the HTML part, you'll note that I added some new attributes to checkboxes and divs, called data-idCheck, where the checkbox with data-idCheck will display the div whose have that same attribute.
Check below to see if my code helps you.
var cb1 = document.getElementById('checkbox1');
cb1.onchange = checkChecked;
var cb2 = document.getElementById('checkbox2');
cb2.onchange = checkChecked;
var cb3 = document.getElementById('checkbox3');
cb3.onchange = checkChecked;
function checkChecked(){
let idCheck = this.getAttribute("data-idCheck");
let relatedDiv = document.querySelector("div[data-idCheck='" + idCheck + "']");
if (this.checked) {
relatedDiv.style.display = 'block';
} else {
relatedDiv.style.display = 'none';
}
}
.hiddenDiv{
display: none;
}
<form>
<label class="switch">
<input type="checkbox" id="checkbox1" data-idCheck="1"> Course 1
</label>
</form>
<form>
<label class="switch">
<input type="checkbox" id="checkbox2" data-idCheck="2"> Course 2
</label>
</form>
<form>
<label class="switch">
<input type="checkbox" id="checkbox3" data-idCheck="3"> Course 3
</label>
</form>
<br>
<div id ="course1" class="hiddenDiv" data-idCheck="1">
Text course 1
</div>
<br>
<div id ="course2" class="hiddenDiv" data-idCheck="2">
Text course 2
</div>
<br>
<div id ="course3" class="hiddenDiv" data-idCheck="3">
Text course 3
</div>
I'm trying to make a simple quiz with radio button options. The quiz has one button that should dynamically remove and add the next question, and set of radio buttons. The questions and options stored in separate arrays. I am stuck on trying to connect each option with a radio button. Any ideas how to go about with this?
P.S. Just started learning JS as you might tell from my code
<script type="text/javascript">
var questionsArray = new Array();
questionsArray[0] = "1. Who's the president of the US?";
questionsArray[1] = "2. What is the capital city of France?";
questionsArray[2] = "3. What is your favorite food?";
var choicesArray = new Array();
choicesArray[0] = ["Lebron James", "Barack Obama", "George Bush","George Clooney"];
choicesArray[1] = ["Nairobi","London","Paris","Sydney"];
choicesArray[2] = ["Pizza","Sushi","Pasta","Lobster"];
function createRadioElement(name){
var radioHTML = '<input type="radio" name="'+name+'"'+'/>';
var radioFragment = document.createElement("div");
radioFragment.innerHTML = radioHTML;
return radioFragment.firstChild;
}
var index = -1;
function questionSwapOnclick(){
while(index < questionsArray.length){
index++;
document.getElementById("question").innerHTML = questionsArray[index];
if(document.getElementById("question").innerHTML == "undefined"){
document.getElementById("question").innerHTML = "Finished the quiz!"
document.getElementById("choices").innerHTML = ""
}
var splitChoices = choicesArray[index].join("<br />");
document.getElementById("choices").innerHTML = splitChoices;
return true;
}
}
</script>
Why not keep the questions in the html?
JS Fiddle
<form id="questions">
<div class="question active">
<p>1. Who's the president of the US?</p>
<label>
<input type="radio" name="q1" value="1">Lebron James</label>
<label>
<input type="radio" name="q1" value="2">Barack Obama</label>
<label>
<input type="radio" name="q1" value="3">George Bush</label>
</div>
<div class="question" style="display: none;">
<p>2. What is the capital city of France?</p><label>
<input type="radio" name="q2" value="1">Nairobi</label>
<label>
<input type="radio" name="q2" value="2">London</label>
<label>
<input type="radio" name="q2" value="3">Paris</label>
</div>
<div class="question" style="display: none;">
<p>3. What is your favorite food?</p>
<input type="radio" name="q3" value="1">Pizza</label>
<label>
<input type="radio" name="q3" value="2">Sushi</label>
<label>
<input type="radio" name="q3" value="3">Pasta</label>
</div>
<hr> Next question ยป
// used jquery 1.11.0
$(function () {
var questions = $('#questions');
var next_btn = $('#next');
next_btn.on('click', function () {
var active_question = questions.find('.active');
if (active_question.find('input[type=radio]:checked').length) {
active_question.slideUp(500, function(){
active_question.removeClass('active');
});
if(active_question.next('.question').length){
active_question.next('.question').addClass('active').slideDown(500);
}
else {
alert('Thank you!');
alert(questions.serialize());
questions.hide();
}
}
else {
alert('Select answer!');
}
});
});
I have a form with 5 questions and 3 different answers for each question.
e.g.
q1. whats is your favorite color?
radio button-1. value blue
radio button-2. value red
radio button-3. value grey
most of these questions have the same value (blue, red, grey), which is what I want, however, I'm trying to add all the values together at the end of the form so I can determine if the person filling out the form equals one of the values (blue, red, or grey).
I'm building this form with angularjs and this is what i have so far.
<label>Q1. what is your favorite color?</label>
<div class="form-group">
<div class="radio">
<label>
<input type="radio" ng-model="formData.color" value="blue">
blue
</label>
</div>
<div class="radio">
<label>
<input type="radio" ng-model="formData.color" value="red">
red
</label>
</div>
<div class="radio">
<label>
<input type="radio" ng-model="formData.color" value="grey">
grey
</label>
</div>
this bit of code only works if I have the values already entered into the variable
$scope.formData = { };
$scope.formData = [];
$scope.formData.sort();
var current = null;
var cnt = 0;
for (var i = 0; i < $scope.formData.length; i++) {
if ($scope.formData[i] != current) {
if (cnt > 0) {
console.log(current + ' shows ' + cnt + ' times');
}
current = $scope.formData[i];
cnt = 1;
} else {
cnt++;
}
}
if (cnt > 0) {
console.log(current + ' shows ' + cnt + ' times');
}
Here is an example solution plunker. Would it work?
controller
$scope.questions = [
'Q1. what is your favorite color?',
'Q2. what color is your car?',
'Q3. what color best represents you?'
];
$scope.formData = [];
$scope.stats = function() {
$scope.results = {};
for (var i = 0; i < $scope.formData.length; i++) {
var color = $scope.formData[i];
if(color) {
if ($scope.results.hasOwnProperty(color)) {
$scope.results[color]++;
} else {
$scope.results[color] = 1;
}
}
}
};
template
<div class="form-group" ng-repeat="q in questions">
<label>{{q}}</label>
<div class="radio">
<label>
<input type="radio" ng-model="formData[$index]" value="blue">blue
</label>
</div>
<div class="radio">
<label>
<input type="radio" ng-model="formData[$index]" value="red">red
</label>
</div>
<div class="radio">
<label>
<input type="radio" ng-model="formData[$index]" value="grey">grey
</label>
</div>
</div>
<button ng-click="stats()">show results</button>
<ul>
<li ng-repeat="(c, n) in results"> {{c}} shows {{n}} times</li>
</ul>