Update price after checkbox is selected - javascript

I have a fairly simple problem (I think) that involves updating a number using jQuery. I have a DIV that holds a price for an item. Users can select a checkbox to add on to the total price. What I need is when someone clicks on a checkbox, it will add the correct amount to the DIV. When a user un-checks a checkbox, the value is subtracted. Here is my code so far:
<div class="cell">
<div class="check">
<input id="check-0" type="checkbox" />
<label for="check-0">$100</label>
<div class="mask"></div>
</div>
</div>
<div class="price">$347</div>
Any help is greatly appreciated!

Hopefully this is something that you could use or help you:
http://jsfiddle.net/VWRAd/
$(".cell").on("click", "input:checkbox", function () {
var $this = $(this);
var $total = $("#price");
var $target = $("label[for='" + $this.attr("id") + "']");
var item_value = +($target.html().replace("$", "") || 0);
var cur_total = +($total.html().replace("$", "") || 0);
if ($this.prop("checked") === true) {
cur_total += item_value;
} else {
cur_total -= item_value;
}
$total.html("$" + cur_total);
});
Although notice that I changed the element with the class of "price" to have an id of "price". It just makes sense, unless you expect to have several "price" elements.
And here is another possible way of doing it...not sure which is better:
http://jsfiddle.net/VWRAd/1/
$(".cell").on("click", "input:checkbox", function () {
var $items = $(".cell").find("input:checkbox:checked");
var $total = $("#price");
var cur_total = 0;
$items.each(function () {
var $this = $(this);
var $target = $("label[for='" + $this.attr("id") + "']");
var item_value = +($target.html().replace("$", "") || 0);
cur_total += item_value;
});
$total.html("$" + cur_total);
});
Some things to consider - it makes sense to separate the "$" from the actual value of the item when displaying it...I'm sure you aren't storing the value with "$", so you might want a structure similar to <label for="whatever">$<span class="the-value">100</span></label>. It would change your jQuery selector logic a little bit, but it would prevent the need for using .replace so often. Also, as someone else already pointed out, it would definitely be easier to store the item's price in the checkbox's value attribute and retrieve it that way (instead of finding the corresponding <label>'s content.

var changePrice = function changePrice(amt, state){
var curPrice = $('.price').text();
curPrice = curPrice.substring(1, curPrice.length);
if(state==true){
curPrice = parseInt(curPrice) + parseInt(amt);
}else{
curPrice = parseInt(curPrice) - parseInt(amt);
}
curPrice = '$' + curPrice;
$('.price').text(curPrice);
}
$(function(){
$('#check-0').on('change', function(){
var itemPrice = $('label[for="check-0"]').text();
itemPrice = itemPrice.substring(1, itemPrice.length);
changePrice(itemPrice, $('#check-0').is(':checked'));
});
})​;​
Demo: http://jsfiddle.net/pratik136/r2Snu/

Even though these may not be form controls intended to hit the server, i would still put the value attribute for each of the inputs.
So for the 'check-0' input, i'd put in a value attribute of 100 (to represent the $100).
Then, a bit of javascript logic should make it easy to update the price value.
So something like this should do it (http://jsbin.com/orodow/1/edit):
<div class="cell">
<div class="check">
<input id="check-0" type="checkbox" value="100" />
<label for="check-0">$100</label>
<div class="mask"></div>
</div>
</div>
<div class="cell">
<div class="check">
<input id="check-1" type="checkbox" value="50" />
<label for="check-1">$50</label>
<div class="mask"></div>
</div>
</div>
<div class="cell">
<div class="check">
<input id="check-2" type="checkbox" value="20" />
<label for="check-2">$20</label>
<div class="mask"></div>
</div>
</div>
<div class="price"></div>
<script>
$(function(){
var inputs = $('.check input:checkbox');
function updatePrice(){
var value = 0;
inputs.filter(':checked').each(function(){
value += parseInt($(this).val(), 10);
});
$('.price').html('$' + value);
}
inputs.change(updatePrice);
});
</script>

Related

Show or hide div based on selection

I am new to JQuery and I want to make a simple function. I have a div that is named based on an id of a checkbox. I want the div to be shown only if its checkbox is checked but the code is not working. It show me this error ($courseTimeDiv.hide is not a function).
this is the part where I define the checkbox
`$programList .= ' <div class="form-check proDiv">
<input type="checkbox" name="course[]" class="form-check-input group2"
id="'.$coursePrice.'" value="'.$courseId.'">
<label class="form-check-label" for="'.$coursePrice.'">'.$courseName .'
price is '.$coursePrice.'$</label>
</div>';`
this is the part of HTML code where I define the div
` $programList .= '<div name="timeDiv'.$courseId.'" class="timeGroup" >
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" id="timeRadio"
value="Weekday" name="time['.$courseId.']" />
<label class="form-check-label"><strong>Weekdays</strong>
</div> </div>';
`
and this is the JQuery code
`$("input[name='course[]']").on('change', function () {
var $courseIdValue = $('input[name="course[]"]:checked').val();
var $courseTimeDiv = $("input[name='timeDiv']") + $courseIdValue;
if($courseTimeDiv.match(/$courseIdValue/)) {
$courseTimeDiv.show(300);
}
else {
$courseTimeDiv.hide();
}
});`
any help is appreciated
var $courseTimeDiv = $("input[name='timeDiv']") + $courseIdValue;
what are you trying to do in this line?
IF, you're trying to select an element, then you can't use match method on it in the next line
IF, you're trying to create element's selector, then js engine is right and your variable does not have an element so you can select it
and in both scenarios you're doing it wrong because you're selecting an input element with name='timeDiv'+blabla while in your code there is no such element
I believe you meant
var selector = "div.timeDiv" + $courseIdValue
var $courseTimeDiv = $(selector);
it's not this simple
you have multiple checkboxes and each checkbox has it's own value, and you want all the selected ones
so
you need to process them to see which one is selected and which one is not, and match method won't help you in this process
`$("input[name*='course']").on('change', function () {
var value = $(this).val();
var selector = "div[name*=[timeDiv" + value + "]"
var courseTimeDiv = $(selector);
if( $(this).is(':checked') ){
courseTimeDiv.show(300);
} else {
courseTimeDiv.hide();
}
});`
I think this should work!
=========UPDATE==========
Previous code works, but it can be wrote in this way to have better performance
`$("input[name*='course']").on('change', function () {
var value = this.value;
var selector = "div[name*=[timeDiv" + value + "]"
var courseTimeDiv = $(selector);
if( this.checked ){
courseTimeDiv.show(300);
} else {
courseTimeDiv.hide();
}
});`

Javascript checkbox that adds value from another table to the price

Could anybody help me with this problem? I have an input price value that changes when you select different checkboxes, but it doesn't add up.
I don't really know how to fix it that if you select something, it adds to the total price, and when you select another one it adds again.
The foreach is to get all the exa_names from the Extra table with the checkbox and the price from that item.
Javascript
$(document).ready(function(){
$(".option").change(function(){
var id = $(this).attr('id');
console.log(id);
var id_number = id.split("_")[1];
console.log(id_number);
var hidden_input = $(".option_price" + id_number).val();
console.log(hidden_input);
})
});
HTML
<label>Options</label><br>
#foreach($options as $option)
<div>
<input type="checkbox" class="option" id="option_{{ $option->exa_id }}" name="option_{{ $option->exa_id }}" value="{{ $option->exa_id }}" {{ isset($cache) ? (isset($cache['option_' . $option->exa_id]) ? 'checked' : '') : (old() ? (old('option_' . $option->exa_id) ? 'checked' : '') : ($inschrijving ? (in_array($registration->exa_id, $registration_options) ? 'checked' : '') : '')) }} >
<input type="hidden" value="{{ $option->exa_price}}" class="option_price_{{ $option->exa_id }}">
<label>{{ $option->exa_name }}</label>
<label> €{{ $option->exa_price }} </label>
</div>
#endforeach
Html input totalprice(where it has to show the total price)
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label>Total</label>
<input type="text" name="totalprice" id="totalprice" class="form-control" data-blocked="<>{}" value="0" required>
</div>
</div>
</div>
RegistrationController
$options_ids_array = array();
$options = Extra::all();
foreach($options as $option){
$option->exa_id = "option_" . $option->exa_id;
$input_option = $option->exa_id;
if(!is_null($input_option)){
$options_ids_array[] = $input_option;
}
}
$registration->dev_option_id = implode(",", $options_ids_array);
$registration->save();
I think it's better to store the price of your item in a javascript variable (because it prevent to change the value of hidden input and have easy access on js side) and access to your price through your checkbox value (because it is exactly the id you tried to get with id value by split it with _ character). For add price from checked checkboxes (if they are not too much checkboxes), create a check function to detect which of them are checked and then select the price of each and add them to each other, then put it to your price place. Something like:
var options = $(".option");
var options_price = ['your', 'price', 'values', 'according', 'to', 'options', 'id'];
function optionsPrice() {
var total_price = 0;
options.each(function () {
var option = $(this);
if (option.is(':checked') && option.val() != '' && $.inArray(option.val(), Object.keys(options_price))) {
total_price += options_price[option.val()];
}
});
return total_price;
}
Call optionsPrice function on any checkbox change.
OR if you have a lot of checkeboxes on your page,
you can have a global total price variable and add or sub price from it on any checkbox change. Something like:
var total_price = 0;
var options = $(".option");
var options_price = ['your', 'price', 'values', 'according', 'to', 'options', 'id'];
var option, val;
options.on('change', function() {
option = $(this);
val = option.val();
if(val && val != '' && $.inArray(val, Object.keys(options_price)) !== -1) {
if(option.is(':checked')) {
total_price += options_price[option.val()];
} else {
if(total_price > 0) {
total_price -= options_price[option.val()];
} else {
total_price = 0;
}
}
}
});
I hope it helps :)
You've got the tricky part - uniquely identifying your inputs in JS - already done. All that is left is to sum them up!
The simplest option is to iterate over all your inputs whenever one of them changes, and recalculate the price from scratch.
I'm not 100% sure how your inputs and prices and extra costs work, but let's make it simple. Here's some example HTML in the format your Blade template could generate:
<div>
<input type="checkbox" class="option" id="option_1" name="option_1" value="1" checked>
<input type="hidden" value="1" class="option_price_1">
<label>Orange</label>
<label>1</label>
</div>
<div>
<input type="checkbox" class="option" id="option_2" name="option_2" value="2">
<input type="hidden" value="2" class="option_price_2">
<label>Apple</label>
<label>2</label>
</div>
<div>
<input type="checkbox" class="option" id="option_3" name="option_3" value="3" checked>
<input type="hidden" value="3" class="option_price_3">
<label>Pear</label>
<label>3</label>
</div>
<!-- I've added a total area to display the total result -->
<div id="total"></div>
Now taking your code, and using jQuery's .each() to iterate over all inputs on the page:
$('.option').change(function() {
// This is what we'll use to sum the prices
var total = 0;
// Use .each() to iterate over all .option inputs
$('.option').each(function(index) {
// Inside .each, $(this) represents the current element
var id = $(this).attr('id');
var id_number = id.split("_")[1];
// Note your code was missing the _ after price here
var hidden_input = $(".option_price_" + id_number).val();
// Is this option checked? If yes, we want to add its value to
// the total
if ($(this).prop('checked')) {
// .val() returns a string, prefixing hidden_input with '+' is
// a trick to cast it as a number
total += +hidden_input;
}
console.log(id, id_number, hidden_input, total);
});
// We've processed all inputs and have a total, update our page with
// the result
$('#total').html(total);
});
Done!
The above works fine, but here are some suggestions for minor improvements:
1) Use for on your labels, so that clicking on the text will also toggle the checkbox.
2) It is good practice to cache your jQuery selectors, otherwise jQuery has to parse the DOM each time to look for them. That's trivially unimportant in this example, but it is good practice to get into so you won't get bitten by problems as your pages get more complex.
3) It is good practice to separate your JS code into smaller chunks, so eg have a function that sums up the price, and a separate event handler which simply calls that when an option is changed.
Putting all that together, here's updated code:
<!-- Just one for example -->
<div>
<input type="checkbox" class="option" id="option_1" name="option_1" value="1" checked>
<input type="hidden" value="1" class="option_price_1">
<label for="option_1">Orange</label>
<label>1</label>
</div>
And now the JS:
// Cache your selectors
var $options = $('.option'),
$total = $('#total');
// Event handler, with callable function
$options.on('change', sumInputs);
function sumInputs() {
var id, id_number, hidden_input, price = 0;
$options.each(function(index) {
id = $(this).attr('id');
id_number = id.split("_")[1];
hidden_input = $(".option_price_" + id_number).val();
if ($(this).prop('checked')) {
price += +hidden_input;
}
console.log(id, id_number, hidden_input, price);
});
$total.html(price);
}

JavaScript Checkbox

I am having troubles with a script with JS, I am still learning but I am stuck for a while.
The solution should be,
IF a checkbox is checked and the value is "" <-- the msgbox should say an message that the textbox should be filled with a value, and so for each checked checkbox, if you uncheck the checkbox, it should dissapear.
Code of 2 checkboxes in html page
<label>
bangkirai
<input id="chk_bangkirai" type="checkbox" onchange="enableTextBox()" />
</label>
<input type="text" id="bangkirai" name="bangkirai" disabled onchange="enableTextBox()" />
<label>
beukenhout
<input id="chk_beukenhout" type="checkbox" />
</label>
<input type="text" id="beukenhout" name="beukenhout" disabled/>
and the JavaScript, I made for each checkbox an other function, but I need to combine the error message in the same msgbox.
function enableTextBox() {
divOutput = document.getElementById("msgbox2");
strValideer = "<ul>";
if (document.getElementById("chk_bangkirai").checked === true) {
document.getElementById("bangkirai").disabled = false;
}
else {
document.getElementById("bangkirai").disabled = true;
}
if (document.getElementById("bangkirai").value === "") {
strValideer += "<li><b>bangkirai: </b>verplicht veld</li>";
}
strValideer += "</ul>";
divOutput.innerHTML = strValideer;
}
function enableTextBox2() {
divOutput = document.getElementById("msgbox2");
strValideer = "<ul>";
if (document.getElementById("chk_beukenhout").checked === true) {
document.getElementById("beukenhout").disabled = false;
}
else {
document.getElementById("beukenhout").disabled = true;
}
if (document.getElementById("beukenhout").value === "") {
strValideer += "<li><b>beukenhout: </b>verplicht veld</li>";
}
strValideer += "</ul>";
divOutput.innerHTML = strValideer;
}
I should probably use an array or an for each itteration ... but I can only find examples with forms ...
I will keep looking for a solution myself, but I hope I can get some inspiration here by experienced coders.
Thanks in advance
You could simplify this a lot and make it more... Concise and less dependent on which checkbox you have. We will do this with an external script and no onClick attributes on our HTML. This will enable us to separate our logic code from our design code. I will also use a placeholder instead of value, as it will create issues when people need to start entering a value (aka, you need to only have the text there when theres no value etc...) It just makes it more complicated.
Since we are dealing with numbers ('stuks' or amounts), lets also only allow number values to be inserted. Lastly, I have not bothered to replicate your HTML as I think the simplified example will make it easier to understand. Update I have also added the required and disabled sattributes here, settings your input to required when the checkbox is checked and disabled when not.
Check the below snippet for comments on the steps taken to do this:
// First, let select all fieldsets like this:
var fieldsets = document.querySelectorAll( 'fieldset.checkbox-message' );
// Lets loop through them
for( let i = 0; i < fieldsets.length; i++ ){
// Lets create variables to store our fieldset, checkbox and input for later use.
let fieldset = fieldsets[ i ];
let checkbox = fieldset.querySelector( 'input[type="checkbox"]' );
let input = fieldset.querySelector( 'input[type="number"]' );
// Lets also store the message we put in placeholder
// We will also give it a default value,
// in case you forget to set the placeholder.
let message = input.placeholder || 'Please fill in the amount';
// Now lets define a function that will fill the placeholder
// based on the checked value of the checkbox
// We will be storing it in a variable because of the scope of a `for` block.
// If you would use function setState() it might be defined globally
// So multiply checkboxes would not work.
let setState = function(){
if( checkbox.checked ){
input.placeholder = message;
input.disabled = false;
input.required = true;
} else {
input.placeholder = '';
input.disabled = true;
input.required = false;
}
}
// Now lets listen for changes to the checkbox and call our setState
checkbox.addEventListener( 'change', setState );
// Lrts also call setState once to initialise the correct placeholder
// for our input element to get started. This will remove any placeholders
// if the checkboxes are unchecked.
setState();
}
<fieldset class="checkbox-message">
<label for="bangkirai">Bangkirai</label>
<input type="checkbox" id="bangkirai" />
<input type="number" placeholder="Tell us, how many 'bangkirai'?" />
<span>stuks</span>
</fieldset>
<fieldset class="checkbox-message">
<label for="beukenhout">Beukenhout</label>
<input type="checkbox" id="beukenhout" />
<input type="number" placeholder="How many 'beukenhout'?" />
<span>stuks</span>
</fieldset>
Good luck coding!
#somethinghere's answer is concise but if we modify your answer as it is you could check this
function enableTextBox() {
bangkirai_validation = document.getElementById("bangkirai_validation");
if (document.getElementById("chk_bangkirai").checked === true) {
document.getElementById("bangkirai").disabled = false;
}
else {
document.getElementById("bangkirai").disabled = true;
bangkirai_validation.style.display='none';
return;
}
if (document.getElementById("bangkirai").value =="") {
bangkirai_validation.style.display='block';
}else
{
bangkirai_validation.style.display='none';
}
}
function enableTextBox2() {
beukenhout_validation = document.getElementById("beukenhout_validation");
if (document.getElementById("chk_beukenhout").checked === true) {
document.getElementById("beukenhout").disabled = false;
}
else {
document.getElementById("beukenhout").disabled = true;
beukenhout_validation.style.display='none';
return;
}
if (document.getElementById("beukenhout").value == "") {
beukenhout_validation.style.display='block';
}else
{
beukenhout_validation.style.display='none';
}
}
<fieldset>
<legend>Bestel gegevens</legend>
<div class="container">
<div class="row">
<div class="span7 id=" houtsoorten"">
<div class="control-group">
<label class="control-label">
bangkirai
<input id="chk_bangkirai" type="checkbox"
onchange="enableTextBox()" >
</label>
<div class="controls">
<div class="input-append">
<input class="inpbox input-mini"
type="number" id="bangkirai" name="bangkirai" placeholder="aantal" disabled
onkeyup="enableTextBox()" onchange="enableTextBox()">
<span class="add-on">stuks</span>
<div style="display:none;" id="bangkirai_validation">Please enter a value</div>
</div>
</div>
</div>
<div class="control-group">
<label class="control-label">
beukenhout
<input id="chk_beukenhout" type="checkbox" onchange="enableTextBox2()" >
</label>
<div class="controls">
<div class="input-append">
<input class="inpbox input-mini"
type="number" id="beukenhout" name="beukenhout" placeholder="aantal"
disabled onkeyup="enableTextBox2()" onchange="enableTextBox2()" >
<span class="add-on">stuks</span>
<div style="display:none;" id="beukenhout_validation">Please enter a value</div>
</div>
</div>
</div>

how do I check dynamically generated radio input value

I have to generate multiple input fields dynamically for each time user clicks "add" button and I was successfully able to get them. Each contact should have this radio input field in different different name so I've created a name in an array form.
Here's what I have so far and I wonder how I'm supposed to get the radio value for each person:
var options = '';
var count = 0;
var maxfields = 4;
$('button#add').click(function() {
options = '<p>Visit Type:
<label class="radio-inline">
<input type="radio" class="c_visittype' + count +'" name="c_visittype[]" value="Student" required>Student</label>
<label class="radio-inline">
<input type="radio" class="c_visittype' + count +'" name="c_visittype[]" value="Visitor" required>Visitor</label> </p>';
if(count < maxfields){
count++;
$(options).fadeIn("slow").appendTo('.companion');
return false;
}
});
$('.c_visittype' + count).on('click', function(){
$('input:radio[name="c_visittype"]').attr('checked', 'checked');
});
Each person should get a choice of either 'student' or 'visitor' and I have to get this value for multiple persons whenever more person fields created.The reason why I put field's name as an array is to iterate it in the next page by php.
<script src="http://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
<script>
$( document ).ready(function() {
var options = '';
var count = 0;
var maxfields = 4;
$('button#add').click(function() {
var options = '<p style="display: none">Visit Type:<label class="radio-inline"> <input type="radio" class="c_visittype' + count +'" name="c_visittype' + count +'[]" value="Student" required>Student</label> <label class="radio-inline"><input type="radio" class="c_visittype' + count +'" name="c_visittype' + count +'[]" value="Visitor" required>Visitor</label> </p>';
if(count < maxfields){
count++;
$('.companion').append(options);
$(".companion p:last").fadeIn();
}
});
});
</script>
<button id="add">add</button>
<div class="companion">
</div>
$('input[name=c_visittype[]]:checked').val();
That's how you access the value of a checked radio button with jQuery.
var inputValues = [];
$('.c_visittype:checked').each(function() {
inputValues.push($(this).val());
});
// Your code using inputValues
For update on changes:
$(function() {
$('.c_visittype').click(function(){
// Insert code here
}
)});
Make sure to move the numbering from the class attribute to the name attribute (like it was, everything was part of the same set of options). Also, put the whole string on 1 line.

How to keep values of radio elements

SOLVED:
I am using jQuery to allow a user to dynamically add fields to a form and I am requiring that they select certain yes and no values. When I clone the row I need to keep the values on input radio elements but not on the text element. I was expecting that this would do it but no luck.
How would I keep the values on the radio elements?
Also when the previous node has radios selected the cloning duplicates the selection information. I DON'T want that to happen.
HTML:
<div class="dynamic-node">
<input type="text" name="custom-name[0]" value=""/>
<hr>
<input type="radio" name="haswood[0]" value="yes"/>Yes
<input type="radio" name="haswood[0]" value="no"/>No
<hr>
<input type="radio" name="hasmetal[0]" value="yes"/>Yes
<input type="radio" name="hasmetal[0]" value="no"/>No
<hr>
<input type="radio" name="hasplastic[0]" value="yes"/>Yes
<input type="radio" name="hasplastic[0]" value="no"/>No
</div>
<div class="clone-node">Add Row</div>
JQuery:
$cloneNode = $( ".clone-node" );
$cloneNode.click(function(){
var $newNode = $(".dynamic-node:last").clone(true);
$newNode.find('input').each(function() {
var $this = $(this);
$this.attr('name', $this.attr('name').replace(/\[(\d+)\]/, function($0, $1) {
return '[' + (+$1 + 1) + ']';
}));
$this.val('');
});
$newNode.insertAfter('.dynamic-node:last');
});
Solution:
Thanks to commenters below and borrowing their fresh set of eyes I resolved this by extending the code a little and making adjustment to elements based on their type and my needs:
$cloneNode = $( ".clone-node" );
$cloneNode.click(function(){
var $newNode = $(".dynamic-node:last").clone(true);
$newNode.find('input').each(function() {
var $this = $(this);
$this.attr('name', $this.attr('name').replace(/\[(\d+)\]/, function($0, $1) {
return '[' + (+$1 + 1) + ']';
}));
if( $this.is('input:text') ) {
$this.val('');
}
if( $this.is('input:radio') ) {
$this.prop('checked', false);
}
});
$newNode.insertAfter('.dynamic-node:last');
});

Categories