I am creating an A/B test variant using VWO.
The website has a list with checkboxes laid out like so;
<ol>
<li>
<label>
<input class="checkBox" type="checkbox">
<p class="checkBoxAnc">Text to grab</p>
</label>
</li>
</ol>
There is an apply button, when this is clicked I want it to cycle through all of the inputs. If checked is true then I need to grab the text from the class "checkBoxAnc" (p element) and concatenate it to a variable.
I have tried the following:
var self= $(this);
//This is referring to the input that the user has clicked, so class '.checkBox'
self.next() // This doesn't work as element's do not match
self.nextUntil('.checkBoxAnc') // Same issue as .next()
var checkBoxSibling = self.parent().find('.checkBoxAnc').text();
// This returns an empty string
When trying to find the parent type this is being returned as 'undefined' rather than 'label'
Are there any other techniques to access '.checkBoxAnc'?
Something like this...
var foo = '';
$('input[type=checkbox]:checked').map(function() {
foo += $(this).next().text(); // value your looking for
}).get();
https://jsfiddle.net/cmac_/8w7vghbt/
Related
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>
I have input box along with checkbox in table <td> like below,
<td>
<input class="Comment" type="text" data-db="comment" data-id="{{uid}}"/>
<input type="checkbox" id="summary" title="Check to set as Summary" />
</td>
Based on check box only the content of input box will be stored in DB.
In the JS file, I tried like
var updateComment = function( eventData )
{
var target = eventData.target;
var dbColumn = $(target).attr('data-db');
var api = $('#api').val();
var newValue = $(target).val();
var rowID = $(target).attr('data-id');
var summary = $('#summary').is(':checked');
params = { "function":"updatecomments", "id": rowID, "summary": summary };
params[dbColumn] = newValue;
jQuery.post( api, params);
};
$('.Comment').change(updateComment);
But the var summary always returning false.
I tried so many ways prop('checked'),(#summary:checked).val() all are returning false only.
How to solve this problem?
Looks like you have multiple rows of checkboxes + input fields in your table. So doing $('#summary').is(':checked') will return the value of first matching element since id in a DOM should be unique.
So, modify your code like this:
<td>
<input class="Comment" type="text" data-db="comment" data-id="{{uid}}"/>
<input type="checkbox" class="summary" title="Check to set as Summary" />
</td>
And, instead of $('#summary').is(':checked'); you can write like this:
var summary = $(target).parent().find(".summary").is(':checked');
By doing this, we are making sure that we are checking the value of checkbox with the selected input field only.
Update: For listening on both the conditions i.e. when when checking checkbox first and then typing input box and when first typing input box and then checked:
Register the change event for checkbox:
// Whenever user changes any checkbox
$(".summary").change(function() {
// Trigger the "change" event in sibling input element
$(this).parent().find(".Comment").trigger("change");
});
You have missed the jQuery function --> $
$('#summary').is(':checked')
('#summary') is a string wrapped in Parentheses. $ is an alias for the jQuery function, so $('#summary') is calling jquery with the selector as a parameter.
My experience is that attr() always works.
var chk_summary = false;
var summary = $("#summary").attr('checked');
if ( summary === 'checked') {
chk_summary = true;
}
and then use value chk_summary
Change all the occurrences of
eventData
To
event
because event object has a property named target.
And you should have to know change event fires when you leave your target element. So, if checkbox is checked first then put some text in the input text and apply a blur on it, the it will produce true.
Use like this
var summary = $('#summary').prop('checked');
The prop() method gets the property value
For more details, please visit below link.
https://stackoverflow.com/a/6170016/2240375
I have this js to update a span value with a new value coming from some math.
$('.ammesso').blur(function(){
ammesso = $(this).val();
perc_worst ='<?php echo $az_info['perc_worst']; ?>';
if(isNaN(ammesso)){
console.log(ammesso);
}else{
flusso = ammesso*perc_worst/100;
var jsonObject = $.parseJSON(prevs);
console.log(prevs);
$.each(jsonObject, function (i, obj) {
console.log(obj.id);
var id_item = obj.id;
//it gets the right value of 393
console.log('testo: '+$(this).parent('fieldset').find('.cl'+id_item).text());
});
console.log('flusso calcolato: '+flusso);
}
});
The html is the following:
<fieldset>
<label>Ammesso: </label><input type="text" name="ammesso[0]" value="" class="ammesso numerico">
<label>Incassi previsti: </label>
<ul id="lista">
<li class="soff_grp">Value - <span class="cl393">CASH</span></li>
</ul>
</fieldset>
console.log('testo: '+$(this).parent('fieldset').find('.cl'+id_item).text()); should return what is now inside the span but I miss what is wrong and why I cannot select the span.
My assumptions are:
with .parent('fieldset') I come back to the first DOM element input
and span have in common
with .find('.cl'+id_item) I get the first element with that class
(that is present in the rendered HTML)
What is wrong in how I use this two selectors? As per what I understand of what I have read in the jQuery documentation it seems to me the right way to select it!
the context of input element is lost in each function. this refers to element in jsonObject on which you are iterating. You need to store the element context outside each loop and then use it in each function:
var fieldset = $(this).parent('fieldset');
$.each(jsonObject, function (i, obj) {
console.log(obj.id);
var id_item = obj.id;
//it gets the right value of 393
console.log('testo: ' + fieldset.find('.cl'+id_item).text());
});
my html code:
<li id='category-10'>
<label class="selectit">
<input value="10" type="checkbox" name="post_category[]" id="in-category-10" /> Developmental
</label>
</li>
my javascript code:
function onCategoryClick() {
$(".selectit").click(function(e){
var categoryValue = $(e.target).text();
alert("The value is " + categoryValue);
});
}
This returns me the string "The value is Developmental" but what I want is "The value is 10"
I'm new to Javascript, how would I go about targeting the value field in the input, instead of the text?
I've also tried
var categoryValue = $(e.target > input).value;
But this doesn't return anything.
Instead of
$(e.target).text();
try
$(this).find('#in-category-10').val();
Here e.target corresponds to the label . And it has text 'Developmental' and also a nested input element.
So you need to use find to access it. (If there is no id)
But ID is supposed to be unique on the page. So to access the element you can directly used the id selector
var categoryValue = $('#in-category-10').val();
And remember that input has no text property. Need to use the val 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('; ');
});