I have a list of results from year to year.
<tr *ngFor="let d of histroricalData; let i = index">
<td>
{{d.YearCalculation}}
</td>
<td>
{{d.OverallResult}}%
</td>
<td>
<!--subtract previous year from current -->
</td>
</tr>
How would I subtract the previus result from the current one in the loop?
This is what I want to achieve using a regular for loop
for (let i = 0; i < this.histroricalData.length; i++) {
if (this.histroricalData[i - 1] != null) {
let calc = this.histroricalData[i].OverallResult - this.histroricalData[i - 1].OverallResult
console.log(Math.round(calc * 100) / 100);
}
}
This a just a idea. You can initialize a array called indexArray something like [0,1,2,3,4,5,6] and use it for the loop as follows
<tr *ngFor="let d of histroricalData; let i of indexArray">
<td>
{{d.YearCalculation}}
</td>
<td>
{{d.OverallResult}}%
</td>
<td *ngIf="histroricalData[i - 1] != null">
{{histroricalData[i].OverallResult - histroricalData[i - 1].OverallResult}}
</td>
</tr>
You can always take help of index,
So, you can use
{{histroricalData[i - 1].OverallResult - histroricalData[i].OverallResult}}%
or,
{{(histroricalData[i - 1]['OverallResult']) - (histroricalData[i]['OverallResult'])}}%
The code becomes,
<tr *ngFor="let d of histroricalData; let i = index">
<td>
{{d.YearCalculation}}
</td>
<td>
{{histroricalData[i - 1].OverallResult - histroricalData[i].OverallResult}}%
</td>
<td>
<!--subtract previous year from current -->
</td>
</tr>
It works for you.
template:
<tr *ngFor="let d of histroricalData; let i = index">
<td>
{{d.YearCalculation}}
</td>
<td>
{{d.OverallResult}}%
</td>
<td *ngIf="i > 0">
{{getCalculatedValue(histroricalData[i].overallResult - histroricalData[i-1].overallResult)}}
</td>
</tr>
ts file:
getCalculatedValue(value){
return Math.round(value * 100) / 100;
}
Related
I am trying to make a simple dieting calculator with my limited HTML, CSS, and JS knowledge. While I was partway through coding the Javascript (the third step for the user out of five), my third variable was returning as 0, when it should return as something else (~10-15) My logic works like this:
A user clicks a button from a group that specifies to them.
For the first function, st1 = (a number that specifies on which button is pressed)
Do note that at the start of the js, the variables are already declared (let st1 = 0; let st2 = 0; etc.)
For the second function, st2 = parseInt(st1) + (another number)
The same thing happens for the 3rd function
I have not finished the rest
I have tried console.log()ing st2 when the third step is called, and it returns as 0. Thanks for any help!
Here is the HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="script.js"></script>
<table>
<tr>
<td>
<p id="step1">Step 1.</p>
</td>
<td>
Gender:
</td>
<td>
<table>
<tr>
<td>
<button onclick="Male()">Male</button>
</td>
</tr>
<tr>
<td>
<button onclick="Female()">Female</button>
</td>
</tr>
<tr>
<td>
<button onclick="Other()">Other/Prefer Not to say</button>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<p id="step2">Step 2.</p>
</td>
<td>
Age:
</td>
<td>
<table>
<tr>
<td>
<button onclick="seventeen()">Between 17-26</button>
</td>
</tr>
<tr>
<td>
<button onclick="twentyseven()">Between 27-37</button>
</td>
</tr>
<tr>
<td>
<button onclick="thirtyeight()">Between 38-47</button>
</td>
</tr>
<tr>
<td>
<button onclick="fortyeight()">Between 48-57</button>
</td>
</tr>
<tr>
<td>
<button onclick="fiftyeight()">Over 58</button>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<p id="step3">Step 3.</p>
</td>
<td>
Height
</td>
<td>
<table>
<tr>
<td>
<button onclick="under5()">Below 5ft</button>
</td>
</tr>
<tr>
<td>
<button onclick="btwn()">Between 5'0" - 5'9"</button>
</td>
</tr>
<tr>
<td>
<button onclick="over()">Over 5'10"</button>
</td>
</tr>
</table>
</td>
</tr>
</body>
</html>
And here is the JS:
let st1 = 0;
let st2 = 0;
let st3 = 0;
//Start Group one, these three functions are each called when clicking a button with the user's gender
function Male() {
st1 = 8;
document.getElementById("step1").innerHTML = "Complete";
console.log(st1);
}
function Female() {
st1 = 2;
document.getElementById("step1").innerHTML = "Complete";
console.log(st1);
}
function Other() {
st1 = 4;
document.getElementById("step1").innerHTML = "Complete";
console.log(st1);
}
//End Group one
//Start group two, each of these are called when the user clicks a button with their age group.
function seventeen() {
let st2 = parseInt(st1) + 4;
document.getElementById("step2").innerHTML = "Complete";
console.log(st2)
}
function twentyseven() {
let st2 = parseInt(st1) + 3;
document.getElementById("step2").innerHTML = "Complete";
console.log(st2);
}
function thirtyeight() {
let st2 = parseInt(st1) + 2;
document.getElementById("step2").innerHTML = "Complete"
console.log(st2);
}
function fortyeight() {
let st2 = parseInt(st1) + 1;
document.getElementById("step2").innerHTML = "Complete"
console.log(st2);
}
function fiftyeight() {
let st2 = parseInt(st1) + 0;
document.getElementById("step2").innerHTML = "Complete"
console.log(st2)
}
//End group 2
//Start Group 3, The user clicks a button with their height range.
function under5() {
let st3 = st2 + 0;
document.getElementById("step3").innerHTML = "Complete";
console.log(st3);
}
function btwn() {
let st3 = parseInt(st2) + 1;
document.getElementById("step3").innerHTML = "Complete";
console.log(st3);
}
function over() {
let st3 = parseInt(st2) + 2 ;
document.getElementById("step3").innerHTML = "Complete";
console.log(st3);
}
//End group 3
//There are two more groups I haven't finished coding, so won't include here.
when you put the keyword let before the variable, it gets redeclared. try removing the lets from the functions.
also, you could do something like this, though there are even better ways...
<button onclick="gender(8)">Male</button>
<button onclick="gender(2)">Female</button>
function gender( value ) {
std1 = value;
}
I'm very new to JS and I'm trying to learn for loops and in this case, I want to turn this into a for loop if possible. I want to calculate a static number string in cell 3, times the input number in cell 4, and output the result to a new cell 5 that has been created in the loop. Any help is much appreciated
var table = document.getElementById("table");
var Row1 = table.rows[1],
cell1 = Row1.insertCell(5);
var Row2 = table.rows[2],
cell2 = Row2.insertCell(5);
var Row3 = table.rows[3],
cell3 = Row3.insertCell(5);
var Row4 = table.rows[4],
cell4 = Row4.insertCell(5);
var Row5 = table.rows[5],
cell5 = Row5.insertCell(5);
var Row6 = table.rows[6],
cell6 = Row6.insertCell(5);
var x1 = table.rows[1].cells[4].getElementsByTagName('input')[0].value;
var y1 = table.rows[1].cells[3].innerHTML;
cell1.innerHTML = y1 * x1;
var x2 = table.rows[2].cells[4].getElementsByTagName('input')[0].value;
var y2 = table.rows[2].cells[3].innerHTML;
cell2.innerHTML = y2 * x2;
var x3 = table.rows[3].cells[4].getElementsByTagName('input')[0].value;
var y3 = table.rows[3].cells[3].innerHTML;
cell3.innerHTML = y3 * x3;
var x4 = table.rows[4].cells[4].getElementsByTagName('input')[0].value;
var y4 = table.rows[4].cells[3].innerHTML;
cell4.innerHTML = y4 * x4;
var x5 = table.rows[5].cells[4].getElementsByTagName('input')[0].value;
var y5 = table.rows[5].cells[3].innerHTML;
cell5.innerHTML = y5 * x5;
var x6 = table.rows[6].cells[4].getElementsByTagName('input')[0].value;
var y6 = table.rows[6].cells[3].innerHTML;
cell6.innerHTML = y6 * x6;
These don't need to be in functions but just to make it easier to read
function createCells() {
cells = []
for (let i = 1; i < 7; i++) {
var cells[i] = table.rows[i].insertCell(5)
}
}
function calculate() {
for
let (i = 1; i < 7; i++) {
var x = table.rows[i].cells[4].getElementsByTagName('input')[0].value;
var y = table.rows[i].cells[3].innerHTML;
cells[i].innerHTML = (y * x);
}
}
A short answer using a simple for-loop is this:
Loop through every row
For each row, multiply quantity with price
Output total in same row
Since we basically always want to have a "total"-field in every row, we can add it in the HTML directly.
And since we know the position of the price-element and quantity-element, we can access them using fixed values as indices.
var rows = document.querySelectorAll("#pricetable tbody tr");
for (var i = 0; i < rows.length; ++i) {
var price = rows[i].children[3].innerHTML;
var quantity = rows[i].children[4].children[0].value;
var total = price * quantity; // Implicit type-casting to numbers
rows[i].children[5].innerHTML = total;
}
<table id="pricetable">
<thead>
<tr>
<th>Number</th>
<th>Product</th>
<th>Brand</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr>
<td>23456789</td>
<td>Phone</td>
<td>Apple</td>
<td>6500</td>
<td>
<input type="text" size="3" value="1" />
</td>
<td></td>
</tr>
<tr>
<td>22256289</td>
<td>Phone</td>
<td>Samsung</td>
<td>6200</td>
<td>
<input type="text" size="3" value="1" />
</td>
<td></td>
</tr>
<tr>
<td>24444343</td>
<td>Phone</td>
<td>Huawei</td>
<td>4200</td>
<td>
<input type="text" size="3" value="1" />
</td>
<td></td>
</tr>
<tr>
<td>19856639</td>
<td>Tablet</td>
<td>Apple</td>
<td>4000</td>
<td>
<input type="text" size="3" value="1" />
</td>
<td></td>
</tr>
<tr>
<td>39856639</td>
<td>Tablet</td>
<td>Samsung</td>
<td>2800</td>
<td>
<input type="text" size="3" value="1" />
</td>
<td></td>
</tr>
<tr>
<td>12349862</td>
<td>Tablet</td>
<td>Huawei</td>
<td>3500</td>
<td>
<input type="text" size="3" value="1" />
</td>
<td></td>
</tr>
</tbody>
</table>
Note: When changing the position of those elements (e.g. by add a new column infront of them), their index would shift. That would make you have to update the indices in the JS-file manually.
You can make this easier for yourself by using this simple "trick":
Add specific classes to the elements (e.g. .price, .quantity, .total), allowing you to easily find them using Element.querySelector().
Note: The script only runs once, the first time the page is loaded. That means, inputting a different quantity won't update the "total"-field. For that, we need an EventListener.
Another approach
By observing the for-loop, we can see:
We access only one row for each iteration
The order in which we access each row is irrelevant
Since both these points are checked, we can use a for...of-loop (also called foreach-loop or enhanced for-loop). A for...of-loop is (in my opinion) easier to read, and tells what we checked using the list above by itself.
Note: Be wary of the difference of the for...of-loop and the for...in-loop.
Now, we could calculate the total right then and there in the loop, but thinking ahead, we want to perform the same calculation again when inputting a new quantity-value. We can reduce the duplicate code by making the calculation a Function updateRowTotal(), making the code easier to debug and understand.
To actually update the total when entering a new quantity-value, we can use an EventListener that calls a function automatically when a new value is entered into the <input>-field (by calling updateRowTotal(evt.target.closest("tr"))).
function clamp(min, value, max) {
return Math.max(min, Math.min(value, max));
}
for (let row of document.querySelectorAll("#pricetable tbody tr")) {
updateRowTotal(row);
row.querySelector("input.quantity").addEventListener("input", evt => {
// Add '/*' before this comment to "remove" this extra part
// The 5 lines below are to clamp 'value' between 'min' and 'max'
let min = parseInt(evt.target.getAttribute("min"));
let max = parseInt(evt.target.getAttribute("max"));
if (isNaN(min)) min = Number.MIN_SAFE_INTEGER;
if (isNaN(max)) max = Number.MAX_SAFE_INTEGER;
evt.target.value = clamp(min, evt.target.value, max);
// */
updateRowTotal(evt.target.closest("tr"));
});
}
function updateRowTotal(row) {
row.querySelector(".total").innerHTML = row.querySelector(".price").innerHTML * row.querySelector(".quantity").value;
}
<table id="pricetable">
<thead>
<tr>
<th>Price</th>
<th>Quantity</th>
<th>Row-Total</th>
</tr>
</thead>
<tbody>
<tr>
<td class="price">6500</td>
<td>
<input class="quantity" type="number" min="0" max="999" value="1" />
</td>
<td class="total"></td>
</tr>
<tr>
<td class="price">6200</td>
<td>
<input class="quantity" type="number" min="0" max="999" value="1" />
</td>
<td class="total"></td>
</tr>
<tr>
<td class="price">4200</td>
<td>
<input class="quantity" type="number" min="0" max="999" value="1" />
</td>
<td class="total"></td>
</tr>
<tr>
<td class="price">4000</td>
<td>
<input class="quantity" type="number" min="0" max="999" value="1" />
</td>
<td class="total"></td>
</tr>
<tr>
<td class="price">2800</td>
<td>
<input class="quantity" type="number" min="0" max="999" value="1" />
</td>
<td class="total"></td>
</tr>
<tr>
<td class="price">3500</td>
<td>
<input class="quantity" type="number" min="0" max="999" value="1" />
</td>
<td class="total"></td>
</tr>
</tbody>
</table>
Sidenote
Making the <input>-field of type="number" prevents any non-numeric character to be entered.
And since the min- and max-attributes only prevent form-submission, we have to code the value-clamping ourselves. This is easily done by reading the values of the attributes and clamping the value to their defined range. Note that we have added default values for both min and max, being the lower-most and upper-most safe integer-value.
You can use for-loops like the one given below. Looks like you are operating on numbers, so I have added a + in front of x1's and y1's assignment to implicitly type-cast them to numbers.
for(var i = 1; i <= 6; i++) {
var firstRow = table.rows[i], cell = firstRow.insertCell(5);
var x1 = +table.rows[i].cells[4].getElementsByTagName('input')[0].value;
var y1 = +table.rows[i].cells[3].innerHTML;
cell.innerHTML = y1 * x1;
}
I have table data for UP and DOWN counts and I want to calculate and display "uptime" as a percentage, for several targets within a the same table. Source counts have commas that must be removed, and I need to show the results to 3 decimal places (no rounding). Some targets begin with a number. The table itself is from an external source, displayed in an iFrame.
So far I have got the decimal places truncating, but I am looking for help parsing the table columns and rows to remove the commas and do the math.
(100 - (downCount / upCount * 100))
EDIT: The accepted answer changed this to:
(upCount / (upCount + downCount) * 100)
https://jsfiddle.net/ncarlton/d12ec7q3/1/
Vanilla JavaSript only please (no jQuery).
JavaScript Starter:
// these are the "correct" answers I'm trying to calculate from sourceTable data
let firstTargetCalc = (100 - (42 / 2218563 * 100));
let _2ndTargetCalc = (100 - (3 / 239384 * 100));
let thirdTargetCalc = (100 - (0 / 8340 * 100));
// this is how I want to truncate the decimals -- not rounding
function truncateDecimals(num, digits) {
var numS = num.toString(),
decPos = numS.indexOf('.'),
substrLength = decPos == -1 ? numS.length : 1 + decPos + digits,
trimmedResult = numS.substr(0, substrLength),
finalResult = isNaN(trimmedResult) ? 0 : trimmedResult;
return parseFloat(finalResult);
}
// here's the "final" answers with the truncation
let trunc1st = truncateDecimals(firstTargetCalc, 4)
let trunc2nd = truncateDecimals(_2ndTargetCalc, 4)
let trunc3rd = truncateDecimals(thirdTargetCalc, 4)
// here's what I want to display to the end user as the calculated uptime for each target
// alert('firsttarget uptime: ' + trunc1st + '%\n2ndtarget uptime: ' + trunc2nd + '%\nthirdtarget uptime: ' + trunc3rd + '%');
The full HTML with a large extraneous <thead> is in the JSFiddle. But the important part might look like this in the <tbody> for three targets. The number of targets will vary but will usually be fewer than ten.
HTML:
<tr>
<td class="cell-hover ng-scope" ng-click="clickHandler($event)">firsttarget</td>
<td>UP</td>
<td class="numeric-value">2,218,563</td>
</tr>
<tr>
<td class="cell-hover ng-scope" ng-click="clickHandler($event)">firsttarget</td>
<td>DOWN</td>
<td class="numeric-value">42</td>
</tr>
<tr>
<td class="cell-hover ng-scope" ng-click="clickHandler($event)">2ndtarget</td>
<td>UP</td>
<td class="numeric-value">239,384</td>
</tr>
<tr>
<td class="cell-hover ng-scope" ng-click="clickHandler($event)">2ndtarget</td>
<td>DOWN</td>
<td class="numeric-value">3</td>
</tr>
<tr>
<td class="cell-hover ng-scope" ng-click="clickHandler($event)">thirdtarget</td>
<td>UP</td>
<td class="numeric-value">8,340</td>
</tr>
<tr>
<td class="cell-hover ng-scope" ng-click="clickHandler($event)">thirdtarget</td>
<td>DOWN</td>
<td class="numeric-value">0</td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
</tr>
</tbody>```
[1]: https://i.stack.imgur.com/SNDdW.png
You can use regex to parse your table rather than iterating rows; your calculation to get the percentage is also incorrect. See snippet for working example.
function showTableData() {
const targetTable = document.getElementById('jstable'); // where to draw the new table
const sourceTable = document.querySelector(".table"); // set kibana as
const innerText = sourceTable.innerText;
const ups = innerText.match(/(\w*(target))\s*(UP)\s*[\d,]*\d(?! )/g);
const downs = innerText.match(/(\w*(target))\s*(DOWN)\s*[\d,]*\d(?! )/g);
let innerHTML = "";
for (let i = 0; i < ups.length; i++) {
const up = ups[i];
const down = downs[i];
const target = up.match(/(\w*(target))/)[0];
const upCount = parseInt(up.match(/[\d,]*\d$/)[0].replace(/,/g, ""));
const downCount = parseInt(down.match(/[\d,]*\d$/)[0].replace(/,/g, ""));
const percentage = (upCount / (upCount + downCount) * 100).toFixed(3)
innerHTML += `${target} uptime: ${percentage}%<br/><br/>`
}
targetTable.innerHTML = innerHTML;
}
// these are the "correct" answers I'm trying to calculate from sourceTable data
let firstTargetCalc = (100 - (42 / 2218563 * 100));
let _2ndTargetCalc = (100 - (3 / 239384 * 100));
let thirdTargetCalc = (100 - (0 / 8340 * 100));
// this is how I want to truncate the decimals -- not rounding
function truncateDecimals(num, digits) {
var numS = num.toString(),
decPos = numS.indexOf('.'),
substrLength = decPos == -1 ? numS.length : 1 + decPos + digits,
trimmedResult = numS.substr(0, substrLength),
finalResult = isNaN(trimmedResult) ? 0 : trimmedResult;
return parseFloat(finalResult);
}
// here's the "final" answers with the truncation
let trunc1st = truncateDecimals(firstTargetCalc, 4)
let trunc2nd = truncateDecimals(_2ndTargetCalc, 4)
let trunc3rd = truncateDecimals(thirdTargetCalc, 4)
// here's what I want to display to the end user as the calculated uptime for each target
// alert('firsttarget uptime: ' + trunc1st + '%\n2ndtarget uptime: ' + trunc2nd + '%\nthirdtarget uptime: ' + trunc3rd + '%');
// this will eventually be run within the function to set the iFrame URL
// need to wait for the iFrame to load to get data for calculations
// for now we will present a button...
function showTableData() {
const targetTable = document.getElementById('jstable'); // where to draw the new table
const sourceTable = document.querySelector(".table"); // set kibana as
const innerText = sourceTable.innerText;
const ups = innerText.match(/(\w*(target))\s*(UP)\s*[\d,]*\d(?! )/g);
const downs = innerText.match(/(\w*(target))\s*(DOWN)\s*[\d,]*\d(?! )/g);
let innerHTML = "";
for (let i = 0; i < ups.length; i++) {
const up = ups[i];
const down = downs[i];
const target = up.match(/(\w*(target))/)[0];
const upCount = parseInt(up.match(/[\d,]*\d$/)[0].replace(/,/g, ""));
const downCount = parseInt(down.match(/[\d,]*\d$/)[0].replace(/,/g, ""));
const percentage = (upCount / (upCount + downCount) * 100).toFixed(3)
innerHTML += `${target} uptime: ${percentage}%<br/><br/>`
}
targetTable.innerHTML = innerHTML;
}
/*
function showTableData() {
document.getElementById('jstable').innerHTML = ""; // where to draw the new table
let sourceTable = document.querySelector(".table"); // set "source" table
for (var i = 0, row; row = sourceTable.rows[i]; i++) {
//iterate through rows
//rows would be accessed using the "row" variable assigned in the for loop
for (var j = 0, col; col = row.cells[j]; j++) {
//iterate through columns
//columns would be accessed using the "col" variable assigned in the for loop
}
}
}
/*calc.prototype.toFixedDown = function(digits) {
var re = new RegExp("(\\d+\\.\\d{" + digits + "})(\\d)"),
m = this.toString().match(re);
return m ? parseFloat(m[1]) : this.valueOf();
};*/
/*
// rounding function
function roundTo(n, digits) {
var negative = false;
if (digits === undefined) {
digits = 0;
}
if( n < 0) {
negative = true;
n = n * -1;
}
var multiplicator = Math.pow(10, digits);
n = parseFloat((n * multiplicator).toFixed(11));
n = (Math.round(n) / multiplicator).toFixed(2);
if( negative ) {
n = (n * -1).toFixed(2);
}
return n;
}
// set the vars
/*let uptimeCells = document.querySelectorAll("td");
for (let i = 0; i < uptimeCells.length; i+=3) {
let uptimeTarget = uptimeCells[i].firstChild.data;
let uptimeFilter = uptimeCells[i + 1].firstChild.data;
let uptimeCount = uptimeCells[i + 2].firstChild.data;
console.log(uptimeTarget, uptimeFilter, uptimeCount);
}
// if () {
// }
return `<p>${this.targetName} ${this.calculatedUptime}</p>`;*/
<body>
<div class="rebuild-table">
<p><input type="button" id="bt" value="Show Rebuilt Table" onclick="showTableData()" /></p>
<p id="jstable"></p>
<h1>
Expected Results
</h1>
<div id=results>
<p>
firsttarget uptime: 99.998%
<!--(100-((42/2218563)*100))-->
</p>
<p>
2ndtarget uptime: 99.999%
<!--(100-((3/239384)*100)) rounded up from 99.9987..-->
</p>
<p>
thirdtarget uptime: 100.000%
<!--(100-((0/8340)*100))-->
</p>
</div>
</div>
<div>
<h1>
Data
</h1>
<!--THE TABLE BELOW IS PRESENTED WITHIN AN IFRAME BUT FOR THE JSFIDDLEWE WILL COMMENT OUT THE IFRAME ELEMENT
<iframe id="iframeURL">-->
<table class="table table-condensed">
<thead>
<tr>
<!-- ngRepeat: col in ::columns -->
<th ng-repeat="col in ::columns" ng-click="paginatedTable.sortColumn($index)" class="">
<span ng-bind="::col.title" class="ng-binding">targets</span>
<!-- ngIf: col.info -->
<!-- ngIf: col.sortable !== false --><i ng-if="col.sortable !== false" class="fa ng-scope fa-sort" ng-class="{
'fa-sort-asc': paginatedTable.sort.columnIndex === $index && paginatedTable.sort.direction === 'asc',
'fa-sort-desc': paginatedTable.sort.columnIndex === $index && paginatedTable.sort.direction === 'desc',
'fa-sort': paginatedTable.sort.columnIndex !== $index || paginatedTable.sort.direction === null
}">
</i>
<!-- end ngIf: col.sortable !== false -->
<!-- ngIf: col.filterable --><i aria-label="Click on a cell to filter" ng-if="col.filterable" class="fa fa-search ng-scope" ng-click="$event.stopPropagation()" tooltip="Click on a cell to filter"></i>
<!-- end ngIf: col.filterable -->
</th>
<!-- end ngRepeat: col in ::columns -->
<th ng-repeat="col in ::columns" ng-click="paginatedTable.sortColumn($index)" class="">
<span ng-bind="::col.title" class="ng-binding">filters</span>
<!-- ngIf: col.info -->
<!-- ngIf: col.sortable !== false --><i ng-if="col.sortable !== false" class="fa ng-scope fa-sort" ng-class="{
'fa-sort-asc': paginatedTable.sort.columnIndex === $index && paginatedTable.sort.direction === 'asc',
'fa-sort-desc': paginatedTable.sort.columnIndex === $index && paginatedTable.sort.direction === 'desc',
'fa-sort': paginatedTable.sort.columnIndex !== $index || paginatedTable.sort.direction === null
}">
</i>
<!-- end ngIf: col.sortable !== false -->
<!-- ngIf: col.filterable -->
</th>
<!-- end ngRepeat: col in ::columns -->
<th ng-repeat="col in ::columns" ng-click="paginatedTable.sortColumn($index)" class="visualize-table-right">
<span ng-bind="::col.title" class="ng-binding">Count</span>
<!-- ngIf: col.info -->
<!-- ngIf: col.sortable !== false --><i ng-if="col.sortable !== false" class="fa ng-scope fa-sort" ng-class="{
'fa-sort-asc': paginatedTable.sort.columnIndex === $index && paginatedTable.sort.direction === 'asc',
'fa-sort-desc': paginatedTable.sort.columnIndex === $index && paginatedTable.sort.direction === 'desc',
'fa-sort': paginatedTable.sort.columnIndex !== $index || paginatedTable.sort.direction === null
}">
</i>
<!-- end ngIf: col.sortable !== false -->
<!-- ngIf: col.filterable -->
</th>
<!-- end ngRepeat: col in ::columns -->
</tr>
</thead>
<tbody kbn-rows="page" kbn-rows-min="perPage">
<tr>
<td class="cell-hover ng-scope" ng-click="clickHandler($event)">firsttarget</td>
<td>UP</td>
<td class="numeric-value">2,218,563</td>
</tr>
<tr>
<td class="cell-hover ng-scope" ng-click="clickHandler($event)">firsttarget</td>
<td>DOWN</td>
<td class="numeric-value">42</td>
</tr>
<tr>
<td class="cell-hover ng-scope" ng-click="clickHandler($event)">2ndtarget</td>
<td>UP</td>
<td class="numeric-value">239,384</td>
</tr>
<tr>
<td class="cell-hover ng-scope" ng-click="clickHandler($event)">2ndtarget</td>
<td>DOWN</td>
<td class="numeric-value">3</td>
</tr>
<tr>
<td class="cell-hover ng-scope" ng-click="clickHandler($event)">thirdtarget</td>
<td>UP</td>
<td class="numeric-value">8,340</td>
</tr>
<tr>
<td class="cell-hover ng-scope" ng-click="clickHandler($event)">thirdtarget</td>
<td>DOWN</td>
<td class="numeric-value">0</td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
</tr>
</tbody>
</table>
</div>
<!--</iframe>-->
<p>
Notes: some targets begin with numbers. The final implementation will have various numbers of targets to calculate. Cannot change the table itself, other than the names of the UP and DOWN filters (e.g., cannot add id="" to any table elements because it's
generated externally). The entire 'thead' element is not important to this project.</p>
</body>
Beginner coder here.
I am currently developing a website for calculating various equations, but I need help with user input.
On the HTML, I currently wrote up the following code.
<section>
<!--- Celsius, Fahrenheit, Kelvin -->
<table>
<tr>
<td>°C</td>
<td>°F</td>
<td>°K</td>
</tr>
<tr>
<td> <input type="number" id="celsius"/> </td>
<td id="fahr1"></td>
<td id="kelv1"></td>
</tr>
<tr>
<td>later</td>
<td> <input type="number" id="fahrenheit"/> </td>
<td>later</td>
</tr>
</table>
</section>
How would I go about changing the second and third row to change along with what the user inputs without having them have to press a submit button? How would I access the input that the user has given me in order to manipulate it into an output in the corresponding spot in the table?
This is what you're after I suspect :)
HTML
<section>
<!--- Celsius, Fahrenheit, Kelvin -->
<table>
<tr>
<td>°C</td>
<td>°F</td>
<td>°K</td>
</tr>
<tr>
<td> <input type="number" id="celsius"/> </td>
<td id="fahr1"></td>
<td id="kelv1"></td>
</tr>
<tr>
<td id="celc2">-</td>
<td> <input type="number" id="fahrenheit" /> </td>
<td id="kelv2">-</td>
</tr>
</table>
</section>
JQuery
//Hook into an event where if an input of type number changes
$('input[type=number]').change(function() {
//If the name of the input that has changed is celsius
if($(this).attr('id') == 'celsius'){
//Call a function to get the current value using $(this).val()
//Update the text inside the relevant td's by calling a function
$('#fahr1').text(celsiusToFahrenheit($(this).val()));
$('#kelv1').text(celsiusToKelvin($(this).val()));
}
//If the name of the input that has changed is fahrenheit
else if($(this).attr('id') == 'fahrenheit'){
//Call a function to get the current value using $(this).val()
//Update the text inside the relevant td's by calling a function
$('#celc2').text(fahrenheitToCelsius($(this).val()));
$('#kelv2').text(fahrenheitToKelvin($(this).val()));
}
});
function celsiusToFahrenheit(c) {
var f = parseInt(c);
f = f * (9/5) + 32;
return f;
}
function celsiusToKelvin(c) {
var k = parseInt(c);
k = k + 273.15;
return k;
}
function fahrenheitToCelsius(f) {
var c = parseInt(f);
c = (c - 32) * (5/9);
return c;
}
function fahrenheitToKelvin(f) {
var k = parseInt(f);
k = (k + 459.67) * (5/9);
return k;
}
Please note! You should put this in a <script></script> section in the top of your HTML. An example can be seen here: W3 Schools Script example
Similarly don't forget to reference JQuery in your <head></head> section. An example can be seen here: W3 Schools Reference JQuery
See it working live here: https://jsfiddle.net/cwr1hm9v/1/
EDIT
As per request, here is the Javascript equivalent
HTML
<section>
<!--- Celsius, Fahrenheit, Kelvin -->
<table>
<tr>
<td>°C</td>
<td>°F</td>
<td>°K</td>
</tr>
<tr>
<td> <input type="number" id="celsius"/> </td>
<td id="fahr1"></td>
<td id="kelv1"></td>
</tr>
<tr>
<td id="celc2">-</td>
<td> <input type="number" id="fahrenheit" /> </td>
<td id="kelv2">-</td>
</tr>
</table>
</section>
JavaScript
const celsius = document.getElementById('celsius');
const fahrenheit = document.getElementById('fahrenheit');
celsius.addEventListener('change', (event) => {
convertFromCelsius();
});
fahrenheit.addEventListener('change', (event) => {
convertFromFahrenheit();
});
function convertFromCelsius() {
var fahr1 = document.getElementById("fahr1");
var kelv1 = document.getElementById("kelv1");
fahr1.textContent = parseInt(celsius.value) * (9/5) + 32;
kelv1.textContent = parseInt(celsius.value) + 273.15;
}
function convertFromFahrenheit() {
var celc2 = document.getElementById("celc2");
var kelv2 = document.getElementById("kelv2");
celc2.textContent = (parseInt(fahrenheit.value) - 32) * (5/9);
kelv2.textContent = (parseInt(fahrenheit.value) + 459.67) * (5/9);
}
See it working live here: https://jsfiddle.net/0Luvq4nx/1/
Please mark this as accepted if this solves your issue.
I have a Javascript that's running on an html form that performs some calculations based on the values the user has entered and then enters the results into some other fields. This is all working well. Here's what the HTML looks like:
<table width="100%" border="0" cellspacing="0" cellpadding="10" class="border" id="calcs">
<tr class="d_green">
<td colspan="4">LAST YEAR</td>
</tr>
<tr class="l_white">
<td width="53%">number of instances in the last year </td>
<td width="13%" align="right"><input name="textfield1" type="text" class="input_b_r" id="textfield1" value="0" /></td>
<td width="24%"> </td>
<td width="10%"> </td>
</tr>
<tr class="l_green">
<td>average number of moderate-risk activity per week in the last year</td>
<td align="right"><input name="textfield2" type="text" class="input_b_r" id="textfield2" value=""/></td>
<td> </td>
<td> </td>
</tr>
<tr class="l_white">
<td>average number of hours of high-risk activity per week in the last year</td>
<td align="right"><input name="textfield3" type="text" class="input_b_r" id="textfield3" value=""/></td>
<td> </td>
<td> </td>
</tr>
<tr class="d_green">
<td colspan="4">NEXT YEAR</td>
</tr>
<tr class="l_white">
<td>expected average number of hours of moderate-risk activity per week next year</td>
<td align="right"><input name="textfield4" type="text" class="input_b_r" id="textfield4" value=""/></td>
<td> </td>
<td> </td>
</tr>
<tr class="l_green">
<td>expected average number of hours of high-risk activity per week next year</td>
<td align="right"><input name="textfield5" type="text" class="input_b_r" id="textfield5" value=""/></td>
<td> </td>
<td> </td>
</tr>
<tr class="l_white">
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr class="l_green">
<td> </td>
<td colspan="2" style="padding-left:31px;"><input type="submit" name="button" id="Calculate" value="Calculate" class="button_calculate" /></td>
<td> </td>
</tr>
<tr class="l_white">
<td> </td>
<td colspan="2" style="padding-left:105px;">predicted number of instances next year</td>
<td><input name="textfield6" type="text" class="input_b" id="textfield6" /></td>
</tr>
<tr class="l_green">
<td> </td>
<td colspan="2" style="padding-left:105px;">extra instances next year</td>
<td><input name="textfield7" type="text" class="input_b" id="textfield7" /></td>
</tr>
</table>
and here's the Javascript:
$(document).ready(function(){
$('#Calculate').click(function(){
var IRRC2 = 1.35;
var IRRC3 = 2.75;
var Npast = Number($("#textfield1").val());
var t2hrswk = Number($("#textfield2").val());
var t3hrswk = Number($("#textfield3").val());
var t2nexthrswk = Number($("#textfield4").val());
var t3nexthrswk = Number($("#textfield5").val());
var t2epyr = t2hrswk * 6 * 52;
var t3epyr = t3hrswk * 6 * 52;
var t01epyr = 52 * 7 * 24 * 6 - t2epyr - t3epyr;
var epochBaseInstances = Npast / (t01epyr + IRRC2 * t2epyr + IRRC3 * t3epyr);
var baselineCoefficient = Math.log(epochBaseInstances);
var t2nextepyr = t2nexthrswk * 6 * 52;
var t3nextepyr = t3nexthrswk * 6 * 52;
var t01nextepyr = 52 * 7 * 24 * 6 - t2nextepyr - t3nextepyr;
var predictedInstances = Math.exp(baselineCoefficient) * (t01nextepyr + IRRC2 * t2nextepyr + IRRC3 * t3nextepyr);
var roundedPredictedInstances = Math.round( predictedInstances * 10 ) / 10;
var lastYearTotal = Number($("#textfield1").val());
var extraInstancesRounded = Math.round( (roundedPredictedInstances - lastYearTotal) * 10 ) / 10;
$('#textfield6').val(roundedPredictedInstances);
$('#textfield7').val(extraInstancesRounded);
});
});
I know need to modify this so that if the value of the first form field (textfield1) is 0 when the user clicks the Calculate button it detects this and then exits, displaying an error message (e.g. "the value for Last Year cannot be zero").
Everything I've tried so far has broken the Javascript - appreciate any assistance with how to proceed.
Try this code, just after the Npast decleration:
var Npast = Number($("#textfield1").val());
if (Npast === 0) {
alert("the value for Last Year cannot be zero");
return;
}
Add this conditional statement toward the bottom:
if ( !Npast ) {
alert('Error!');
return false;
}
Here's a working demo of the fix: http://jsfiddle.net/38PGy/
Try this
var last_year = $("#textfield1").val();
if (last_year == 0) {
alert("The value for Last Year cannot be zero, please enter valid number");
return;
}
you could try adding validations for your textfields
here is a sample:
$(document).ready(function(){
$('#Calculate').on('click',function(){
if (!validateTextField()){
alert('no zeroes');
} else {
alert('zeroes');
}
});
});
function validteTextField(){
//$('input[id^=textfield]') --> selects all input with id having a prefix textfield
$('input[id^=textfield]').css('background-color','white');
var flg = false;
$('input[id^=textfield]').each(function(){
if ($(this).val() === 0 || $(this).val().length === 0){
$(this).css('background-color','pink');
flg = true;
}
});
return flg;
}
jsFiddle demo