Looping thru checked checkboxes and creating multi dimensional array - javascript

I have a series of checkboxes, meals and products. I am able to check each one and find the name and value. What I want to do and unable to do is create an array, the array index would be the name of the checkbox and the value would be the value of the checkbox that was checked.
$("#recipe-filter-form").submit(function(e) {
e.preventDefault();
var categories = [];
var i = 0;
$('.category-checkbox').each(function (index, value) {
var checkboxName = $(this).attr('name');
var checkboxValue = $(this).val();
// if checkbox is checked
if ($(this).is(':checked'))
{
categories[checkboxName][i] = checkboxValue;
i++;
}
});
console.log(categories);
});
This loops thru each checkbox, if it is checked, lets get the name and value.
I added an index i to the array in hopes of it working but it returns an error: TypeError: Cannot set property '0' of undefined
HTML
<form action="" method="get" id="recipe-filter-form">
<ul>
<li>
<label class="check" data-category="appetizers">
<input type="checkbox" name="meal" value="appetizers" class="category-checkbox"> Appetizers</label>
</li>
<li>
<label class="check" data-category="beverages">
<input type="checkbox" name="meal" value="beverages" class="category-checkbox"> Beverages</label>
</li>
</ul>
<ul>
<li>
<label class="check" data-category="sides">
<input type="checkbox" name="products" value="sides" class="category-checkbox"> Sides</label>
</li>
<li>
<label class="check" data-category="soups">
<input type="checkbox" name="products" value="soups" class="category-checkbox"> Soups</label>
</li>
</ul>
<button type="submit" class="button green secondary">Filter</button>
</form>
If every checkbox was checked, my expected output is:
array('meal' => array('appetizers', beverages'), 'products' => array('sides', 'soups')
Why do I want to create a multi dimensional array?
Because after the array is created, I will generate a string by looping thru the array by appending the array index, values for a string to look like:
meal=appetizers,beverages&products=sides,soups
Question: How do I alter my code to get the expected output as seen on the line above?

I believe you were having problems in the code you posted.
categories[checkboxName][i] here categories[checkboxName] is undefined in the first attempt. So it will cause error.
i is not needed. Just use push().
You can use categories[checkboxName] = categories[checkboxName] || []; to initialize the variable as an array if it is undefined in the loop.
$("#recipe-filter-form").submit(function(e) {
e.preventDefault();
var categories = [];
$('.category-checkbox').each(function(index, value) {
var checkboxName = this.name;
var checkboxValue = this.value;
// if checkbox is checked
if ($(this).is(':checked')) {
categories[checkboxName] = categories[checkboxName] || []; //initialize if not exist
categories[checkboxName].push(checkboxValue);
}
});
console.log(categories);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<form action="" method="get" id="recipe-filter-form">
<ul>
<li>
<label class="check" data-category="appetizers">
<input type="checkbox" name="meal" value="appetizers" class="category-checkbox">Appetizers</label>
</li>
<li>
<label class="check" data-category="beverages">
<input type="checkbox" name="meal" value="beverages" class="category-checkbox">Beverages</label>
</li>
</ul>
<ul>
<li>
<label class="check" data-category="sides">
<input type="checkbox" name="products" value="sides" class="category-checkbox">Sides</label>
</li>
<li>
<label class="check" data-category="soups">
<input type="checkbox" name="products" value="soups" class="category-checkbox">Soups</label>
</li>
</ul>
<button type="submit" class="button green secondary">Filter</button>
</form>

Related

check the radio button when click on the li using javascript

I have radio button
Html code:
<input type="radio" class="first" name="bright" checked>
<input type="radio" class="second" name="bright" >
<input type="radio" class="third" name="bright">
<input type="radio" class="four" name="bright">
And i have a nav bar
Html code
<ul class="nav">
<li class="st st1 active" data-cont="first">
<h2 class="inner">وزارة الاستثمار</h2>
</li>
<li class="st st2" data-cont="second">
<h2 class="inner">وزارة التجارة</h2>
</li>
<li class="st st3" data-cont="third">
<h2 class="inner">جهات حكومية اخرى</h2>
</li>
<li class="st st4" data-cont="four">
<h2 class="inner">مكتب هندسي</h2>
</li>
</ul>
These 2 are conected with the data-cont that have the class of the radio button
I want when i click on the li the correct radio button be checked using javascript
I tried to make it using this code in JavaScript
let radio = document.querySelectorAll("input");
let radioArray = Array.from(radio);
let tabs = document.querySelectorAll(".nav li");
let tabsArray = Array.from(tabs);
tabsArray.forEach((ele) => {
ele.addEventListener("click", function (e) {
tabsArray.forEach((ele) => {
ele.classList.remove("active");
});
e.currentTarget.classList.add("active");
document.querySelector(e.currentTarget.dataset.cont).checked = true;
});
});
I try to remove the active class from li and put it on the li where i click then i want the radio button be checked
Any body can help me on this?
the last querySelector is where your code is failing you're not referencing the class for your input it needs to be document.querySelector('.' + e.currentTarget.dataset.cont).checked = true; note the "." prefix
Although that answers your question there is probably more value in pointing out that by changing your html markup to be a little more accessible you can eliminate the need for all of the javascript in your example
e.g.
input:checked + label {
color:Red;
}
<div><input type="radio" id="first" name="bright" checked>
<label for='first'>وزارة الاستثما</label>
</div>
<div>
<input type="radio" id="second" name="bright" >
<label for='second'>وزارة التجارة</label>
</div>
<div>
<input type="radio" id="third" name="bright">
<label for='third'>جهات حكومية اخرى</label>
</div>
<div>
<input type="radio" id="four" name="bright">
<label for='four'>مكتب هندسي</label>
</div>
The use of labels associated with your radio buttons is now significantly more accessible and you can drastically reduce a lot of your markup ( though to be accessible you would need to provide a more meaningful name for for attribute.

HTML multiple different 'check all' checkboxes

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.

How to delete list of checked item from a specific list

I have here 2 ul list which contains inside two lists of items and 2 delete buttons. I use here only one button click function for both delete buttons and I would like to have something like: when the user checks the items in the List 1 then only the items in the List 1 will be deleted after pressing the delete button no matter items in List 2 are checked or not and vice versa. Because now I can use the delete button in List 1 to delete items in List 2. What I have read on the internet is after pressing the delete button I might use something call: $(event.currentTarget).parent() to get the exact content list belongs to this button and then process inside of this list. Am I right?
$(document).ready(function() {
$("#delete").click(function() {
var deleteItem = [];
$("input:checkbox").each(function() {
var $this = $(this);
if ($this.is(":checked")) {
deleteItem.push($this.attr("name"));
}
});
if (deleteItem != []) {
if (deleteItem.indexOf("cbox1") > -1 && deleteItem.indexOf("cbox2") > -1) {
$("#box1").remove();
$("#box2").remove();
}
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul>List 1
<li id="box1"><span><input type="checkbox" name="cbox1" value="1" />Visit W3Schools1.com!</span></li>
<li id="box2"><span><input type="checkbox" name="cbox2" value="2" />Visit W3Schools2.com!</span></li>
<li id="box3"><span><input type="checkbox" name="cbox3" value="3" />Visit W3Schools3.com!</span></li>
<button id="delete">Delete</button>
</ul>
<ul>List 2
<li id="box1"><span><input type="checkbox" name="cbox1" value="1" />Visit W3Schools1.com!</span></li>
<li id="box2"><span><input type="checkbox" name="cbox2" value="2" />Visit W3Schools2.com!</span></li>
<li id="box3"><span><input type="checkbox" name="cbox3" value="3" />Visit W3Schools3.com!</span></li>
<button id="delete">Delete</button>
</ul>
As I mentioned in my comment, you should use a class instead of id's because id's must be unique.
Here is a Fiddle Demo.
JQUERY:
$('.delete').click(function() {
var items = $(this).parent('ul').find('input:checked');
items.closest('li').remove();
});
When an element with the class 'delete' is clicked, it finds the parent ul and then looks for checked inputs. Once those are found, it looks for the closest li for those inputs and removes them.
HTML:
<ul>List 1
<li class="box1"><span><input type="checkbox" name="cbox1" value="1" />Visit W3Schools1.com!</span></li>
<li class="box2"><span><input type="checkbox" name="cbox2" value="2" />Visit W3Schools2.com!</span></li>
<li class="box3"><span><input type="checkbox" name="cbox3" value="3" />Visit W3Schools3.com!</span></li>
<button class="delete">Delete</button>
</ul>
<ul>List 2
<li class="box1"><span><input type="checkbox" name="cbox1" value="1" />Visit W3Schools1.com!</span></li>
<li class="box2"><span><input type="checkbox" name="cbox2" value="2" />Visit W3Schools2.com!</span></li>
<li class="box3"><span><input type="checkbox" name="cbox3" value="3" />Visit W3Schools3.com!</span></li>
<button class="delete">Delete</button>
</ul>
OP asked how to find the name of the checked inputs. Here is one way to do it:
$('.delete').click(function() {
var items = $(this).parent('ul').find('input:checked');
//iterate over objects and log the name
$.each(items, function( index, value ) {
console.log($(this).attr('name'));
});
items.closest('li').remove();
});
I've added an iterator which will go through the objects in items and output the name attribute to the console (F12 in most browsers). Here is an updated Fiddle Demo.
Note :Id must be unique. If you are tending to use same Id convert that to a class
Working Demo
$(document).ready(function() {
$(".delete").click(function() {
var deleteItem = [];
$("input:checkbox").each(function() {
var $this = $(this);
if ($this.is(":checked")) {
$(this).parent().parent().remove()
}
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul>List 1
<li id="box1"><span><input type="checkbox" name="cbox1" value="1" />Visit W3Schools1.com!</span>
</li>
<li id="box2"><span><input type="checkbox" name="cbox2" value="2" />Visit W3Schools2.com!</span>
</li>
<li id="box3"><span><input type="checkbox" name="cbox3" value="3" />Visit W3Schools3.com!</span>
</li>
<button class="delete">Delete</button>
</ul>
<ul>List 2
<li id="box1"><span><input type="checkbox" name="cbox1" value="1" />Visit W3Schools1.com!</span>
</li>
<li id="box2"><span><input type="checkbox" name="cbox2" value="2" />Visit W3Schools2.com!</span>
</li>
<li id="box3"><span><input type="checkbox" name="cbox3" value="3" />Visit W3Schools3.com!</span>
</li>
<button class="delete">Delete</button>
</ul>
Yeah you are right in the use of .parent() jquery method. If i understand what you trie to do, you can maybe improve your code in this way :
$(document).ready(function() {
$("#delete").click(function() {
var parentUl = $(this).parent(); // get the parent url of the clicked button
var li_items = parentUl.find('li'); // get the li in the parent ul
li_items.each(function() { // for each li retrieved
if ($(this).children('input:checkbox').is(':checked')) // if the input is checked
$(this).remove(); // we remove it
});
});
Hope it helps ! :)
EDIT :
As other says, you should use a class instead of an id. per definition, an id should be considers as an unique block identifier in your html. in your case, you have 2 buttons so it's better to do this : <button class="delete"></button>

Removing an element from an array when a dropdown item is unselected

I have this script that runs when a user selects an element in a dropdown list:
<script type="text/javascript">
var seSelection = [];
$(document).ready(function() {
$(".dropdown-menu input").click(function() {
var value = $(this).val();
$(this).closest("#seButton").data();
if (this.checked) {
seSelection.push(this.value);
}
});
console.log("se equals " + seSelection);
});
</script>
<button id ="seButton" data-toggle="dropdown" class="btn btn-primary dropdown-toggle">
Options<span class="caret"></span>
</button>
<ul class="dropdown-menu noclose">
<li>
<input type="checkbox" id="ex3_1" name="ex3" value="A" checked="">
<label for="ex3_1">Option 1</label>
</li>
<li>
<input type="checkbox" id="ex3_2" name="ex3" value="B">
<label for="ex3_2">Option 2</label>
</li>
<li>
<input type="checkbox" id="ex3_3" name="ex3" value="C">
<label for="ex3_3">Option 3</label>
</li>
</ul>
I'm using the Twitter Bootstrap noclose, so dropdown-menu stays open until I click out of it. This is designed to allow a user to select multiple options. So as I select various options, my console looks like this, as the script fires on each click:
se equals
se equals A
se equals A,B
se equals A,B,C
This is great - and it's functioning properly, but in the same dropdown, if I deselect C after I have selected it, it doesn't REMOVE c as a value from the array seSelection.
I'm not sure how to write the code that does the inverse of what my script's code above does since I can't find any unclick(function) or unpush(this.value) that exists in jQuery.
How do I write this?
On unchecking you can remove the item from the array just like this http://jsfiddle.net/93zL0ae9/
<script type="text/javascript">
var seSelection = [];
$(document).ready(function(){
$(".dropdown-menu input").click(function() {
var value = $(this).val();
$(this).closest("#seButton").data();
if (this.checked) {
seSelection.push(this.value);
}
else
{
var index = seSelection.indexOf(this.value);
if(index>=0)
{
seSelection.splice(index,1);
}
}
console.log("se equals " + seSelection);
});
});
</script>
<button id ="seButton" data-toggle="dropdown" class="btn btn-primary dropdown-toggle">Options<span class="caret"></span></button>
<ul class="dropdown-menu noclose">
<li>
<input type="checkbox" id="ex3_1" name="ex3" value="A" checked="">
<label for="ex3_1">Option 1</label>
</li>
<li>
<input type="checkbox" id="ex3_2" name="ex3" value="B">
<label for="ex3_2">Option 2</label>
</li>
<li>
<input type="checkbox" id="ex3_3" name="ex3" value="C">
<label for="ex3_3">Option 3</label>
</li>
</ul>
</div>
It's because the instance is still being saved in your global variable, seSelection. I bet you if you unselect and then re-select an option it would show up twice.
It depends what your requirements are, but you probably instead want to generate that array of results from scratch after each click. You can do this by moving your var seSelection = []; line within the anonymous callback function, as well as that console.log statement.

Assigning checkbox values to variables

I've got a list of possible checkboxes and the user can select up to three options. What I'm struggling with is how to recognize which boxes are checked, and then assign them to variables (to send in a later ajax call). So far the code I've written seems to just take the first three checkbox values regardless of whether they are checked or not and use those in my ajax call. Please help me figure out where I've gone wrong.
Here's my HTML:
<ul id="Names" class="stateNames">
<li>Alabama
<ul class="airports">
<li><input type="checkbox" class="destination"/> Birmingham, AL</li>
<li><input type="checkbox" class="destination"/> Huntsville, AL</li>
</ul>
<li>Alaska
<ul class="airports">
<li><input type="checkbox" class="destination"/> Anchorage, AK</li>
<li><input type="checkbox" class="destination"/> Fairbanks, AK</li>
<li><input type="checkbox" class="destination"/> Juneau, AK</li>
</ul>
</li>
</ul>
<input type="button" onclick="clickHandler()" value="Submit" />
Here's my javascript/jquery:
function clickHandler() {
endLocDest1 = "";
endLocDest2 = "";
endLocDest3 = "";
for(i = 0; i < document.getElementsByClassName('destination').length; i++) {
if (document.getElementsByClassName('destination')[i].checked) {
endLocDest1 = document.getElementsByClassName('destination')[0].value;
endLocDest2 = document.getElementsByClassName('destination')[1].value;
endLocDest3 = document.getElementsByClassName('destination')[2].value;
}
alert(endLocDest1 + endLocDest2 + endLocDest3);
};
}
I've also put this code into a fiddle http://jsfiddle.net/6ywm1n6h/3/ (which currently doesn't return anything).
Thanks in advance!
In your jsfiddle, you had jQuery turned on, assuming that, try using ...
$(".destination:checked")
Which will return all checked; you can use this as an array and determine which are clicked.
EDIT:
You can assign this to a variable, say ...
var checked_values = $(".destination:checked");
... then loop through and do what you need.
for (var i=0,len=checked_values.length; i<len; i++) {
console.log(checked_values[i].attr("id"));
}
If your code is wrapped in <form> and </form> then checked inputs will be sent automatically when form is submitted (normaly or AJAX'ed). Your mistake is that you do not set names nor values to your checkboxes. Try:
<input type="checkbox" name="airport[alabama][]" value="Birmingham">
<input type="checkbox" name="airport[alabama][]" value="Huntsville">
<input type="checkbox" name="airport[alaska][]" value="Anchorage">
<input type="checkbox" name="airport[alaska][]" value="Fairbanks">
and see print_r($_POST) or print_r($_GET) (depending on your form method) in page which receives form submission.

Categories