so I'm very new to Javascript ;I'm trying so hard to learn it but it's difficult for me especially because I'm coming from an OOP standpoint (C++/Java) . Anyway ,I'm building a calculator and my question is I'm trying to set a single global variable to a long reference . Here's what i mean .
Here is what i have tried in order to make a single global variable to work instead of writing ( document.form.textview.value ) every single time.
1. var number = document.form.textview.value;
2. var number = newFunction();
function newFunction() {
return document.form.textview.value;
}
3. i also tried using document.getelementbyID and queryselector but none of them worked.
what i have and is working :-
function insert(num) { // inserts a number into the textbox or form
document.form.textview.value = document.form.textview.value + num;
}
function equal() { // calculates numbers
var exp = document.form.textview.value;
if (exp) {
document.form.textview.value = eval(exp);
}
}
function Squareroot() {
document.form.textview.value =
eval(Math.sqrt(document.form.textview.value));
}
as you can see i have to write 'document.form.textview.value' every single time in order to get it to work instead i want a single global variable to do that for me.
This is what i want :-
var number = document.form.textview.value;
function insert(num) {
return number+num;
}
function equal() {
if (number) {
eval(number);
}
}
function Squareroot() {
eval(Math.sqrt(number));
}
html :-
<form name="form">
<input class="textview" name="textview">
<table>
<caption>
<h1>↻</h1>
</caption>
<tr>
<td onclick="Clearview()">C</td>
<td>←</td>
<td onclick="Takepercentage('')">%</td>
<td onclick="insert('/')">/</td>
</tr>
<tr>
<td onclick="insert('.')">.</td>
<td onclick="exponents()">x<sup>2</sup></td>
<td onclick="Squareroot()">√</td>
<td onclick="insert('*')">*</td>
</tr>
<tr>
<td onclick="insert(6)">6</td>
<td onclick="insert(7)">7</td>
<td onclick="insert(8)">8</td>
<td onclick="insert('-')">-</td>
</tr>
<tr>
<td onclick="insert(3)">3</td>
<td onclick="insert(4)">4</td>
<td onclick="insert(5)">5</td>
<td onclick="insert('+')">+</td>
</tr>
<tr>
<td onclick="insert(0)">0</td>
<td onclick="insert(1)">1</td>
<td onclick="insert(2)">2</td>
<td onclick="equal()">=</td>
</tr>
</table>
</form>
The DOM is very much like any other OOP system you might be familiar with. You can very easily make a reference to document.form.textview, acting as an object you can change by accessing or mutating its value property. But if you create a reference to that property, getting or setting it simply changes the reference, and not the underlying object.
Think of it as similar to
var r = new Rectangle(5, 3);
r.area() //=> 15
r.width //=> 5
r.width + 7 //=> 12, but doesn't change the rectangle.
So by using number.value where you were hoping to use number, and setting number to document.form.textview, you should be able to get things to work:
const number = document.form.textview;
function insert(num) {
return number.value += '' + num;
}
function equal() {
if (number.value) {
eval (`number.value = ${number.value}`);
}
}
function Squareroot() {
number.value = Math.sqrt(number.value);
}
<form name="form">
<input class="textview" name="textview">
<table>
<caption>
<h1>↻</h1>
</caption>
<tr>
<td onclick="Clearview()">C</td>
<td>←</td>
<td onclick="Takepercentage('')">%</td>
<td onclick="insert('/')">/</td>
</tr>
<tr>
<td onclick="insert('.')">.</td>
<td onclick="exponents()">x<sup>2</sup></td>
<td onclick="Squareroot()">√</td>
<td onclick="insert('*')">*</td>
</tr>
<tr>
<td onclick="insert(6)">6</td>
<td onclick="insert(7)">7</td>
<td onclick="insert(8)">8</td>
<td onclick="insert('-')">-</td>
</tr>
<tr>
<td onclick="insert(3)">3</td>
<td onclick="insert(4)">4</td>
<td onclick="insert(5)">5</td>
<td onclick="insert('+')">+</td>
</tr>
<tr>
<td onclick="insert(0)">0</td>
<td onclick="insert(1)">1</td>
<td onclick="insert(2)">2</td>
<td onclick="equal()">=</td>
</tr>
</table>
</form>
You can use the onkeyup event listener to update the global variable. That way any time you want to reference globalVal you'll have the right value. This is also called one way binding. That is, any time you change the input value, the global variable will get updated, but not the other way around. In two way binding, a change made to the global variable or the input would result in both of them being updated.
var globalVal = "";
function update(val) {
globalVal = val;
console.log(globalVal);
}
<input id="textview" onkeyup="update(this.value)" class="textview" name="textview">
Related
In this reactjs app I have a table with the following body:
<tbody>
{results.map(result =>
<tr key={result.metric} onClick={this.handleClick}>
<td className="inpt-td">{result.t00}</td>
<td className="inpt-td">{result.t01}</td>
<td className="inpt-td">{result.t02}</td>
<td className="inpt-td">{result.t03}</td>
<td className="inpt-td">{result.t04}</td>
<td className="inpt-td">{result.t05}</td>
<td className="inpt-td">{result.t06}</td>
<td className="inpt-td">{result.t07}</td>
<td className="inpt-td">{result.t08}</td>
<td className="inpt-td">{result.t09}</td>
<td className="inpt-td">{result.t10}</td>
<td className="inpt-td">{result.t11}</td>
<td className="inpt-td">{result.t12}</td>
<td className="inpt-td">{result.t13}</td>
<td className="inpt-td">{result.t14}</td>
<td className="inpt-td">{result.t15}</td>
<td className="inpt-td">{result.t16}</td>
<td className="inpt-td">{result.t17}</td>
<td className="inpt-td">{result.t18}</td>
<td className="inpt-td">{result.t19}</td>
<td className="inpt-td">{result.t20}</td>
<td className="inpt-td">{result.t21}</td>
<td className="inpt-td">{result.t22}</td>
<td className="inpt-td">{result.t23}</td>
</tr>
)}
</tbody>
The header does not exist for this particular table, but I was wondering if there was a way to obtain the column name of a clicked cell. So for example if you clicked on the second cell in a given row, it would return "t01", which is the column name.
My searches online did not provide an efficient way of doing this. Is there a method to retrieve this info?
In your handleClick you can get access to the event.target property, which is a cell.
After that you can do:
var child = event.target;
var parent = child.parentNode;
// equivalent of parent.children.indexOf(child)
var index = Array.prototype.indexOf.call(parent.children, child);
var value = 't' + index // this will be value what you are looking for
If you need information how to use event.target - here is an example.
I have a table with following rows and cells:
<table id='table1'>
<tr id='row1'>
<th>index</th>
<th>Product</th>
<th>Description</th>
</tr>
<tr id='row2' name='row'>
<td name='index'>1</td>
<td name='product'>Apples</td>
<td name='description'>fruits</td>
</tr>
<tr id='row3' name='row'>
<td name='index'>2</td>
<td name='product'>Bananas</td>
<td name='description'>fruits</td>
</tr>
<tr id='row4' name='row'>
<td name='index'>3</td>
<td name='product'>Carrots</td>
<td name='description'>vegetables</td>
</tr>
<tr id='row5' name='row'>
<td name='index'></td>
<td name='product'></td>
<td name='description'></td>
</tr>
</table>
I need to select the value for the last td with name='index' which is not null. Anyone has any idea how can this be done.
Use the following selector :
$('td[name=index]:not(:empty):last')
For purely educational purposes, here is a non jQuery version:
function getLastNonEmptyCell(tableSelector) {
//Find parent table by selector
var table = document.querySelector(tableSelector)
//Return null if we can't find the table
if(!table){
return null;
}
var cells = table.querySelectorAll("td")
var lastNonEmptyCell = null;
//Iterate each cell in the table
//We can just overwrite lastNonEmptyCell since it's a synchronous operation and the return value will be the lowest item in the DOM
cells.forEach(function(cell) {
//!! is used so it's so if it is not null, undefined, "", 0, false
//This could be changed so it's just cell.innerText.trim() !== ""
if (!!cell.innerText) {
lastNonEmptyCell = cell;
}
})
return lastNonEmptyCell;
}
var cell = getLastNonEmptyCell("#table1")
Edit
As #squint suggested this can be done much more succintly:
function lastNonEmptyCell(tableSelector) {
//Since we want the last cell that has content, we get the last-child where it's not empty. This returns the last row.
var row = document.querySelectorAll(tableSelector + " td:not(:empty):last-child")
//Just grabbing the last cell using the index
return row[row.length - 1]
}
I wasn't quite sure how to word this in the title, so thank you for clicking to on this.
So now to my problem:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<style>
.block {
background-color: black;
}
</style>
<table border='1px'>
<tr>
<td id='11'></td>
<td id='12'></td>
<td id='13'></td>
<td id='14'></td>
<td id='15'></td>
</tr>
<tr>
<td id='21'></td>
<td id='22'></td>
<td id='23'></td>
<td id='24'></td>
<td id='25'></td>
</tr>
<tr>
<td id='31'></td>
<td id='32'></td>
<td id='33' class="block"></td>
<td id='34'></td>
<td id='35'></td>
</tr>
<tr>
<td id='41'></td>
<td id='42'></td>
<td id='43'></td>
<td id='44'></td>
<td id='45'></td>
</tr>
<tr>
<td id='51'></td>
<td id='52'></td>
<td id='53'></td>
<td id='54'></td>
<td id='55'></td>
</tr>
</table>
<button onclick="blockUp()">Up</button>
<button onclick="blockDown()">Down</button>
<button onclick="blockLeft()">Left</button>
<button onclick="blockRight()">Right</button>
<script>
var blockUp = function() {
var oldBlock = document.getElementsByClassName("block")[0].id;
var newBlock = Math.floor(oldBlock + 1);
document.getElementById(newBlock).classList.add("block");
document.getElementById(oldBlock).classList.remove("block");
}
</script>
</body>
</html>
This code is not complete, as I want to fix this problem first.
I want to use Math.floor to get a certain ID (thus, IDs as numbers), and manipulate them. More specifically, I want to find the ID of the cell that currently has the .block class, find the ID of the cell above that using Math.floor(oldBlock + 1), remove the class from the original cell, and add the class to the new cell. I used variables so that the function would always be able to run, rather than making a million if/else if/else statements.
Unfortunately, this doesn't work with my current code. How would I be able to do this?
Any help is appreciated!
You have to make sure that "oldBlock" contains a number before trying to do math with it (like adding 1):
var oldBlock = +document.getElementsByClassName("block")[0].id;
That's one way of doing it. You could also use parseInt():
var oldBlock = parseInt(document.getElementsByClassName("block")[0].id, 10);
The value of the "id" property will be a string, so if you involve that in an addition operation JavaScript will treat it as string concatenation. By forcing it to be a number first, you'll get the effect you want.
I have a variable html that stores HTML:
<tr class="odd">
<td class="charge1">0</td>
<td class="nc1">0</td>
</tr>
<tr class="even">
<td class="charge2">0</td>
<td class="nc2">0</td>
</tr>
<tr class="odd">
<td class="charge3">250</td>
<td class="nc3">0</td>
</tr>
Basically I need to add the values for the td with the class starting with charge to the values for the td with the class starting with nc and replace the value in the td with class starting with nc with the sum. The values in both td's in each row could change, so the code needs to be dynamic. So for this example, the resulting HMTL in the variable should be:
<tr class="odd">
<td class="charge1">0</td>
<td class="nc1">0</td>
</tr>
<tr class="even">
<td class="charge2">0</td>
<td class="nc2">0</td>
</tr>
<tr class="odd">
<td class="charge3">250</td>
<td class="nc3">250</td>
</tr>
In this example, the only row that actually changes is the third row. The td starting with class nc now shows 250 instead of the original 0.
I have to use the variable html later in the code with the updated td information if it did change.
This is the code that I have, but it's not working:
var html = $('#chargetable').html();
console.log(html);
$('[class*=nc]', html).each(function(){
var ncamount = $(this).html();
var chargeamount = $(this).parents('tr').find('[class*=charge]').html();
var totalnc = parseFloat(chargeamount) + parseFloat(ncamount);
$(this).html(totalnc);
console.log(chargeamount + ' ' + ncamount + ' ' + totalnc);
});
console.log(html);
This is the results of the console's log:
<tr class="odd">
<td class="charge1">0</td>
<td class="nc1">0</td>
</tr>
<tr class="even">
<td class="charge2">0</td>
<td class="nc2">0</td>
</tr>
<tr class="odd">
<td class="charge3">250</td>
<td class="nc3">0</td>
</tr>
0 0 0
0 0 0
250 0 250
<tr class="odd">
<td class="charge1">0</td>
<td class="nc1">0</td>
</tr>
<tr class="even">
<td class="charge2">0</td>
<td class="nc2">0</td>
</tr>
<tr class="odd">
<td class="charge3">250</td>
<td class="nc3">0</td>
</tr>
The html variable isn't being updated, but I can't for the life of me figure out how to get it to update, short of splitting the variable, replacing the td with class nc, and recreating the html variable on each iteration. I'm thinking there's got to be a better way to do this.
Any help is very much appreciated.
The problem with you code is that you cannot use html variable in this line
$('[class*=nc]', html)
the second parameter is used to define scope in which jQuery searches for the selector.
So, like document,parent.document(if its iframe etc..)
If you need the original dom you can use jQuery .clone() to store the original dom like this
//if you require the original code for later clone it
var htmlclone = $('#chargetable').clone().html();
console.log(htmlclone);
$('#chargetable [class*=nc]').each(function(){
var ncamount = $(this).html();
var chargeamount = $(this).parents('tr').find('[class*=charge]').html();
var totalnc = parseFloat(chargeamount) + parseFloat(ncamount);
$(this).html(totalnc);
console.log(chargeamount + ' ' + ncamount + ' ' + totalnc);
});
console.log(htmlclone);
Here is a fiddle http://jsfiddle.net/z4n7kjcf/
$(function () {
var $chargeTable = $("#chargetable");
var $chargeTableCloned = $chargeTable.clone();
var $chargeTableRows = $("tr", $chargeTableCloned);
$.each($chargeTableRows, function(i, $tr){
var $tdCharge = $("td[class^='charge']", $tr);
var $tdNc = $("td[class^='nc']", $tr);
var charge = parseInt($tdCharge.text(), 10);
var nc = parseInt($tdNc.text(), 10);
$tdNc.text(charge + nc);
});
$chargeTable.after($chargeTableCloned);
});
Example
I have table as follows :
<table>
<thead>
<th>PRODUCT</th>
<th>QUANTITY</th>
<th>AREA</th>
<th>PRICE</th>
<th>TOTAL</th>
<tr>
<td id="name">SWEETS</td>
<td id="qty">10</td>
<td id="area">250</td>
<td id="price">16.50</td>
<td id="total">160.50</td>
</tr>
<tr>
<td id="name"">DRY FOODS</td>
<td id="qty">5</td>
<td id="area">100</td>
<td id="price">10.25</td>
<td id="total">51.25</td>
</tr>
<tr>
<td id="name">FRESH</td>
<td id="qty">20</td>
<td id="area">250</td>
<td id="price">5</td>
<td id="total">100</td>
</tr>
<tr>
<td id="name">MEAT</td>
<td id="qty">10</td>
<td id="area">250</td>
<td id="price">15</td>
<td id="total">150</td>
</tr>
<tr>
<td id="name">FROZEN</td>
<td id="qty">20</td>
<td id="area">300</td>
<td id="price">10</td>
<td id="total">200</td>
</tr>
</table>
So, I want to make an array like {area:total} then grouping array values based on area and sum area values.
Like :
AREA 250 : 410.5
AREA 100 : 51.25
AREA 300 : 200
I tried as follow which I got it array but I don't know how can I grouping the areas ( I used setInterval function because employees can remove or change the area values)
setInterval(function() {
var $row = $(this).closest("tr");
var sasData = [];
$row.each(function(i) {
var sasValue = parseFloat($row.find("#area").val());
var totValue = parseFloat($row.find("#total").val());
sasData.push({sas:sasValue, tot:totValue});
console.log(sasData);
});
function compressedArray(original) {
var compressed = [];
};
}, 1500)
Could you please show me the way how can we handle this issue?
This JSFiddle should solve your problem. I've also fixed your missing thead, your double quote in the DRY FOODS td, and changes id's to classes:
http://jsfiddle.net/Q9nrf/1/
var areas = {};
$("tr").each(function() {
var area = $(this).find("td.area").text();
if (area != "") {
var total = parseFloat($(this).find("td.total").text());
if (!areas.hasOwnProperty(area)) {
areas[area] = 0;
}
areas[area] += total;
}
});
console.log(areas);
You will need to change the id values to some other attribute, say class.
Loop over the rows (use the tbody element to skip the header) and collect values from the elements with the classes you're after. You will need to use an array to store them, as you can't order the properties of an object and each property must have a unique name.
id should be unique. so change <td id="area">250</td> to <td class="area">250</td>
then just call:
o = {};
$("td.area").each(function(){
key = o[$(this).text()];
if (!key) key = 0;
key += parseFloat( $(this).closest("tr").find(".total").text());
});
then you have on object contains key-value [key=area code, value=total]