Build string map in JS from checkboxes using jquery - javascript

I'm still learning Jquery and am trying to figure out how to build a string containing some checkbox inputs and a parent title. I have a repeating table that is basically just a title wrapped in a tag and a list of inputs as children a few layers beneath that. I want to only grab h4 titles that have at least 1 child checkbox selected, and then the names of those checkboxes along with that h4 title. basically something like this:
{(h4 value1 here),
({selected checkbox name 1,
selected checkbox name 2})
},
{(h4 value3 here),
({selected checkbox name 1,
selected checkbox name 3})
}
Here's my current html for this table being built.
<div class="specialClass" id="categoryBox">
<c:forEach items="${searchCategories}" var="cat">
<div class="col4">
<h4><span class="categorySpan">${cat.key.description}</span></h4>
<p class="stack">
<c:forEach items="${cat.value}" var="subCats">
<label>
<input class="cat" type="checkbox" name="searchCategoryBoxes" value="${subCats}"/>
${subCats}
</label>
</c:forEach>
</p>
</div>
</c:forEach>
</div>
I'm able to add names/classes/IDs as needed, but am not really sure where to start. Any pointers on which articles to read to help me figure out jquery selectors? Or alternatively any pointers on how I can solve this problem? :)

I used some of daddygames answer and modified it to get the following:
var searchCategories =
$("input[name='searchCategoryBoxes']:checked")
.parents('div[class="col4"]')
.map(function(){
var checked = false;
var subCatStr = '{' +
$(this).find('input[type="checkbox"]:checked')
.map(function() {
checked = true; return this.value;
}).get().join(',') + '}';
if (checked) {
var catStr = '{' +
$(this).find('span[class="categorySpan"]')
.html() + ',' + subCatStr + '}';
return catStr;
}
// should never get here
return '';
}).get().join(',');
on the following html block
<div id="categoryBox">
<c:forEach items="${searchCategories}" var="cat">
<div class="col4">
<h4>
<span class="categorySpan">
${cat.key.description}
</span>
</h4>
<c:forEach items="${cat.value}" var="subCats">
<label>
<input type="checkbox" name="searchCategoryBoxes" value="${subCats}"/>
${subCats}
</label>
</c:forEach>
</div>
</c:forEach>
</div>
This returned the result I was looking for.

Related

List item can't be added using javascript

I checked all the code and there is nothing wrong with it. When I check the "vegetables" radio button, write something in the text field and hit add, it doesn't add the element.
function add() {
var item;
item = document.getElementById("item").value;
if (document.getElementById("1").checked) {
var li = document.createElement(li);
text = document.createTextNode(item);
li.appendChild(text);
document.getElementById("1v").appendChild(li);
}
}
<section>
<h1>Welcome to your shopping List!</h1>
<h2>Type in the item, choose its type, and hit add !!</h2>
<div id="blue">
<form action="">
<label for="task">I need :</label><br>
<input type="text" placeholder="Example : Apples" id="item" name="item"><br>
<br>
<label for="type">which is :</label><br>
<div class="">
<input type="radio" id="1" name="type" value="Vegetables">
<label for="">Vegetables</label><br>
</div>
<br>
<button id="add" onclick="add()">Add !</button>
</section>
</form>
</div>
<br>
<footer id="white">
<div>
<table border="bold">
<th>Vegetables</th>
<tbody>
<tr>
<td>
<ol id="1v"></ol>
</td>
</tr>
</tbody>
</table>
</div>
</footer>
You have several problems:
You are using a form, so when you click the button, the form
submits and you leave the page. In your case, you aren't really going to submit data anywhere, so you really don't even need the form element or to specify name attributes for your fields.
You don't have li in quotes, so you aren't actually creating an
<li> element. Without quotes, the system thinks li is a variable, but since you don't have a variable called that, a new Global variable is created with a value of undefined, so your code executes as: document.createElement("undefined"), which does actually create: <undefined></undefined>, but since that isn't an actual HTML element, nothing is rendered for it, except the text you placed inside it (but no numbering):
var li;
let el = document.createElement(li);
console.log(el);
You are using label incorrectly. A <label> element correlates to a form-field element (i.e. input, select, textarea) as a way to have a "caption" for that element. To use it, you should set its for attribute to the id of the form-field its associated with or you can not use for and just nest the form-field its associated with inside of the label. label is not just for text you want to display.
Your HTML is not nested properly and you are missing elements.
Tables should really not be used for anything but displaying tabular
data. They should not be used for layout. Since you are creating new
ordered list items for each item added, you should not use a table.
But, even when you do, you can't just have th. th must be inside
of tr, which would then be inside of thead.
A footer element is meant to provide "the fine print" content at the end of a section. Producing your list isn't that kind of content and shouldn't be in a footer.
Here's all of that put toghether:
// Get your DOM references just once
const item = document.getElementById("item");
const list = document.getElementById("1v");
const veg = document.getElementById("type");
// Don't use inline HTML event attributes to set up events.
// Do your event binding in JavaScript, not HTML.
document.getElementById("add").addEventListener("click", add);
function add() {
if (veg.checked) {
var li = document.createElement("li"); // <-- Need quotes around the element name
li.textContent = item.value;
list.appendChild(li);
}
}
table,th,td { border:1px solid black; }
<section>
<h1>Welcome to your shopping List!</h1>
<h2>Type in the item, choose its type, and hit add !!</h2>
<div id="blue">
I need : <input type="text" placeholder="Example : Apples" id="item"><br>
<br>
which is : <input type="checkbox" id="type" value="Vegetables"> Vegetables
<div><button id="add">Add !</button></div>
</div>
</section>
<br>
<footer id="white">
<div>
Vegetables
<ol id="1v"></ol>
</div>
</footer>
2 quick fixes to your code (personally, I would rewrite the whole thing):
add type="button" to the button. It will prevent the button from defaulting to a submit.
Syntax error in var li = document.createElement(li);. the li should be in quotes:
var li = document.createElement('li');

Angular FormControl CheckBox selection marks every sibling

StackBlitz: http://stackblitz.com/edit/angular-jul7bv
I am having trouble with Angular FromControl, that are being created dynamicly based od passed data.
My list displays Groups and Subgroups of specific Data, everything works almost perfectly fine, but whenever I check subgroup, every of its sibling is being marked and i am unable to come up whats wrong.
Thats my html:
<div *ngFor="let chapter of checkboxControlLabels; let i = index;">
<div class="input-checkbox-subgroup-list__checkbox">
<div class="input-checkbox">
<input type="checkbox" [attr.id]="chapter.id + '_checkboxControl_' + i"
[formControl]="getChapterControl(i)" />
<label [attr.for]="chapter.id + '_checkboxControl_'+ i">{{ chapter.title }} </label>
</div>
</div>
<div class="input-checkbox-subgroup-list__checkbox" *ngFor="let chart of chapter.charts; let x = index;">
<div class="input-checkbox chart">
<input type="checkbox" [attr.id]="chart.title + '_checkboxControl_' + x" [formControl]="getChartControl(i, x)" />
<label [attr.for]="chart.title + '_checkboxControl_' + x">{{ chart.heading }} </label>
</div>
</div>
</div>
And this is how I am mapping specific FormControl :
getChartControl(chapterIndex: string, chartIndex: number) {
return this.data.controls[chapterIndex].get('charts').controls[chartIndex];
}
As you can see on below image when I check subgroup, there is 11 selected and I have no idea how thats possible.
More intresting thing is that this doesnt apply to groups... So if I would check First group there would be only one selected...
This is FormGroupModel that I am using later on:
this.chapterChartsData.forEach(chapters => {
dataForm.push(new FormGroup({
chapter: new FormControl(false),
charts: new FormArray(Array(chapters.charts.length).fill(new FormControl(false)))
}))
});
Apparently problem was with populating list of form controls like that :
charts: new FormArray(Array(chapters.charts.length).fill(new FormControl(false)))

How can I set default and change price with checkboxes?

I am trying to create an interface of a website which has a varying price dependent on whether check boxes are checked and which has a default value if none are selected.
The varying value is in a table which has the id 'Level1Price' which I want to default to a value of '£5.11' if neither of the two check boxes are checked and the value to chage if either one or both are selected and where the two chekc boxes on their own would hold a different value each.
The two check boxes have the id's 'partner' and 'children'. When no checkboxes are checked (for the purpose of this demonstartion) the value of 'Level1Price in the table should be 5.
If just the 'partner' checkbox is checked the value of 'Level1Price' is 10.
If just the 'children' checkbox is checked the value of 'Level1Price' is 12.
If both checkboxes are checked the value of 'Level1Price' is 20.
var partner = document.getElementById("partner");
var children = document.getElementById("children");
function calc()
if (!partner.checked && !children.checked)
{
document.getElementById('Level1Price')element.innerHTML = 5;
} else if (partner.checked && !children.checked)
{
document.getElementById('Level1Price')element.innerHTML = 10;
} else if (!partner.checked && children.checked)
{
document.getElementById('Level1Price')element.innerHTML = 12;
} else if (partner.checked && children.checked)
{
document.getElementById('Level1Price')element.innerHTML = 20;
}
This is the code that I thought would work and i'm struggling. I apologies if I have made rookie mistakes i'm quite new to this and couldn't find any working resolutions anywhere.
Thanks in advance.
These are the chekcboxes that I want to help change the vale in the table.
<div class="addition">
<label for="partner">+ Partner:</label>
<input type="checkbox" name="partner" id="partner" value="partner" required>
</div>
<div class="addition">
<label for="children">+ Children:</label>
<input type="checkbox" name="children" id="children" value="children" required>
</div>
</div>
This is the Table data I want to be able to populate
<tr>
<td scope=col id="Level1Price" value="5.11"> <b></b> <br/> per month</td>
<td scope=col id="Level2Price" value="9.97"> <b></b> <br/> per month</td>
<td scope=col id="Level3Price" value="14.06"> <b></b> <br/> per month</td>
</tr>
Is it possible to automatically update without the need for a 'calculate' button?
Provided your HTML looks like:
<span id="Level1Price"></span>
then:
document.getElementById('Level1Price').innerHTML = 20;
will result in your HTML being:
<span id="Level1Price">20</span>
Basically you just have a syntax problem (remove the erroneous 'element' text).
There is a small syntax error in your code. for better understanding, I have attached a fully functional code to meet your requirement.
Kindly refer the following code.
var partner = document.getElementById("partner");
var children = document.getElementById("children");
function calc() {
var val = 5;
if (partner.checked && !children.checked) {
val = 10;
} else if (!partner.checked && children.checked) {
val = 12;
} else if (partner.checked && children.checked) {
val = 20;
}
document.getElementById('Level1Price').innerHTML = val;
}
Partner: <input type="checkbox" id="partner" /> <br /> Children: <input type="checkbox" id="children" /> <br /> Level1 Price:
<span id="Level1Price"></span>
<br />
<button onClick="calc()">Calculate</button>
If still you find any issue or have any doubt feel free to comment, I will update my answer. TIA

How can I change the index of input element dynamically based on parent and inner parent in jquery

How can I change the index of input element dynamically based on the parent and inner parent count in jQuery.
In the following code how can I change the index of form elements
<div id='parent_container0'>
<div id='parent_inner_container0'>
<label> Name </label>
<input type='text' name='name[]'/>
<div id='child_container0'>
<div id='child_inner_container0'>
<label> Email </label>
<input type='text' name='email[]'/>
<label> Phone </label>
<input type='text' name='phone[]'/>
</div>
</div>
</div>
</div>
<div id='parent_container1'>
<div id='parent_inner_container1'>
<label> Name </label>
<input type='text' name='name[]'/>
<div id='child_container1'>
<div id='child_inner_container1'>
<label> Email </label>
<input type='text' name='email[]'/>
<label> Phone </label>
<input type='text' name='phone[]'/>
</div>
</div>
</div>
</div>
I need the changed name of form element as
name[0]
email[0][0]
phone[0][0]
name[1]
email[1][0]
phone[1][0]
Based on the parent's index of those elements in jQuery.
How can I achieve this?
Any help is appreciated.
Thanks,
Note: The requirement is to use a nested form to add more form of parent and Child with each form has nested form fields I am using the following code for changing index.
$('.parent_container').each(function(i) {
var pindex = $(this).index();
var mainfrm=$(this);
var orgname="";
mainfrm.find('.parent_container_inner').each(function(j) {
$(this).find('input, select, textarea').each(function(k){
orgname = $(this).attr('name');
orgname = orgname.replace(/[[]\d]+/g,"");
$(this).attr('name', orgname+"["+pindex+"]["+j+"]["+k+"]");
});
});
});
First, you should select your parent "containers" with:
$("div[id^=parent_container]").each(function(){
console.log(this);
});
It will print your two parent_container (parent_container0 and parent_container1). Check out here how to use selector attribute with Starts With
Then you will need to find and replace all name[], email[] and phone[].
So, you should use Ends With, to find each input you need to replace the name
$("div[id^=parent_container]").each(function(){
var parentContainerId = this.id.replace('parent_container', '');
$(this).find("input[name$='[]']").each(function(){
var newName = this.name.replace('[]', '[' + parentContainerId + ']');
this.name = newName;
})
});
Here is the Fiddle
Also, concerning your question, you should definitely take a better look into JQuery Selectors

jQuery product filter using checkboxes and :contains() show/hide

I'm attempting to put together a simple jQuery product filter for a store that lists all products of a category on one page. This can't be achieved through AJAX because of the way the store is set up.
Simply put, all products of the category are on one page. They have varying brands product names and team names. The markup looks something like this (the form at the end is how I'm planning on doing the filter).
<div id="CategoryContent">
<ul>
<li class="product">Brand1 PRODUCT1 TeamA</li>
<li class="product">Brand1 PRODUCT2 TeamB</li>
<li class="product">Brand2 PRODUCT3 TeamB</li>
<li class="product">Brand2 PRODUCT4 TeamC</li>
<li class="product">Brand3 PRODUCT5 TeamA</li>
<li class="product">Brand3 PRODUCT6 TeamD</li>
<li class="product">Brand4 PRODUCT7 TeamD</li>
<li class="product">Brand1 PRODUCT8 TeamA</li>
<li class="product">Brand1 PRODUCT9 TeamA</li>
<li class="product">Brand1 PRODUCT10 TeamB</li>
<li class="product">Brand4 PRODUCT11 TeamD</li>
<li class="product">Brand2 PRODUCT12 TeamA</li>
</ul>
<div style="clear:both;"></div>
<div class="filter">
<form id= "brandfilter" action="">
<h2>Brands:</h2>
<input type="checkbox" name="brand" value="Brand1"/>Brand1 </br>
<input type="checkbox" name="brand" value="Brand2"/>Brand2 </br>
<input type="checkbox" name="brand" value="Brand3"/>Brand3 </br>
<input type="checkbox" name="brand" value="Brand1"/>Brand4 </br>
</form>
<form id="teamfilter" action="">
<input type="checkbox" name="team" value="TeamA"/>TeamA </br>
<input type="checkbox" name="team" value="TeamB"/>TeamB </br>
<input type="checkbox" name="team" value="TeamC"/>TeamC </br>
<input type="checkbox" name="team" value="TeamD"/>TeamD </br>
</form>
I have found this filter works as I want. In console replacing hide with show and Brand1 with Brand2, TeamA, etc works just fine.
$("#CategoryContent li").not(
$("#CategoryContent li:contains(Brand1)")
).hide();
The next step is getting a double filter which works as well:
$("#CategoryContent li").not(
$("#CategoryContent li:contains(Brand1):contains(TeamA)")
).hide();
My problem with getting this working is two fold. 1 is replacing the Brand1 / Team A with variables (hence the formids).
The second is trying to run the script when a checkbox is clicked. It should work if either one is clicked and if both are clicked (meaning that with the script above it would need to reset by showing all and then hiding).
Currently to initiate it I'm running this script but I'm running into problems so I've gone back to just 1 filter.
$("input:checkbox[name='brand']").click(function() {
var brandfilter = $(this).val();
alert (brandfilter);
$("#CategoryContent li:contains(' + brandfilter + ')").parent().hide();
});
The alert that pops up is what I want (i.e. Brand1) but the hide function afterwards doesn't work and when I alert (brandfilter) again in console again I get [object HTMLFormElement]. So I think the variable isn't storing correctly or something?
Here is the simple working basic script http://jsfiddle.net/7gYJc/
Assuming you want to show items which match any currently ticked box, you can use this:
$('input:checkbox').change(showHideProducts);
function showHideProducts()
{
var checked = $('input:checked');
var products = $('.product');
// If all the boxes are unchecked, show all the products.
if (checked.length == 0)
{
products.show();
}
else
{
products.hide();
checked.each
(
function()
{
$('.product:contains("' + $(this).val() + '")').show();
}
);
}
}​
EDIT: Since you want all the boxes to display when nothing is checked, just add an if (length = 0) check and show everything in there (see above).
I can't tell where the problem is but you can try using filter() instead of the :contains selector. With filter() you can create your own custom filtering rules as it takes a function as parameter.
var myProducts = function (brand, team) {
brand = brand || '';
team = team || '';
return $('.product').filter(function () {
var re = new RegExp(brand + '.+' + team, 'i');
return re.test($(this).text());
});
};
myProducts('Brand1', 'TeamA').hide();
myProducts('Brand2').hide();
Example: http://jsfiddle.net/elclanrs/hYZcW/
I came up with the following approach:
Start with all the checkboxes checked, because you want to show all the products. If the user unticks a checkbox, then it should hide products matching that brand/team.
Here is the code I had:
var $filters = $("input:checkbox[name='brand'],input:checkbox[name=team]").prop('checked', true); // start all checked
var $categoryContent = $('#CategoryContent li'); // cache this selector
$filters.click(function() {
// if any of the checkboxes for brand or team are checked, you want to show LIs containing their value, and you want to hide all the rest.
$categoryContent.hide();
$filters.filter(':checked').each(function(i, el) {
$categoryContent.filter(':contains(' + el.value + ')').show();
});
});​
jsFiddle link.
I had the same kind of problem this week with multiple selects. The selectors worked fine, but hide did not work. I was able to solve it using
.css('visibility', 'hidden'); // instead of .hide() and
.css('visibility', ''); // instead of .show()
I do not understand it, but it worked.

Categories