How to put values from array in td elements - javascript

I'm very new to programming, especially to JavaScript and I encounter some problem with putting some values from an array to td elements.
I want to grab the nodeValue from td Elements performe some calculation on it and put it back in some other td-elements. The first part works fine, but I didn't get it right to put the values back from the array in other td elements.
I always get the warning in the console.:
TypeError:
document.getElementById(...).getElementsByTagName(...).item(...) is
null
What do I wrong? The relevant code:
for (i = 0; i <= getPreis.length; i++) {
priceNumber += 1;
newElement += 1;
}
function myFunction() {
// create array element
var oldPrice = [];
// get all td elements in id "originalPrice"
var getPreis = document.getElementById('originalPrice').getElementsByTagName('td');
// determine number of td elements
for (i = 0; i < getPreis.length; i++) {
oldPrice.push(getPreis[i].childNodes[0].nodeValue);
}
// get all td elements in id "listNewPrice"
var putPreis = document.getElementById('listNewPrice').getElementsByTagName('td');
// set index of item
var newElement = 0;
// set index for array
var priceNumber = 0;
// perform operation on array element
var newPrice = oldPrice[priceNumber] * 0.94;
/* it got problems with this for loop
here i want to loop through all td elements in tr "listNewPrice" and put the values from the array in there */
for (i = 0; i <= getPreis.length; i++) {
priceNumber += 1;
newElement += 1;
}
document.getElementById("listNewPrice").getElementsByTagName('td').item(newElement).innerHTML = newPrice;
}
<!DOCTYPE html>
<html>
<body>
<table>
<tbody>
<tr id="originalPrice">
<td>22.50</td>
<td>45.00</td>
<td>75.00</td>
</tr>
<tr id="listNewPrice">
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<button onclick="myFunction()">Click me</button>
</body>
</html>

You need to move the calculation and assignment of the result to the td element inside your loop as you are using incrementing index values that get calculated inside the for loop.
for (i = 0; i < getPreis.length; i++) {
var newPrice = oldPrice[priceNumber] * 0.94;
document.getElementById("listNewPrice").getElementsByTagName('td').item(newElement).innerHTML = newPrice;
priceNumber += 1;
newElement += 1;
}
In your example newElement === 2 after the for loop then you try and get the item at index 2 of the array of td elements which doesn't exist. Hence the error
document.getElementById(...).getElementsByTagName(...).item(...) is null
Example JSFiddle

Since you are going to be reading numeric data out of the original table and performing calculations on it, you'll need to ensure that you are properly parsing the values as numbers instead of strings.
You can do this by using the parseFloat() function when reading in your values :
for (i = 0; i < getPreis.length; i++) {
// Read in the actual values (so they will be usable in calculations)
oldPrice.push(parseFloat(getPreis[i].childNodes[0].nodeValue));
}
Then when updating your values, just perform the operation backwards (i.e. iterate through your loop and set the values of each node) :
// determine number of td elements
for (i = 0; i < getPreis.length; i++) {
putPreis[i].innerHTML = oldPrice[i] * 0.94;
}
Both of these changes will allow you to greatly simplify your existing code :
function myFunction() {
// create array element
var oldPrice = [];
// get all td elements in id "originalPrice"
var getPreis = document.getElementById('originalPrice').getElementsByTagName('td');
// determine number of td elements
for (i = 0; i < getPreis.length; i++) {
oldPrice.push(parseFloat(getPreis[i].childNodes[0].nodeValue));
}
// get all td elements in id "listNewPrice"
var putPreis = document.getElementById('listNewPrice').getElementsByTagName('td');
// update your values
for (i = 0; i < getPreis.length; i++) {
putPreis[i].innerHTML = oldPrice[i] * 0.94;
}
}
Example
You can see a working example of this here and demonstrated below :

Related

Lottery Javascript cant clear the array

So I'm making a simulation of the lottery. I generate 6 numbers between 0 and 40 and show them in the html id 'generated'. My problem is that if I click a second time on 'generate' (in my html page), the previous generated numbers are still a part of the array and still show up. Does anybody know how to clear the array when pushed on the button multiple times?
This is my Javascript code:
'use strict';
function generatenumbers(){
let number = [];
let i;
i=0;
for(i= 0; i <= 5; i++){
number[i] = Math.floor(Math.random()*40);
}
i = 0;
for(i=0; i<= number.length - 1; i++){
let node = document.createElement("LI");
let textnode = document.createTextNode(number[i]);
node.appendChild(textnode);
document.getElementById("generated").appendChild(node);
}
}
You are supposed to remove the previously appended children then add new ones.
var list = document.getElementById("generated");
list.removeChild(list.childNodes[0]); // for removing first child only
//for removing all children
var list = document.getElementById("genrated");
while (list.firstChild) {
list.removeChild(list.firstChild);
}
you don't want to clear the array...you want to clear the document.getElementById("generated") element before you call the loop, that way, there will always be 6 LI elements at the end of the function.
document.getElementById("generated").innerHTML = ""; // clear the element
for(i=0; i<= number.length - 1; i++){
let node = document.createElement("LI");
let textnode = document.createTextNode(number[i]);
node.appendChild(textnode);
document.getElementById("generated").appendChild(node);
}

How to remove all children from an element using jQuery?

I have a script that creates a table with specifications given by the user.
The issue is that when the table is printed more than once, it prints below the other table. Turning a 10x10 table into a 10x20 table. (if that makes sense)
In previous assignments I used:
//Clean grid
while(grid.firstChild)
grid.removeChild(grid.firstChild);
to clear the grid, but this assignment is using jQuery and I am not sure how to do it. I've tried:
var divBlock = document.getElementById('my_table');
while (divBlock.firstChild) {
divBlock.removeChild(divBlock.firstChild);
and
$("#my_table").empty();
and
$("#my_table").remove();
and
$('#my_table').remove('table');
but neither seem to work, here is the full code:
// TODO: clear table
var $rows = $("#rows");
var $cols = $("#cols");
var $print_button = $("#print");
var $my_table = $("#my_table");
var $stats = $("#stats");
var arr = [];
var $table_obj = $('<table>'); //Create an element
var $row_obj;
var $col_obj;
var counter = 0;
$print_button.on('click', function() {print_pattern();});
function print_pattern()
{
// Clear table
// var divBlock = document.getElementById('my_table');
// while (divBlock.firstChild) {
// divBlock.removeChild(divBlock.firstChild);
// }
// $("#my_table").empty();
$('#my_table').remove('table');
// Get row and column values
var r = $rows.val(); //Get value of rows
element
var c = $cols.val(); //Get value of cols element
// Create 2-D Array
for (var i = 0; i < r; i++) {
arr[i] = [];
}
// Double for-loop to create table
for (var i = 0; i < r; i++) {
$row_obj = $('<tr>'); // Create row
for (var j = 0; j < c; j++) {
$col_obj = $('<td>'); // Create table cell
var n = Math.floor(Math.random()*10000)%100; //Math methods:
floor and random
$($col_obj).append(n); // Append random number to table cell
$($row_obj).append($col_obj); // Append column to row
$($table_obj).append($row_obj); // Append row to table object
// if random number > 90 -> make background color yellow
if (n > 90) {
$col_obj.css('background-color', 'yellow'); //Change css
counter++; // counter for stats
}
}
$($table_obj).append($row_obj); // Append row to table object
}
$($my_table).append($table_obj); // Append table to div container
// Stats calculation
$stats.html("<b>" + (counter/(r*c)*100).toFixed(2) + "%<b>");
//Change html content
counter = 0; // reset counter
// event function for removing a row when its clicked on
$('tr').on('click', function(){ $(this).fadeOut(500); });
}
So I've tried a number of things, I am not sure if I am just getting the syntax wrong or if I am using the wrong function to clear the div tag.
If anyone can point me in the right direction that would help a lot!
Thank you.
EDIT: I figured out the issue. My original while() block worked fine when I put all the variables inside the function.
First of all, you have to distinguish variables.
A. There is a variable that has to define 1 time, and any changes will
be stored on that.
B. And there is a variable that needs to be reset every function
called.
variable on condition b you need put inside your function so it won't keep last value and make it has double value (last value + new value)
in this case i could say this variable is on condition b:
$table_obj, $row_obj, $col_obj, arr, ...

JQUERY/JavaScript - call to custom math function not returning correctly

I have a function that passes values into another function to perform calculations. I rewrote it from jquery into pure js on account of performance issues existing. The function has multiple for loops and is a bit odd to understand. Basically it starts at a column index (19) and gathers cells starting at the top and once they reach the cell below with the class of subtotal they average the values and return.
Here is my JSFIDDLE
Function that calls the average function:
$(function doIt() {
var el1 = $('#rackPlan1 > thead > tr > th:gt(17):not(.totalRow)');
var x = el1.length;
var starter = 19;
for (i = 0; i < x; i++) {
var divs = $('#rackPlan1 > tbody > tr > td:nth-child(' + starter + ')');
for (var a = 0; a < divs.length; a++) {
var thisDiv = divs[a]; // element
var $thisDiv = $(divs[a]); // jquery object
getAverage($thisDiv, 'subTotal');
}
starter += 1;
}
})
The calculations perform on the cells with the header of Proto A, B, etc. So for instance for bottoms in Proto A the third cell down what should be returned is 1.0 (the average) instead of 0.

How to compare cells in JavaScript table to each other and test for equality? How does indexOf work?

I created a table in my HTML code. It has 9 columns and 13 rows. It gets filled up completely by a JavaScript loop that fills it with names of people from a few arrays. However, I want to add a validation step that makes sure that no two cells within a row hold the same value and that the value of a each cell does not repeat in the cell directly beneath it.
Since I am only able to access the values of the cells of the table as a NodeList, I decided to make it into an array to use the IndexOf property to search through the array:
var table1 = document.getElementsByTagName("td");
var table1Array = []; //number of "td" elements on page
for (i = 0; i < 117; i++) {
table1Array[i] = table1[i].innerHTML;
}
I don't know of a more elegant method (sort of a beginner here). So I set up some nested loops to compare each cell to each element in the row array I create (for all 13 rows):
function validateCells() {
for (i = 0; i < 117; i = i + 9) { //increment for going to next column (after 9 cells or elements in array)
for (j = 0; j < 8; j++) {
var curCell = table1Array[i];
var curRow = []; //I'm ignoring the first column which is "date", so it has 8 elements rather than 9
for (k = 0; k < 8; k++) {
curRow[k] = document.getElementById("row" + j).children[k].innerHTML;
}
if (curRow.indexOf(curCell) != -1) {
curCell = "CONFLICT"; //trying to change value in table. Doesn't work.
}
}
}
}
Unfortunately, this won't work. I don't even know if modifying the value of the curCell reference variable will actually change the value of the table1Array at that location, even less if it will change the data in the table.
Am I using the indexOf property correctly? Do I use the != comparison operator or !==? Does indexOf return the index as a Is there any other less complicated, more elegant to do this? I just started with jQuery, maybe it can help simplify the code and make it less error-prone.
Sorry for the all the questions, I'm really trying to understand how all of this works. Thanks!
You should get an array of rows, each row is an array of cells. That way the validation is much easier. I'm not sure about how you want to show the conflict. In this demo I've just highlight the duplicated cells (conflicted) in red (at least I like this kind of showing conflict rather than modifying the conflicted cells' text).
HTML:
<table>
<tr><td>1</td><td>2</td><td>3</td></tr>
<tr><td>1</td><td>5</td><td>6</td></tr>
<tr><td>7</td><td>8</td><td>7</td></tr>
<tr><td>8</td><td>9</td><td>10</td></tr>
</table>
<button>Check constraints</button>
CSS:
td {
width:100px;
height:50px;
border:1px solid black;
}
table {
border:1px solid black;
border-collapse:collapse;
}
td.invalid {
background:red;
}
JS:
$('td').attr('contenteditable',true);
var cell;
function highlight(){
$(arguments).toggleClass('invalid',true);
}
function checkConstraints(e){
//reset style before re-checking
$('td.invalid').toggleClass('invalid');
//get rows as an array of array
var rows = $('tr').map(function(elem,i){
return [$(this).children('td').toArray()];
}).toArray();
//loop through the rows
for(var i = 0; i < rows.length; i++){
cell = {};
for(var j = 0; j < rows[i].length; j++){
var cellText = $(rows[i][j]).text();
if(cell[cellText]) {
highlight(cell[cellText], rows[i][j]);
} else {
cell[cellText] = rows[i][j];
}
if(i < rows.length - 1 &&
cellText == $(rows[i+1][j]).text()){
highlight(rows[i][j],rows[i+1][j]);
}
}
}
}
$('button').click(checkConstraints);
Demo.
Note that, I set contenteditable for all the cells (td), you can edit the cells text to what you want and click the button to test the demo.
You can use the table rows and cells collections for the iteration. The following does a literal comparison of the text content, you may wish to process the text first to "normalise" it in regard to whitespace.
<table id="t0">
<tr><td>foo<td>bar<td>fum</td>
<tr><td>fum<td>bar<td>foo</td>
<tr><td>foo<td>fum<td>fum</td>
</table>
<script>
compareRows(document.getElementById('t0'));
function compareRows(table) {
var row, rows = table.rows;
var cell, cells;
var rowText;
// For each row in the table
for (var i=0, iLen=rows.length; i<iLen; i++) {
row = rows[i];
cells = row.cells;
// Compare the text in each cell
for (var j=0, jLen=cells.length; j<jLen; j++) {
cell = cells[j];
for (var k=0; k<jLen; k++)
if (k != j && cells[k].textContent == cell.textContent) {
// cell text is repeated in current row
console.log('row ' + i + ' cell ' + j + ' text repeated in cell ' + k);
}
// Compare with the text in the cell immediately below (if there is one)
if (i < iLen-2 && cell.textContent == rows[i+1].cells[j].textContent) {
// cell text is repeated in next row
console.log('row ' + i + ' cell ' + j + ' text repeated in row ' + (i+1));
}
}
}
}
</script>
Note that repeated text in a row will be reported twice.
The above uses the textContent property, which may be supported as innerText in some user agents. It also runs about 10 times faster than the jQuery alternative.

JQuery not replacing html

here is the deal, i have the following jquery code that should add the array values to specific #id, buf it does not replace the code, only add more, and i need a little help to make it replace the html on othe link click.
Code:
function changeClass(curClass){
switch(curClass){
case "Schoolgirl":
case "Fighter":
var charSkillsNames = ["text1","text2","text4","text5"];
//loop show array values
listSkillsNames(charSkillsNames);
break;
}
}
function listSkillsNames(arr){
var length = arr.length,
element = null;
$("#skills").html(function(){
for (var i = 0; i < length; i++) {
element = arr[i];
$(this).append("<li>"+element+"</li>");
}
});
}
this works well but i need it to replace the html inside the "#skills" id when i click on the link that makes it work
PS: problem is really here
The issue is that you don't empty the HTML of #skills element. Use $("#skills").html("") to empty it.
function listSkillsNames(arr){
var length = arr.length,
element = null;
var $skills = $("#skills");
$skills.html(""); // empty the HTML
for (var i = 0; i < length; i++) {
element = arr[i];
$skills.append("<li>"+element+"</li>"); // append new items
}
}
The problem is because you are keep appending new items to the element always without removing the existing items.
Just empty the skill element, also there is no need to use the .html(function(){}) here
function listSkillsNames(arr) {
var length = arr.length,
element = null;
var $skill = $("#skills").empty();
for (var i = 0; i < length; i++) {
element = arr[i];
$skill.append("<li>" + element + "</li>");
}
}

Categories