So I'm trying to calculate sales tax for a project and I can't get it to work. Needless to say, I'm still learning javascript. Here's how it works: If the buyer selects New Jersey, I want to apply a 7% sales tax to the order. Everywhere else goes to zero.
Here's a link to the jsFiddle project: https://jsfiddle.net/JohnOHFS/hpdnmjfL/
Here's my basic form HTML (skipping the opening and closing tags, etc.)
<div id="public">
<div class="row">
<div class="col-xs-7 col-md-7">
<div class="form-group">
<label for="city">CITY</label>
<input type="text" size="20" autocomplete="off" class="city input-small form-control" placeholder="CITY"/>
</div>
</div>
<div class="col-xs-4 col-md-4">
<div class="form-group">
<label for="state">STATE</label>
<select class="form-control" id="state" onChange="taxRate()">
<option value="">N/A</option>
<option value="AK">Alaska</option>
<option value="AL">Alabama</option>
<option value="NH">New Hampshire</option>
<option value="NJ">New Jersey</option>
<option value="NM">New Mexico</option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-5 col-md-5">
<div class="form-group">
<label for="zipCode">ZIP CODE</label>
<input id="zip" type="text" size="6" autocomplete="off" class="zipcode form-control" placeholder="ZIP CODE"/>
</div>
</div>
</div>
</div> <!-- Closes Public -->
<div class="row">
<div class="col-xs-7 col-md-7">
<label>ORDER INFORMATION</label>
</div>
</div>
<div class="row">
<div class="col-xs-7 col-md-7 col-md-offset-1">
<label>SUBTOTAL: <b>$<span id="order_subtotal">100</span></b></label>
</div>
</div>
<div class="row">
<div class="col-xs-7 col-md-7 col-md-offset-1">
<label>TAXES: <b><span id="order_tax" type="text" value=""></span></b></label>
</div>
</div>
<div class="row">
<div class="col-xs-7 col-md-7 col-md-offset-1">
<label>ORDER TOTAL: <b><span id="order_total" type="text" value=""></span></b></label>
</div>
</div>
Here's the Javascript:
function taxRate() {
var tax_rate = .07;
var order_taxes = 0;
var subtotal = document.getElementById("order_subtotal").value;
subtotal = parseInt(subtotal);
var total = 0;
var state = document.getElementById("state").value;
var selection = state.options[state.selectedIndex].value;
if (selection == 'New Jersey') {
order_taxes += tax_rate * subtotal;
}
if (selection == 'else') {
order_taxes = 0;
}
if (selection == 'New Jersey') {
tax_percent = tax_rate * 100;
}
if (selection == 'else') {
tax_percent = 0;
}
var el = document.getElementById('order_tax');
el.textContent = order_taxes;
var total = subtotal + order_taxes;
var el1 = document.getElementById('order_total');
el1.textContent = total;
}
Here are my questions.
1. What am i doing wrong?
2. How do I pass tax_percent from this javascript into the html for submittal to Stripe?
Thanks!
The first problem with your fiddle is that the taxRate() function is not a global function and so it can't be called from an inline html attribute event handler. This is because by default JSFiddle wraps the JS in an onload handler. Use the JS settings menu (from top-right corner of the JS window) to change the "load type" to one of the "no wrap" options.
Then you've got a problem getting the order total value, because you try to get the element .value when it is a span, so you need to use .innerHTML.
The next thing is that your state variable is set equal to the value of the current selection of the select element. So it will be 'NJ', or 'AK', etc. (Or an empty string if nothing is selected.) So when you try to set the selection variable to state.options[state.selectedIndex].value that won't work because state is a string. Test your existing state variable against 'NJ':
if (state == 'NJ')
You also have a test if (selection == 'else') which won't do anything because even if your selection variable worked its value would never be the string 'else'. I think you just want an else statement there, except that what that block actually does is just set order_taxes = 0 and order_taxes has already been set to a default of 0 at the point of declaration. So you don't need that part at all.
Then you've got another if testing for New Jersey that could be combined with the first one. It's setting a tax_percent variable that isn't declared, so add a declaration for that with var at the top of your function.
Also, because of the way JS does floating point maths, 100 * 0.07 comes out to be 7.000000000000001. You probably want to round that off to two decimal places for the cents amount (which in this case would be no cents, but obviously if the order total wasn't such a round number you might get some number of cents in the taxes).
How do I pass tax_percent from this javascript into the html for submittal to Stripe?
One way is to add a hidden input to your form and set its value from JS:
<input type="hidden" id="tax_percent" name="tax_percent">
document.getElementById('tax_percent').value = tax_percent;
Putting that all together:
function taxRate() {
var tax_rate = .07;
var order_taxes = 0;
var tax_percent = 0;
var subtotal = document.getElementById("order_subtotal").innerHTML;
subtotal = parseInt(subtotal);
var total = 0;
var state = document.getElementById("state").value;
if (state === 'NJ') {
order_taxes += +(tax_rate * subtotal).toFixed(2);
tax_percent = +(tax_rate * 100).toFixed(2);
}
var el = document.getElementById('order_tax');
el.textContent = order_taxes;
var total = subtotal + order_taxes;
var el1 = document.getElementById('order_total');
el1.textContent = total;
document.getElementById('tax_percent').value = tax_percent;
}
Demo: https://jsfiddle.net/hpdnmjfL/5/
Related
I want to add off option value in my page
For example, you come in my shop page and choose a package, I want to add an option field for the Discount and when you enter a text that is available on s.txt you receive a discount offer.
For example, you enter a StackOverflow code and in s.txt:
stackoverflow--20
Then the price will be reduced by %20 and displayed.
My source code follows.
JavaScript:
$("#payBtn").click(function() {
$("#count").html($("#member").val());
var price = $("#member").val();
price = price * 5;
location.href = 'https://zarinp.al/levicoder/' + price;
});
$("#name").keyup(function() {
$("#payerName").html($("#name").val());
});
$("#channelInput").keyup(function() {
$("#channel").html($("#channelInput").val());
});
$("#discount").keyup(function() {
$("#disdis").html($("#discount").val());
});
$("#member").click(function() {
$("#count").html($("#member").val());
var price = $("#member").val();
price = price * 5;
$("#amount").html(price);
});
Html:
<div class="box shadow_box purchase_cm_box" >
<h4>Order</h4>
<hr>
<input type="text" class="form-control" id="name" placeholder="Your name"><br>
<input type="text" class="form-control" id="channelInput" placeholder="Your Id"><br>
<input type="text" class="form-control" id="discount" placeholder="discount code"><br>
<div class="form-group">
<select class="form-control" id="member">
<option value="9000">9000 Value</option>
<option value="2000">2000 Value</option>
</select>
<br>
</div>
</div>
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 pull-left" id="leftmenu">
<div class="box shadow_box purchase_cm_box" >
<h4>Factor</h4>
<hr>
Your Name : <label id="payerName">don't entered</label><br>
Your id : <label id="channel"></label><br>
discount code : <label id="disdis"></label><br>
Pay Count
<label id="amount">7,000</label>
$
<br><br>
<button class="getBtn" id="payBtn">Pay</button><br>
<p id="payStatus"></p>
</div>
</div>
I tried not to officially answer this question because I am unsure what LeVi needs. But as a result of our conversation in the comments, I was asked to provide code.
Here's my best guess of what LeVi is asking:
let inputCode = "stackoverflow";
let savedCode = "stackoverflow--20"; // derived from file s.txt
let splitSavedCode = savedCode.split('--'); // this will return ['stackoverflow', '20']
if( inputCode == splitSavedCode[0] ) {
// edited after further discussion in comments
let discountPercentage = splitSavedCode[1] / 100;
let discountAmount = price * discountPercentage;
$('#discount').val(discountAmount);
}
I have a HTML form that is for payment status in my panel. In this form if i select payment status Advance Paid Then displays The another input box that i can enter for the advanced paid price. There is another input box is available that is remaining price if i entered the value of advance paid the remaining price should be display the remaining value using java script. If I choose payment status is Null then display total price in remaining price input box and if i choose Paid then display 0 in remaining price input box...all things run good ...but only one thing is not working that is if i enter the value of advance price the remaining price is not displyed. Here is my HTML Code
<div class="col-md-6">
<div class="form-group">
<label>Final Total</label>
<input type="text" value="100" name="total" id="Ftotal" class="form-control" >
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="paymentstatus">Payment Status</label>
<select class="form-control" name="paymentstatus" style="height: 40px;" onchange="yesnoCheck(this);">
<option value=""> ---Select Payment Status---</option>
<option>Advance</option>
<option>Null</option>
<option>Paid</option>
</select>
</div>
</div>
<div class="col-md-6" id="ifYes" style="display: none;">
<div class="form-group">
<label for="advancepaid">Advanced Paid</label>
<input type="text" name="advancedPiad" id="advancedPiad" onKeyUp="remaining()" class="form-control">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="remainingammount">Remaining Ammount</label>
<input type="text" name="remaining" id="remaining" class="form-control remaining" >
</div>
</div>
this is my javascript
function yesnoCheck(that) {
if (that.value == "Advance") {
document.getElementById("ifYes").style.display = "block";
} else {
document.getElementById("ifYes").style.display = "none";
}
if (that.value == "Null") {
a = Number(document.getElementById('Ftotal').value);
document.getElementById('remaining').value = a;
}
if (that.value == "Paid") {
a = 0;
document.getElementById('remaining').value = a;
}
}
function remaining()
{
a = Number(document.getElementById('Ftotal').value);
b = Number(document.getElementById('advancedPiad').value);
c = a - b;
document.getElementsByClassName("remaining").value = c;
}
Try
document.getElementsByClassName("remaining")[0].value = c;
document.getElementsByClassName gives you the array of the elements with the class name specified. In your case just set the value of first element.
Try to use js parseInt() method to convert it into integer
function remaining()
{
a=parseInt(document.getElementById('Ftotal').value);
b = parseInt(document.getElementById('advancedPiad').value);
c = a - b;
document.getElementsByClassName("remaining").value = c;
}
I have a html form, where user need to enter the name and address of their office. The number of offices are dynamic.
I want to add an Add More button, so that users can enter the details of any number of offices.
My question is, how can I create an array of inputs where new elements can be added and removed using JavaScript. Currently, I'm doing it using js clone method, but I want an array, so that input data can easily be validated and stored to database using Laravel.
What I'm currently doing..
This is my HTML form where users have to enter the address of their clinic or office. I've taken a hidden input field and increasing the value of that field whenever a new clinic is added, so that I can use loop for storing data.
<div class="inputs">
<label><strong>Address</strong></label>
<input type="text" class="hidden" value="1" id="clinicCount" />
<div id="addresscontainer">
<div id="address">
<div class="row" style="margin-top:15px">
<div class="col-md-6">
<label><strong>Clinic 1</strong></label>
</div>
<div class="col-md-6">
<button id="deleteclinic" type="button" class="close deleteclinic"
onclick="removeClinic(this)">×</button>
</div>
</div>
<textarea name="address1" placeholder="Enter Clinic Address" class="form-control"></textarea>
<label class="text-muted" style="margin-top:10px">Coordinates (Click on map to get coordinates)</label>
<div class="row">
<div class="col-md-6">
<input class="form-control" id="latitude" type="text" name="latitude1" placeholder="Latitude" />
</div>
<div class="col-md-6">
<input class="form-control" id="longitude" type="text" name="longitude1" placeholder="Longitude" />
</div>
</div>
</div>
</div>
</div>
<div class="text-right">
<button class="btn btn-success" id="addclinic">Add More</button>
</div>
And my js code..
function numberClinic(){
//alert('test');
var i=0;
$('#addresscontainer > #address').each(function () {
i++;
$(this).find("strong").html("Clinic " + i);
$(this).find("textarea").attr('name','name'+i);
$(this).find("#latitude").attr('name','latitude'+i);
$(this).find("#longitude").attr('name','longitude'+i);
});
}
$("#addclinic").click(function(e){
e.preventDefault();
$("#addresscontainer").append($("#address").clone());
numberClinic();
$("#addresscontainer").find("div#address:last").find("input[name=latitude]").val('');
$("#addresscontainer").find("div#address:last").find("input[name=longitude]").val('');
$("#clinicCount").val(parseInt($("#clinicCount").val())+1);
});
function removeClinic(address){
if($("#clinicCount").val()>1){
$(address).parent('div').parent('div').parent('div').remove();
$("#clinicCount").val(parseInt($("#clinicCount").val())-1);
}
numberClinic();
}
This way, I think I can store the data to the database but can't validate the data. I'm using the laravel framework.
One way you could do this is by using the position of the input in the parent as the index in the array, then saving the value in the array every time each input is changed. Then you can just add and remove inputs.
Sample code:
var offices = document.getElementById('offices');
var output = document.getElementById('output');
var data = [];
var i = 0;
document.getElementById('add').addEventListener('click', function() {
var input = document.createElement('input');
input.setAttribute('type', 'text');
input.setAttribute('placeholder', 'Office');
var button = document.createElement('button');
var index = i++;
input.addEventListener('keyup', function() {
for (var i = 0; i < offices.children.length; i++) {
var child = offices.children[i];
if (child === input) {
break;
}
}
// i is now the index in the array
data[i] = input.value;
renderText();
});
offices.appendChild(input);
});
document.getElementById('remove').addEventListener('click', function() {
var children = offices.children;
if (children.length === data.length) {
data = data.splice(0, data.length - 1);
}
offices.removeChild(children[children.length - 1]);
renderText();
});
function renderText() {
output.innerHTML = data.join(', ');
}
JSFiddle: https://jsfiddle.net/94sns39b/2/
http://www.quirksmode.org/dom/domform.html
I am trying to implement this extend form function in my project. But the field names cannot be located (the console log returns "undefined"), until I place an input field out of the divs and directly under the parent span tag. I'm not sure how the field names can be located and named accordingly as I intend to keep the divs.
HTML:
<span id="readroot" style="display: none">
<input class="btn btn-default" type="button" value="Remove review"
onclick="this.parentNode.parentNode.removeChild(this.parentNode);">
<br><br>
<div class="row">
<div class="col-lg-3">
<div class="form-group required">
<label for="Student1Age">Age</label>
<input name="age" class="form-control" placeholder="Age"
maxlength="11" type="text" id="Student1Age" required="required">
</div>
</div>
<div class="col-lg-3">
<div class="form-group required">
<label for="Student1Grade">Grade</label>
<select name="grade" class="form-control" id="Student1Grade" required="required">
<option value="">Please Select</option>
<option value="1">Grade 1</option>
<option value="2">Grade 2</option>
</select>
</div>
</div>
</div>
</span>
<span id="writeroot"></span>
<input class="btn btn-default" type="button" onclick="moreFields()"
value="Give me more fields!">
Javascript:
var counter = 0;
function moreFields() {
counter++;
var newFields = document.getElementById('readroot').cloneNode(true);
newFields.id = '';
newFields.style.display = 'block';
var newField = newFields.childNodes;
for (var i=0;i<newField.length;i++) {
var theName = newField[i].name;
if (theName)
newField[i].name = "data[Student][" + counter + "][" + theName + "]";
console.log(newField[i].name);
}
var insertHere = document.getElementById('writeroot');
insertHere.parentNode.insertBefore(newFields,insertHere);
}
childNodes returns only direct children. It will find only elements with name attributes at the top level. To find all descendant elements with names as you want, try
var newField = newFields.querySelectorAll('[name]');
Minor points:
Although in this case you don't need to use either, you should use .children instead of .childNodes. The latter will visit white-space nodes, which won't hurt anything but isn't what you want.
You are missing brackets around the body of the if (theName) statement, meaning the console.log is being executed each time through the loop, even when a white-space node is being visited. To avoid such problems, set up your editor to indent property, and/or run a linter across your code.
if (theName) {
newField[i].name = "data[Student][" + counter + "][" + theName + "]";
console.log(newField[i].name);
}
I'd suggest naming your variables a bit more clearly. You have a variable named newFields which is a single span, and you have a variable called newField which is a collection of fields.
I have a set of number fields, each with a class "product-quantity", and a set of empty divs. the number fields are set with a data-attr small, medium, and goes up to 5xl. The empty div's are set with a data-attr small, medium, and goes up to 5xl as well because the small number field is associated with the small div and so one.
When you increase or decrease the number inside the small number field a div "small" should insert after the empty div with the attr small.
When you increase or decrease the number inside the medium number field a div "medium" should insert after the empty div with the attr medium.... and so on
additionally, all of the above belongs to a product x container, and there are multiple products on a page.
I have this jsfiddle that simulates what I am trying to do:
http://jsfiddle.net/7PhJZ/25/
however, right now when I add/subtract a number to the small number fields, it adds/subtracts a div to both the empty small/ medium div as well as in both products. and same for the medium.
I am having a hard time trying to associate which number field belongs to which empty div, which belongs to which product.
html:
<div id="product-1">
<div class="size-field">
<div id="size-label">
s
</div>
<div class="number-input">
<input id="Small" class="product-quantity" type="number" name="Small" min="0"
max="9999" data-product-id="1">
</input>
</div>
</div>
<div id="size-label">
m
</div>
<div class="number-input">
<input id="Medium" class="product-quantity" type="number" name="Medium"
min="0" max="9999" data-product-id="1">
</input>
</div>
<div class="name-number-header"><h5>HEADER<h5></div>
<div class="name-number-field-container" data-size="Small">small:
</div>
<div class="name-number-field-container" data-size="Medium">medium:
</div>
</div>
<br clear="all">
<div id="product-2">
<div class="size-field">
<div id="size-label">
s
</div>
<div class="number-input">
<input id="Small" class="product-quantity" type="number" name="Small" min="0"
max="9999" data-product-id="2">
</input>
</div>
</div>
<div id="size-label">
m
</div>
<div class="number-input">
<input id="Medium" class="product-quantity" type="number" name="Medium"
min="0" max="9999" data-product-id="2">
</input>
</div>
<div class="name-number-header"><h5>HEADER<h5></div>
<div class="name-number-field-container" data-size="Small">small:
</div>
<div class="name-number-field-container" data-size="Medium">medium:
</div>
</div>
js:
$('.product-quantity').on('change',function(){
$('.name-number-field').remove();
var val = $(this).val();
for (var i = 0; i < parseInt(val); i++){
$('<div/>',{'class':'name-number-field'}).insertAfter($("[data-size]"));
}
});
$('.product-quantity').on('change', function () {
var val = $(this).val(),
ele = $(this).closest('[id^="product"]').find('[data-size="'+this.name+'"]');
ele.nextUntil('[data-size]').remove();
for (var i = 0; i < parseInt(val); i++) {
$('<div/>', {
'class': 'name-number-field'
}).insertAfter(ele);
}
});
FIDDLE
EDIT:
Based on the comments, what you're really trying to do is just add one if the value increments, and remove the last if the value decrements, and for that the approach would be somewhat different:
$('.product-quantity').each(function() {
$(this).data('val', this.value);
}).on('change', function () {
var val = $(this).val(),
old = $(this).data('val'),
ele = $(this).closest('[id^="product"]').find('[data-size="'+this.name+'"]'),
inc = val >= old;
if (inc) {
$('<div/>', {
'class': 'name-number-field'
}).insertAfter(ele);
}else {
$('.name-number-field', ele.parent()).last().remove();
}
$(this).data('val', this.value);
});
FIDDLE
Make Use of your data-product-id and hook the textbox's parent and target the required elements.
Try this,
$('.product-quantity').on('change',function(){
$('.name-number-field').remove();
var val = $(this).val();
for (var i = 0; i < parseInt(val); i++){
$('<div/>',{'class':'name-number-field'})
.insertAfter($(this).parents('#product-' + $(this).data('product-id')).find("[data-size]"));
}
});
DEMO
Edit:
$('.product-quantity').on('change',function(){
$('.name-number-field').remove();
var val = $(this).val();
for (var i = 0; i < parseInt(val); i++){
$('<div/>',{'class':'name-number-field'})
.insertAfter($(this).parents('#product-' + $(this).data('product-id')).find("[data-size='"+ $(this).attr('name') +"'][data-size]"));
}
});
NEW - DEMO