I have a list of products, each individual product has a checkbox value with the products id e.g. "321". When the products checkbox is checked (can be more than 1 selected) i require the value to be collected. Each product will also have a input text field for defining the Qty e.g "23" and i also require this Qty value to be collected. The Qty text input should only be collected if the checkbox is checked and the qty text value is greater than 1. The plan is to collect all these objects, put them in to a loop and finally turn them in to a string where i can then display the results.
So far i have managed to collect the checkbox values and put these into a string but i'm not sure how to collect the additional text Qty input values without breaking it. My understanding is that document.getElementsByTagName('input') is capable of collecting both input types as its basically looking for input tags, so i just need to work out how to collect and loop through both the checkboxes and the text inputs.
It was suggested that i use 2 if statements to accomplish this but i'm new to learning javascript so i'm not entirely sure how to go about it. I did try adding the if statement directly below the first (like you would in php) but this just seemed to break it completely so i assume that is wrong.
Here is my working code so far that collects the checkbox values and puts them in a string. If you select the checkbox and press the button the values are returned as a string. Please note nothing is currently appended to qty= because i dont know how to collect and loop the text input (this is what i need help with).
How can i collect the additional qty input value and append this number to qty=
// function will loop through all input tags and create
// url string from checked checkboxes
function checkbox_test() {
var counter = 0, // counter for checked checkboxes
i = 0, // loop variable
url = '/urlcheckout/add?product=', // final url string
// get a collection of objects with the specified 'input' TAGNAME
input_obj = document.getElementsByTagName('input');
// loop through all collected objects
for (i = 0; i < input_obj.length; i++) {
// if input object is checkbox and checkbox is checked then ...
if (input_obj[i].type === 'checkbox' && input_obj[i].checked) {
// ... increase counter and concatenate checkbox value to the url string
counter++;
url = url + input_obj[i].value + '&qty=' + '|';
}
}
// display url string or message if there is no checked checkboxes
if (counter > 0) {
// remove first "&" from the generated url string
url = url.substr(1);
// display final url string
alert(url);
}
else {
alert('There is no checked checkbox');
}
}
<ul>
<li>
<form>
<input type="checkbox" id="checked-product" name="checked-product" value="311">Add To Cart
<div class="quantity">
<input type="text" name="qty" id="qty" maxlength="12" value="1" class="input-text qty"/>
</div>
</form>
</li>
<li>
<form>
<input type="checkbox" id="checked-product" name="checked-product" value="321">Add To Cart
<div class="quantity">
<input type="text" name="qty" id="qty" maxlength="12" value="10" class="input-text qty"/>
</div>
</form>
</li>
<li>
<form>
<input type="checkbox" id="checked-product" name="checked-product" value="98">Add To Cart
<div class="quantity">
<input type="text" name="qty" id="qty" maxlength="12" value="5" class="input-text qty"/>
</div>
</form>
</li>
</ul>
<button type="button" onclick="javascript:checkbox_test()">Add selected to cart</button>
My answer has two parts: Part 1 is a fairly direct answer to your question, and Part 2 is a recommendation for a better way to do this that's maybe more robust and reliable.
Part 1 - Fairly Direct Answer
Instead of a second if to check for the text inputs, you can use a switch, like so:
var boxWasChecked = false;
// loop through all collected objects
for (i = 0; i < input_obj.length; i++) {
// if input object is checkbox and checkbox is checked then ...
switch(input_obj[i].type) {
case 'checkbox':
if (input_obj[i].checked) {
// ... increase counter and concatenate checkbox value to the url string
counter++;
boxWasChecked = true;
url = url + input_obj[i].value + ',qty=';
} else {
boxWasChecked = false;
}
break;
case 'text':
if (boxWasChecked) {
url = url + input_obj[i].value + '|';
boxWasChecked = false;
}
break;
}
}
Here's a fiddle showing it working that way.
Note that I added variable boxWasChecked so you know whether a Qty textbox's corresponding checkbox has been checked.
Also, I wasn't sure exactly how you wanted the final query string formatted, so I set it up as one parameter named product whose value is a pipe- and comma-separated string that you can parse to extract the values. So the url will look like this:
urlcheckout/add?product=321,qty=10|98,qty=5
That seemed better than having a bunch of parameters with the same names, although you can tweak the string building code as you see fit, obviously.
Part 2 - Recommendation for Better Way
All of that isn't a great way to do this, though, as it's highly dependent on the element positions in the DOM, so adding elements or moving them around could break things. A more robust way would be to establish a definitive link between each checkbox and its corresponding Qty textbox--for example, adding an attribute like data-product-id to each Qty textbox and setting its value to the corresponding checkbox's value.
Here's a fiddle showing that more robust way.
You'll see in there that I used getElementsByName() rather than getElementsByTagName(), using the name attributes that you had already included on the inputs:
checkboxes = document.getElementsByName('checked-product'),
qtyBoxes = document.getElementsByName('qty'),
First, I gather the checkboxes and use an object to keep track of which ones have been checked:
var checkedBoxes = {};
// loop through the checkboxes and find the checked ones
for (i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].checked) {
counter++;
checkedBoxes[checkboxes[i].value] = 1; // update later w/ real qty
}
}
Then I gather the Qty textboxes and, using the value of each one's data-product-id attribute (which I had to add to the markup), determine if its checkbox is checked:
// now get the entered Qtys for each checked box
for (i = 0; i < qtyBoxes.length; i++) {
pid = qtyBoxes[i].getAttribute('data-product-id');
if (checkedBoxes.hasOwnProperty(pid)) {
checkedBoxes[pid] = qtyBoxes[i].value;
}
}
Finally, I build the url using the checkedBoxes object:
// now build our url
Object.keys(checkedBoxes).forEach(function(k) {
url += [
k,
',qty=',
checkedBoxes[k],
'|'
].join('');
});
(Note that this way does not preserve the order of the items, though, so if your query string needs to list the items in the order in which they're displayed on the page, you'll need to use an array rather than an object.)
There are lots of ways to achieve what you're trying to do. Your original way will work, but hopefully this alternative way gives you an idea of how you might be able to achieve it more cleanly and reliably.
Check the below simplified version.
document.querySelector("#submitOrder").addEventListener('click', function(){
var checkStatus = document.querySelectorAll('#basket li'),
urls = [];
Array.prototype.forEach.call(checkStatus, function(item){
var details = item.childNodes,
urlTemplate = '/urlcheckout/add?product=',
url = urlTemplate += details[0].value + '&qty=' + details[1].value;
urls.push(url)
});
console.log(urls);
})
ul{ margin:0; padding:0}
<ul id="basket">
<li class="products"><input type="checkbox" value = "311" name="item"><input type="text"></li>
<li><input type="checkbox" value = "312" name="item"><input type="text"></li>
<li><input type="checkbox" value = "313" name="item"><input type="text"></li>
</ul>
<button id="submitOrder">Submit</button>
Related
I have a form a field called Name and with a field's id as:
'id_Name_set-0' on row 0
'id_Name_set-1' on row 1
etc...
'Name_set-0','Name_set-1' are set automatically when the rows are created.
I'm trying to autofill the Name field with the name entered on row 0.
My first approach was:
$('#id_Name_set-0').on('input',function(e){
$('#id_Name_set-1').val(String($('#id_Name_set-0').val()));
});
$('#id_Name_set-0').on('input',function(e){
$('#id_Name_set-1').val(String($('#id_Name_set-0').val()));
});
$('#id_Name_set-0').on('input',function(e){
$('#id_Name_set-2').val(String($('#id_Name_set-0').val()));
});
This works fine since i hard-coded the values 0,1,2...but i want to dynamically update those values using a loop.
You can filter your inputs using $('input[id^="id_Name_set-"]'), get the total number of them, and then just skip the first (number 0) one in the loop.
var totalDivs = $('input[id^="id_Name_set-"]').length;
for(var i = 1; i < totalDivs; i++)
{
$("#id_Name_set-" + i).val(i);
}
Obviously adapt the above to your needs such as setting all the inputs to the value of the first input. It's only an example of how to achieve it.
Use JQUERY for this, first get all inputs and set each loop on it.
this.id will get the id of which input where use inputs.
$("input").each(function(){
$(this).on("input",function(){
alert(this.id);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="input1"/>
<input id="input2"/>
<input id="input3"/>
<input id="input4"/>
This is a pretty straightforward question, but I wasn't able to find the answer to it.
Is it possible to do something like this with JavaScript and HTML? So below the names of the checkboxes in order would be 1, 2, 3, 4
<input type="checkbox" name=counter()>
<input type="checkbox" name=counter()>
<input type="checkbox" name=counter()>
<input type="checkbox" name=counter()>
function counter() {
i++;
return i;
}
No, but yes in a different way. Don't include the name attribute (or set the value as ""), and put this code after your checkboxes:
<script type="text/javascript">
var chx = document.getElementsByTagName("input");
for (var i = 0; i < chx.length; i++) {
var cur = chx[i];
if (cur.type === "checkbox") {
cur.name = "checkbox" + i;
}
}
</script>
DEMO: http://jsfiddle.net/bLRLA/
The checkboxes' names will be in the format "checkbox#". This starts counting at 0. If you want to start the names with 1 instead (like you did say), use cur.name = "checkbox" + i + 1;.
Another option for getting the checkboxes is using:
var chx = document.querySelectorAll('input[type="checkbox"]');
With this, you don't have to check the .type inside the for loop.
In either case, it's probably better not to use document, and instead use some more specific container of these elements, so that not all checkboxes are targeted/modified...unless that's exactly what you want.
In the demo, I added extra code so that when you click on the checkbox, it will alert its name, just to prove it's being set properly. That code obviously isn't necessary for what you need....just the code above.
This code could be run immediately after the checkboxes, at the end of the <body>, or in window.onload.
You can get a nodeList of all inputs on the page and then loop through them adding the loop index to whatever the common name string you want for those that have a type of "checkbox". In the following example I have used Array.forEach and Function.call to treat the array like nodeList as an array, to make looping simple.
<input type="checkbox" />
<input type="checkbox" />
<input type="checkbox" />
<input type="checkbox" />
var inputs = document.getElementsByTagName("input");
Array.prototype.forEach.call(inputs, function (input, index) {
if (input.type === "checkbox") {
inputs.name = "box" + index;
}
});
on jsfiddle
Finally, though this has been demonstrated as possible, I think you need to be asking yourself the question "why would I do it this way?". Perhaps there is a better alternative available to you.
Since you're most probably processing the form server-side. you can possibly not bother altering the form markup client-side. For example, simple changing your form markup to the following will do the trick:
<input type="checkbox" value="One" name=counter[]>
<input type="checkbox" value="Two" name=counter[]>
<input type="checkbox" value="Tre" name=counter[]>
<input type="checkbox" value="For" name=counter[]>
Then, for example, using PHP server-side:
<?php
if ( isset( $_REQUEST['counter'] ) ) {
print_r( $_REQUEST['counter'] );
}
?>
I think you're better off creating the elements in code. add a script tag in replace of your controls and use something like this (create a containing div, I've specified one named container in my code below)
for(int i = 0; i < 4; i ++){
var el = document.createElement('input');
el.setAttribute('name', 'chk' + i.toString());
document.getElementById('container').appendChild(el);
}
This post was on the right track, but I need one step further; my input names potentially have non-sequential index values assigned to them.
Background: Instead of a long series of checkboxes, I have a routine that builds a list from selecting values in a dropbox. This helps reduce real estate on the screen. So as the user selects values from the drop down, the script tries to make sure the selection does not already exist, and if it does, don't add it a second time.
The list generated looks like this:
<div id="Access:search_div">
<ul class="options">
<li onclick="removeRoleOptions(this,'Access:search_div');"><input type="hidden" name="Access:search[7]" value="1" />Standard</li>
<li onclick="removeRoleOptions(this,'Access:search_div');"><input type="hidden" name="Access:search[8]" value="1" />Premium</li>
<li onclick="removeRoleOptions(this,'Access:search_div');"><input type="hidden" name="Access:search[10]" value="1" />Lifetime</li>
<li onclick="removeRoleOptions(this,'Access:search_div');"><input type="hidden" name="Access:search[14]" value="1" />SysOp</li>
</ul>
</div>
I see plenty of examples of how to find the value, but it's just a Boolean, so if it's in the list, it will always be 1. What I need is to search the name and see what index value is attached. So for the above code, I want to compare the value of the item selected from the drop down against 7, 8, 10, and 14.
Here is the important part of the code I have so far:
function addRoleOptions(select, variable, output) {
var display=document.getElementById(output);
var option = select.options[select.selectedIndex];
var ul = display.getElementsByTagName('ul')[0];
if (!ul) {
ul = document.createElement("ul");
ul.setAttribute('class', 'options');
display.innerHTML = '';
display.appendChild(ul);
}
var choices = ul.getElementsByTagName('input');
for (var i = 0; i < choices.length; i++) {
if (choices[i].value == option.value) {
return;
}
}
option.value holds the number I'm comparing against.
So my question is, how do I parse out the value within the [] of the name to compare against the value being sent?
I am not so sure about the requirement, but then you can try using regex to extract the index from the name.
(choices[i].name).match(/[0-9]+/g) will give you the value between the []
and then you can use that value to the operation you need to do
var s = "Access:search[6543]";
var num = s.match(/\d+/)
I have a couple of checkboxes. when any of them are clickd/checked and the search button is clicked, will grab their values and pass to the url as querystring and refresh the page returning results matching the passed query values.
like this: mysite.com/result.aspx?k="Hospital" OR "Office" OR "Emergency"
I am able to grab the values after 'k='. I have "Hospital" OR "Office" OR "Emergency" captured and stored in a variable. Now I need to reset the checked state of checkboxes based on these values after the page reloads and forgets the previous state of the controls. I couldn't move any further than this. Can someone help me?
var checkedOnes=decodeURI(location.href.match(/\&k\=(.+)/)[1]);
if (value.length == 2) {
$('input[name="LocType"][value="' + value[1] + '"]').prop('checked', true);
}
This is how I am capturing the checkboxes values and passing to the URL:
var checkboxValues = $("input[name=LocType]:checked").map(function() {
return "\"" + $(this).val() + "\"";}).get().join(" OR ");
window.location= url+checkboxValues;
<div class="LocTypeChkBoxesSearch">
<div class="LocTypeChkBoxes">
<input name="LocType" type="checkbox" value="Hospital"/>HOSPITALS
<input name="LocType" type="checkbox" value="Office"/> PHYSICIAN OFFICES
<input name="LocType" type="checkbox" value="Emergency"/>EMERGENCY CENTERS
<input name="LocType" type="checkbox" value="Out-Patient"/>OUT-PATIENT CENTERS
<input name="LocType" type="checkbox" value="Facility"/>FACILITIES
</div>
<div class="searchBtnHolder"><a class="searchButton" href="#" type="submit" ><span>GO</span></a></div>
</div>
I've faced same problem, and my solution is HTML5 Local Storage.
Add an function for colect checkboxes values
function(){
var data = $('input[name=checkboxName]:checked').map(function(){
return this.value;
}).get();
localStorage['data']=JSON.stringify(data);
}
And onload function to check checkboxes
function(){
if(localStorage&&localStorage["data"]){
var localStoredData=JSON.parse(localStorage["data"]);
var checkboxes=document.getElementsByName('checkboxName');
for(var i=0;i<checkboxes.length;i++){
for(var j=0;j<localStoredData.length;j++){
if(checkboxes[i].value==localStoredData[j]){
checkboxes[i].checked=true;
}
}
}
localStorage.removeItem('data');
}
}
It's work fine to me.
You shouldn't need JavaScript for this. You can check the $_GET parameters in your back-end code, and serve the page with the proper form element attributes.
In PHP, for example:
<input name="LocType" type="checkbox" value="Facility" <?php if (isset($_GET['LocType'] && $_GET['LocType'] == 'Facility') { ?> checked="checked" <?php } ?> /> FACILITIES
Try this.
//Split the url parameter value and get all the values in an array
var checkedOnes = decodeURI(location.href.match(/\&k\=(.+)/)[1]).split(" OR ");
//Find all the checkbox with name="LocType" and cache them in local variable
var $checkBoxes = $('input[name=LocType]');
//Loop through the array and find the corresponding checkbox element using filter
$.each(checkedOnes, function(i, val){
$checkBoxes.filter('value=[' + $.trim(val.replace(/\"/g, '')) +']').prop('checked', true);
});
I am splitting the value of k by OR which will give all the values in an array. Next, loop through the array and find the corresponding checkbox by matching its value attribute and set its checked property to true using prop method.
How to iterate over enumerated Check List (check boxes) using JQuery?
Hello there, I have the following check list (containing two check boxes which have two different e-mail addresses in them):
<div id="emailCheckListId" class="checkList">
<ul id="emailCheckListId_ul">
<li>
<label for="mycomponent.emailCheckList_0" class="checkListLabel">
<input type="checkbox"
value="johndoe1#example.com"
id="mycomponent.emailCheckList_0"
name="mycomponent.emailCheckList"/>
johndoe1#example.com
</label>
</li>
<li>
<label for="mycomponent.emailCheckList_1" class="checkListLabel">
<input type="checkbox"
value="johndoe2#example.com"
id="mycomponent.emailCheckList_1"
name="mycomponent.emailCheckList"/>
johndoe2#example.com
</label>
</li>
</ul>
Am able to use a JavaScript event listener to populate / remove from a text field, every time a user clicks on an individual check box using this:
// Event listener which picks individual contacts
// and populates input field.
$('#emailCheckListId_ul input:checkbox').change(function() {
// Declare array
var emails = [];
// Iterate through each array and put email addresses into array
$('#emailCheckListId_ul input:checkbox:checked').each(function() {
emails.push($(this).val());
});
// Assign variable as To: text field by obtaining element's id.
var textField = document.getElementById("mycomponent.textfield");
// Add / Remove array from text field
textField.value = emails;
});
However, I now have an enumerated check list... Just need to append / concatenate the index number (which I stored in an hidden field and can always obtain the
correct one), but can't seem to see how to pass in the second iterator's input:checkbox:checked.
Here's the HTML source of the checked list:
<div id="mycomponent.comment0.replyToRecipientsCheckList"
class="checkList"
onclick="selectIndividualRecipients()">
<ul id="mycomponentcomment0.replyToRecipientsCheckList_ul">
<li>
<label for="mycomponent.comment0.replyToRecipientsCheckList_0"
class="checkListLabel">
<input type="checkbox"
value="johndoe1#example.com"
id="mycomponent.comment0.replyToRecipientsCheckList_0"
name="mycomponent.comment0.replyToRecipientsCheckList"/>
johndoe1#example.com
</label>
</li>
<li>
<label for="mycomponent.comment0.replyToRecipientsCheckList_1"
class="checkListLabel">
<input type="checkbox"
value="johndoe2#example.com"
id="mycomponent.comment0.replyToRecipientsCheckList_1"
name="mycomponent.comment0.replyToRecipientsCheckList"/>
johndoe2#example.com
</label>
</li>
</ul>
</div>
JavaScript:
// Uses an event listener which picks individual contacts
// and populates input field.
function selectIndividualRecipients() {
var checkListPrefix = 'mycomponent.comment';
var index = document.getElementById("commentHiddenField").value;
var checkListPostfix = '.replyToRecipientsCheckList_ul';
var event = checkListPrefix + index + checkListPostfix;
$(event).change(function() {
// Declare array
var emails = [];
// Iterate through each array and put email addresses into array
// THIS DOESN'T SEEM TO BE WORKING:
var test = '#' + event.attr('id') + 'input:check:checked';
$(test).each(function() {
alert('inside iterator');
alert('this.val: ' + $(this).val());
emails.push($(this).val());
alert('emails = ' + emails);
});
// Assign variable to Reply To: text field by obtaining element's id.
var textField = document.getElementById(indexedReplyTextField);
// Add / Remove array from text field
textField.value = emails;
}
The browser says that ($test).each() throws an exception which is not caught and this is not allowed...
What am I possibly doing wrong?
Have you tried changing your var test declaration as follows?
var test = '#' + event.attr('id') + ' input:checkbox:checked';
Notice the space before input and checkbox instead of check.
There may be an easier method:
$('div.checkList').delegate('input', 'change', function() {
textField.value = $('div.checkList ul li input:checked').map(function() {
return $(this).val();
}).get().join('; ');
});