javascript event handler not working (button click - google says null) - javascript

I've looked over a number of threads here of similar problems to little avail - I can't figure out exactly what's going wrong here. Google claims that the element I'm trying to reference is null
Uncaught TypeError: Cannot read property 'addEventListener' of null at sales.js:12
and no matter how I've tried to fix it, it doesn't seem to work. As you can see in the js code, I've tried a number of ways of fixing it based on stuff I've found here.
Originally the <script src ="sales.js"> in the HTML file was up in the head, but I read in some pages here that putting it there can make it load before everything else and to put it down before the HTML closing tag.
Any suggestions?
HTML Code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Sales Tax Calculator</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<main>
<h1>Sales Calculator</h1>
<p>Complete the form and click "Calculate".</p>
<fieldset>
<legend>
Item Information
</legend>
<label for="item">Item:</label>
<input type="text" id="item" ><br>
<label for="price">Price:</label>
<input type="text" id="price" ><br>
<label for="discount">Discount %:</label>
<input type="text" id="discount" ><br>
<label for="taxRate">Tax Rate:</label>
<input type="text" id="taxRate" ><br>
<label for="total">Discount Price:</label>
<input type="text" id="discountPrice" disabled ><br>
<label for="salesTax">Sales Tax:</label>
<input type="text" id="salesTax" disabled ><br>
<label for="total">Total:</label>
<input type="text" id="total" disabled ><br><br>
<div id="buttons">
<input type="button" id="calculate" value="Calculate" >
<input type="button" id="clear" value="Clear" ><br></div>
</fieldset>
<pre>© Fall 2020 Rob Honomichl - Dakota State University</pre>
</main>
</body>
<script src="sales.js"></script>
</html>
JS Code:
//"use strict"
var $ = function (id) {
return document.getElementById(id);
};
//window.addEventListener("DOMContentLoaded", () => {
//$("#calculate").addEventListener("click", processEntries);
//});
window.addEventListener('DOMContentLoaded', function () {
document.getElementById("#calculate").addEventListener("click", processEntries);
});
//window.onload = function(){
//$("#calculate").addEventListener("click", processEntries);
//};
const processEntries = () => {
//Gather User Input
//var item = document.querySelector("#item").value;
var price = parseFloat(document.querySelector("#price").value).toFixed(2);
var discount = parseInt(document.querySelector("#discount").value);
var taxRate = parseInt(document.querySelector("#taxRate").value);
//Calculate Discounted Price
function discountPriceCalc(price, discount) {
const disPrice = price * (discount/100);
return disPrice.toFixed(2);
}
//Calculate Sales Tax
function salesTaxCalc(discountPrice, taxRate) {
const taxTotal = price * (taxRate/100);
return taxTotal.toFixed(2);
}
//Calculate Total
function totalCalc(discountPrice, salesTax) {
return ((Number(discountPrice) + Number(salesTax).toFixed(2)));
}
//Calculate the disabled text box values
var discountPrice = discountPriceCalc(price, discount);
var salesTax = salesTaxCalc(discountPrice, taxRate);
var Total = totalCalc(discountPrice, salesTax);
//Update Text Boxes
document.getElementById("discountPrice").value = discountPrice;
document.getElementById("salesTax").value = salesTax;
document.getElementById("total").value = Total;
//set focus to Item box after
document.getElementById("item").focus();
};

You need to get rid of the # in the getElementById call to properly locate the element.
window.addEventListener('DOMContentLoaded', function () {
document.getElementById("calculate").addEventListener("click", processEntries);
});

Related

Calculate the sum of dynamic cloned forms for Profit and Loss in javascript Jquery

I am trying to build a Simple Profit and Loss page for my sales. The goal is:
One row equals One client.
Add a dynamic row based on number of clients.
For each row I need to input the sale amount and cost amount, then calculate the profit for that row(client).
Calculate the sum of all rows profit.
The issue: When I add a row, the button calculates only the first DOM row and not the result of the cloned ones as well.
$(document).ready(function() {
$("#addForm").click(function() {
$("#pnl").clone().appendTo(".originalPnlDiv");
});
});
function calculate() {
var salesPnl = document.getElementsbyClassName('sale').value;
var costPnl = document.getElementsbyClassName('cost').value;
var sum = document.getElementById('total').value = salesPnl - costPnl;
}
function totalProfit() {
var totalSalesPnl = document.getElementsbyClassName('sale').value;
var totalCostPnl = document.getElementsbyClassName('cost').value;
var totalSum = document.getElementById('grandTotal').value = totalSalesPnl - totalCostPnl;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>PNL</h1>
<div class="originalPnlDiv">
<form action="" id="pnl">
<select>
<option value="customerZ">customerZ</option>
<option value="customerX">customerX</option>
</select>
<input class="sale" type="number" placeholder="sale S$">
<input class="cost" type="number" placeholder="cost S$">
<input placeholder="invoice#">
<input type="date">
<input id="total"/>
</form>
</div>
<button id="addForm">Clone</button>
<button onclick="calculate()">calculate</button>
<br>
<br>
<button onclick="totalProfit()">Total Profit</button>
<p>The totalprofit is <span id="grandTotal"></span></p>
Thanks a lot for your help, I am only two months old regarding coding.
Have a nice day
don't use id when it's not going to be unique across the page.
re-organize your logic by moving the calculate button for each line
use document.querySelector and document.querySelectorAll
$(document).ready(function() {
$("#addForm").click(function() {
$("#pnl").clone().appendTo(".originalPnlDiv");
});
});
function calculate(button) {
var form = button.closest("form");
var salesPnl = form.querySelector('.sale').value;
var costPnl = form.querySelector('.cost').value;
var sum = salesPnl - costPnl;
form.querySelector('#total').value = sum;
return sum;
}
function totalProfit() {
var parent = document.querySelector(".originalPnlDiv");
var panels = parent.querySelectorAll("#pnl")
var grand = 0;
panels.forEach(function(panel) {
grand += calculate(panel);
})
document.querySelector("#grandTotal").innerText = grand;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>PNL</h1>
<div class="originalPnlDiv">
<form action="" id="pnl">
<select>
<option value="customerZ">customerZ</option>
<option value="customerX">customerX</option>
</select>
<input class="sale" type="number" placeholder="sale S$">
<input class="cost" type="number" placeholder="cost S$">
<input placeholder="invoice#">
<input type="date">
<input id="total" />
<button onclick="calculate(this); return false">calculate</button>
</form>
</div>
<button id="addForm">Clone</button>
<br>
<br>
<button onclick="totalProfit()">Total Profit</button>
<p>The totalprofit is <span id="grandTotal"></span></p>

Launching a new window and filling form values using Javascript

I have been learning JavaScript and i am attempting to launch a new window on click after a user has placed info into a form fields and then placing that info into form fields in the newly launched window. I have read many posts and methods in Stackoverflow however i cant seem to get it to work properly.
Starting page HTML:
<form id="memCat" methed="get" class="member_catalogue">
<button type="submit" class="prodBtn" id="catOrder" onclick="openMemberOrder()"><img class="prodImg" src="../../../Images/bcpot002_thumb.jpg" name="Red Bowl"></button>
<div class="cat_block">
<label class="cat_label" for="cat_name">Product Name:</label>
<input class="cat_input" type="text" id="catID" value="bepot002" readonly>
</div>
<div class="cat_block">
<label class="cat_label" for="cat_description">Product Description:</label>
<input class="cat_input" type="text" id="catDesc" value="Ocre Red Pot" readonly>
</div>
<div class="cat_block">
<label class="cat_label" for="cat_price">Per unit price:$</label>
<input class="cat_input" type="number" id="catVal" value="10" readonly>
</div>
</form>
New page HTML:
<form id="memOrder" method="post">
<div>
<label for="pname">Product Name:</label>
<input type="text" id="orderID" readonly>
</div>
<div>
<label for="pdescription">Product Description:</label>
<input type="text" id="orderDesc" readonly>
</div>
<div>
<label for="quantity">Quantity ordered:</label>
<input type="number" class="quantOrder" id="orderOrder" value="1" min="1" max="10">
</div>
<div>
<label for="ind_price">Per unit price: $</label>
<input type="number" class="quantCount" id="orderVal" readonly>
</div>
<div>
<label for="tot_price">Total Price: $</label>
<input type="number" class="quantCount" id="orderTotal" readonly>
</div>
<div>
<button type="reset">Clear Order</button>
<button type="submit" id="orderCalc">Calculate Total</button>
<button type="submit" id="orderPlace">Place Order</button>
</div>
</form>
Script i have to date:
function openMemberOrder() {
document.getElementById("orderID").value = document.getElementById("catID").document.getElementsByTagName("value");
document.getElementById("orderDesc").value = document.getElementById("catDesc").document.getElementsByTagName("value");
document.getElementById("orderVal").value = document.getElementById("catVal").document.getElementsByTagName("value");
memberOrderWindow = window.open('Member_Orders/members_order.html','_blank','width=1000,height=1000');
};
script and other meta tags in head are correct as other code is working correctly.
So after much trial and error i have had success with this:
On the submission page:
1. I created a button on the page that will capture the input form data
2. i created the localstorage function in JS
3. I then placed the script tag at the bottom of the page before the closing body tag
HTML
<button type="submit" class="prodBtn" id="catOrder" onclick="openMemberOrder()"><img class="prodImg" src="../../../Images/bcpot002/bcpot002_thumb.jpg" name="Red Bowl"></button>
Javascript
var catID = document.getElementById("catID").value;
var catDesc = document.getElementById("catDesc").value;
var catVal = document.getElementById("catVal").value;
function openMemberOrder() {
var memberOrderWindow;
localStorage.setItem("catID", document.getElementById("catID").value);
localStorage.setItem("catDesc", document.getElementById("catDesc").value);
localStorage.setItem("catVal", document.getElementById("catVal").value);
memberOrderWindow = window.open('Member_Orders/members_order.html', '_blank', 'width=1240px,height=1050px,toolbar=no,scrollbars=no,resizable=no');
} ;
Script Tag
<script type="text/javascript" src="../../../JS/catOrder.js"></script>
I then created the new page with the following javascript in the header loading both an image grid as well as input element values:
var urlArray = [];
var urlStart = '<img src=\'../../../../Images/';
var urlMid = '_r';
var urlEnd = '.jpg\'>';
var ID = localStorage.getItem('catID');
for (var rowN=1; rowN<5; rowN++) {
for (var colN = 1; colN < 6; colN++){
urlArray.push(urlStart + ID + '/' + ID + urlMid + rowN + '_c' + colN + urlEnd)
}
}
window.onload = function urlLoad(){
document.getElementById('gridContainer').innerHTML = urlArray;
document.getElementById('orderID').setAttribute('value', localStorage.getItem('catID'));
document.getElementById('orderDesc').setAttribute('value', localStorage.getItem('catDesc'));
document.getElementById('orderVal').setAttribute('value', localStorage.getItem('catVal'));
};
I then created 2 buttons to calculate a total based on inputs and clearing values separately, the script for this was placed at the bottom of the page.
function total() {
var Quantity = document.getElementById('orderQuant').value;
var Value = document.getElementById('orderVal').value;
var Total = Quantity * Value;
document.getElementById('orderTotal').value = Total;
}
function clearForm() {
var i = 0;
var j = 0;
document.getElementById('orderQuant').value = i;
document.getElementById('orderTotal').value = j;
}

When I click the Calculate button, it does not display the calculations in textbox for sales tax and total

When I run the code on my chrome browser, clicking the calculate button, it does not put the value in the Total and Sales Tax text box.
Also "Add the Javascript event handler for the click event of the Clear button, This should clear all text boxes and move the cursor to the Subtotal field."
I'm using Html and js file. Using a function expression to calculate and display my calculation, then also use the clear button to clear all text boxes.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Sales Tax Calculator</title>
<link rel="stylesheet" href="styles.css" />
<script src="sales_tax.js"></script>
</head>
<body>
<main>
<h1>Sales Tax Calculator</h1>
<p>Enter Subtotal and Tax Rate and click "Calculate".</p>
<label for="subtotal">Subtotal:</label>
<input type="text" id="subtotal" ><br>
<label for="tax_rate">Tax Rate:</label>
<input type="text" id="tax_rate" ><br>
<label for="sales_tax">Sales Tax:</label>
<input type="text" id="sales_tax" disabled ><br>
<label for="total">Total:</label>
<input type="text" id="total" disabled ><br>
<label> </label>
<input type="button" id="calculate" value="Calculate" >
<input type="button" id="clear" value="Clear" ><br>
</main>
</body>
</html>
This is my js file.
var $ = function (id) {
return document.getElementById(id);
};
var SumSalesTax = function (sub, rate){
var sales_tax = (sub * rate);
sales_tax = sales_tax.toFixed(2);
var total = (sub * rate + sub);
total = total.toFixed(2);
return sales_tax, total;
}
var processEntries = function() {
var sub = parseFloat($("subtotal").value);
var rate = parseFloat($("tax_rate").value);
if (sub < 0 && sub > 10000 && rate < 0 && rate > 12) {
alert("Subtotal must be > 0 and < 1000, and Tax Rate must be >0 and < 12.
")
} else {
$("sales_tax").value = SumSalesTax(sub, rate);
$("total").value = SumSalesTax(sub, rate);
}
};
window.onload = function() {
$("calculate").onclick = processEntries;
$("clear").onclick = sumSalesTax;
};
Sales Tax Calculator
It seems like you had a typo when you were doing $("clear").onclick = sumSalesTax;, as the variable was named SumSalesTax rather than with the lower case. This meant that the code block errored out and therefore didn't actually run. Make sure you make good use of the browser console so you can spot errors like this! The below example should work
var $ = function (id) {
return document.getElementById(id);
};
var SumSalesTax = function (sub, rate){
var sales_tax = (sub * rate);
sales_tax = sales_tax.toFixed(2);
var total = (sub * rate + sub);
total = total.toFixed(2);
return sales_tax, total;
}
var processEntries = function() {
var sub = parseFloat($("subtotal").value);
var rate = parseFloat($("tax_rate").value);
if (sub < 0 && sub > 10000 && rate < 0 && rate > 12) {
alert("Subtotal must be > 0 and < 1000, and Tax Rate must be >0 and < 12.")
} else {
$("sales_tax").value = SumSalesTax(sub, rate);
$("total").value = SumSalesTax(sub, rate);
}
};
window.onload = function() {
$("calculate").onclick = processEntries;
$("clear").onclick = SumSalesTax;
};
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Sales Tax Calculator</title>
<link rel="stylesheet" href="styles.css" />
<script src="sales_tax.js"></script>
</head>
<body>
<main>
<h1>Sales Tax Calculator</h1>
<p>Enter Subtotal and Tax Rate and click "Calculate".</p>
<label for="subtotal">Subtotal:</label>
<input type="text" id="subtotal" ><br>
<label for="tax_rate">Tax Rate:</label>
<input type="text" id="tax_rate" ><br>
<label for="sales_tax">Sales Tax:</label>
<input type="text" id="sales_tax" disabled ><br>
<label for="total">Total:</label>
<input type="text" id="total" disabled ><br>
<label> </label>
<input type="button" id="calculate" value="Calculate" >
<input type="button" id="clear" value="Clear" ><br>
</main>
</body>
</html>

javaScript Debugging Code Explanation

I am new to javaScript.
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Example</title>
<style>
body { "background-color: #fff; color: #000; font-size: 14px;
position: relative;}
form {
font-size:16px;
}
</style>
</head>
<!-- Embedded css style -->
<body>
<div>
<header>
<h1>Example</h1>
</header>
<div class= "container">
<main>
<form>
<fieldset>
<legend>
Example
</legend>
<!--asks for name-->
<label for="nameInput">Name</label>
<input type="text" id="nameInput" name="name" placeholder="John Doe" />
<br>
<!--asks for purchase price -->
<label for="amt">Amount:</label>
<input type="text" id="amt"><br>
<!--asks for state-->
<input type="radio" name="stateCode" value="k" id="k" checked> Kansas
<input type="radio" name="stateCode" value="c" id="c"> California
<input type="radio" name="stateCode" value="m" id="m">Missouri
<br>
<label for="tax">Tax :</label>
<input type="text" id="tax" disabled><br>
<label for="totalCost">Your total is:</label>
<input type="text" id="totalCost" disabled><br>
<label> </label>
<input type="button" id="calculate" value="Calculate"><br>
</fieldset>
</form>
</main>
</div><!-- end .container -->
</div><!--end of #pushDown -->
</body>
</html>
javascript:
// returns a html element (id)
var $ = function(id) {
return document.getElementById(id);
};
// calculates total after sales tax
function coffeeCalc(amt,tax) {
var totalCost = amt + tax;
totalCost = totalCost.toFixed(2); // 2 decimals
return totalCost; // returns value
}
function init() {
// assign variables to id and class values from HTML page
var amt = parseFloat( $("amt").value);
// declaring variables
var taxRate;
var stateSelected; // for console log purpose only
// radio buttons
if ($("k").checked) {
taxRate = .087; // tax rate: 8.7%
stateSelected = "Kansas";
} else if ($("c").checked) {
taxRate = .077; // tax rate: 7.7%
stateSelected = "California";
} else {
taxRate = .09; // tax rate: 9%
stateSelected = "Missouri";
}
var tax = amt * taxRate;
// shows output
$("tax").value = tax.toFixed(2); // 2 decimals
$("totalCost").value = coffeeCalc(amt,tax); //calls the coffeeCalc function
}
Image 1:
On the bottom right side: it shows totalCost: input#totalCost. The debugger displays amt: 10, so therefore I would think it would resemble amt except it should be:
total: 10.87.
Image 2: After I finish debugging the last line:
console.log(“Total Cost: “ + $(“totalCost).value);
it opens a new tab: VM236 with amt
What does that mean?
The variable totalCost in your screenshot refers to the DOM element, not the value from the coffeeCalc function, since that has already completed by the time your breakpoint has been reached (and the totalCost variable is locally scoped to that function).
You can see by typing totalCost into the console (without having broken) that there is a globally-scoped variable called totalCost, the value of which is the input element. (See screenshot here)
Regarding the new tab, the debugger is simply continuing to step through code that's running. VM... files are generated by Chrome's Dev Tools for scripts that have no sourceURL (that have been injected dynamically).
You say you are new to JS, so if you haven't already, you might want to take a look Chrome's official 'Getting Started' guide to debugging.

How to display recommendations after calculating a certain result?

How do I display something like a recommendation list after a user calculate a result from the inputs? E.g having the user to key in the salaries of the family and calculating the PCI (Per capita income) and after they key in and press on the calculate button which then will trigger a list of recommendations based on the amount of PCI the family have (Maybe tables that shows different results based on different categories of PCI?)
<!DOCTYPE html>
<html>
<head>
<script src="common.js"></script>
<script>
function cal()
{
var salary1 = document.getElementById('salary1').value;
var salary2 = document.getElementById('salary2').value;
var salary3 = document.getElementById('salary3').value;
var salary4 = document.getElementById('salary4').value;
var members = document.getElementById('members').value;
var total = (parseInt(salary1) + parseInt(salary2) + parseInt(salary3) + parseInt(salary4)) / parseInt(members);
document.getElementById('total').value = total;
alert (total);
}
</script>
</head>
<body>
<h1>Want to know which bursary your eligible?</h1>
<input id="salary1" value="" placeholder="Enter your 1st family income..."/>
<input id="salary2" value="" placeholder="Enter your 2nd family income..."/>
<input id="salary3" value="" placeholder="Enter your 3rd family income..."/>
<input id="salary4" value="" placeholder="Enter your 4th family income..."/>
<input id="members" value="" placeholder="Enter the total number of family members..."/>
<br>
<button onclick="cal()"> Calculate PCI!</button>
<br>
Total: <input id="total"> </input>
</body>
</html>
You can create a hidden div that holds the data then show that div when user clicks the button
HTML:
<div id="divToShow" style="display:none;" class="table_list" >
//put your data table here
</div>
<input type="button" name="myButton" value="Show Div" onclick="showDiv()" />
Javascript:
function showDiv() {
document.getElementById('divToShow').style.display = "block";
}
This should get you there: Jsfiddle.
<form id="form">
<input id="number1" type="number" min="1" name="number" placholder="add value one"> +
<input id="number2" type="number" min="1" name="number" placholder="add value one">
<button>Submit</button>
</form>
var form = document.getElementById('form');
number1 = document.getElementById('number1');
number2 = document.getElementById('number2');
form.onsubmit = function() {
var total = +number1.value + +number2.value; // add + before
alert( total );
};
function cal(){
var salary1 = document.getElementById('salary1').value;
var salary2 = document.getElementById('salary2').value;
var salary3 = document.getElementById('salary3').value;
var salary4 = document.getElementById('salary4').value;
var members = document.getElementById('members').value;
var recommanted;
var recommandations=[
{maxpci:1000,recommandation:'first_recommandation'},
{maxpci:2000,recommandation:'second_recommandation'},
{maxpci:3000,recommandation:'third_recommandation'},
{maxpci:6000,recommandation:'fourth_recommandation'}
];
var total=(parseInt(salary1) + parseInt(salary2) + parseInt(salary3) + parseInt(salary4)) / parseInt(members);
if(recommandations[recommandations.length - 1].maxpci < total ){recommanted=recommandations[recommandations.length - 1].recommandation;}
else{
for (var i = 0; i < recommandations.length; i++) {
if(total <= recommandations[i].maxpci){
recommanted=recommandations[i].recommandation;break;}
}}
document.getElementById('result').innerHTML = "Your PCI : "+total+"</br>Recommandation : "+recommanted;
}
<h1>Want to know which bursary your eligible?</h1>
<input id="salary1" type="number" value="" placeholder="Enter your 1st family income..."/>
<input id="salary2" type="number" value="" placeholder="Enter your 2nd family income..."/>
<input id="salary3" type="number" value="" placeholder="Enter your 3rd family income..."/>
<input id="salary4" type="number" value="" placeholder="Enter your 4th family income..."/>
<input id="members" type="number" value="" placeholder="Enter the total number of family members..."/>
</br>
<button onclick="cal()"> Calculate PCI!</button>
</br>
<div id="result">
</div>

Categories