Iterating through html array is not working in javascript - javascript

I tried iterating through this but could not.
the function below
function orderpackage (){
var product_line = $('#carttable')[0].getElementsByTagName('tr');
for (var i = 1; i < product_line.length; i++) {
}
console.log(product_line)
Produces this in the console output
each of the tr.table_row is made from this
<tr class="table_row">
<td class="column-1">
<div class="how-itemcart1">
<img src=${Items.imageurl} alt="IMG">
</div>
</td>
<td class="column-2">${Items.name}</td>
<td class="column-3">$ ${Items.price}</td>
<td class="column-4">
<div class="wrap-num-product flex-w m-l-auto m-r-0">
<div class="btn-num-product-down cl8 hov-btn3 trans-04 flex-c-m qty-change" id="qty-change">
<i class="fs-16 zmdi zmdi-minus"></i>
</div>
<input class="mtext-104 cl3 txt-center num-product" type="number" name="num-product1" value=${Items.user_quantity}>
<div class="btn-num-product-up cl8 hov-btn3 trans-04 flex-c-m qty-change" id="qty-change">
<i class="fs-16 zmdi zmdi-plus"></i>
</div>
</div>
</td>
<td class="column-5">${line_total_sum}</td>
</tr>
what I want to do is iterate through each and get the price, quantity and line total.
When I tried the function below for the line total is shows error
var product_line = $('#carttable')[0].getElementsByTagName('tr')[4];
How do I iterate through each tr to the price, quantity and line total?

With plain JS, you can use HTMLTableElement.rows to get all the rows on the table.
Then you need to iterate over them, probably skipping the first one (header). For each one, access the children (cells) that contain the fields you need and create a new array with them, [price, quantity, total], and push that one to another array containing the data for all the table.
Here's one way to do it using Array.from() and Array.prototype.map():
const tableData = Array.from(document.getElementById('table').rows).slice(1).map(row => {
const cells = row.children;
return [cells[0].innerText, cells[1].innerText, cells[2].innerText];
});
console.log(JSON.stringify(tableData));
table {
border-collapse: collapse;
font-family: monospace;
text-align: right;
}
table, th, td {
border: 3px solid black;
}
th, td {
padding: 5px 10px;
}
<table id="table">
<tr><th>PRICE</th><th>QUANTITY</th><th>TOTAL</th></tr>
<tr><td>1</td><td>5</td><td>5</td></tr>
<tr><td>10</td><td>2</td><td>20</td></tr>
<tr><td>8</td><td>4</td><td>32</td></tr>
</table>
If you prefer to use a for...of loop instead:
let tableData = [];
// Iterate over every row:
for (const row of document.getElementById('table').rows) {
// Get the cells in the current row:
const cells = row.children;
// Read the text on the columns we want:
tableData.push([cells[0].innerText, cells[1].innerText, cells[2].innerText]);
}
// Remove the first row (header):
tableData = tableData.slice(1);
console.log(JSON.stringify(tableData));
table {
border-collapse: collapse;
font-family: monospace;
text-align: right;
}
table, th, td {
border: 3px solid black;
}
th, td {
padding: 5px 10px;
}
<table id="table">
<tr><th>PRICE</th><th>QUANTITY</th><th>TOTAL</th></tr>
<tr><td>1</td><td>5</td><td>5</td></tr>
<tr><td>10</td><td>2</td><td>20</td></tr>
<tr><td>8</td><td>4</td><td>32</td></tr>
</table>
Or just a normal for loop instead:
const rows = document.getElementById('table').rows;
const totalRows = rows.length;
const tableData = [];
// Iterate over every row, skipping the first one (header) already:
for (let i = 1; i < totalRows; ++i) {
// Get the cells in the current row:
const cells = rows[i].children;
// Read the text on the columns we want:
tableData.push([cells[0].innerText, cells[1].innerText, cells[2].innerText]);
}
console.log(JSON.stringify(tableData));
table {
border-collapse: collapse;
font-family: monospace;
text-align: right;
}
table, th, td {
border: 3px solid black;
}
th, td {
padding: 5px 10px;
}
<table id="table">
<tr><th>PRICE</th><th>QUANTITY</th><th>TOTAL</th></tr>
<tr><td>1</td><td>5</td><td>5</td></tr>
<tr><td>10</td><td>2</td><td>20</td></tr>
<tr><td>8</td><td>4</td><td>32</td></tr>
</table>

Related

Save content editable HTML table in multiple fields

I need to develop a HTML table where one of the table column is editable on its row and the table row is dynamic in term of the row number.
I come across a problem where when I automate the saveEdits() function, the code is not working.
Here is my code, where the 'cnt' is a dynamic numeric number. Example cnt=50
<!DOCTYPE html>
<html>
<head>
<style>
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
table ,tr td{
border:1px solid #dddddd;
padding: 8px;
}
tbody {
display:block;
height:600px;
overflow:auto;
}
thead, tbody tr {
display:table;
width:100%;
table-layout:fixed;
}
thead {
width: calc( 100% - 1em )
}
tr:nth-child(even) {
background-color: #dddddd;
}
</style>
<script type="text/javascript">
function saveEdits(cnt) {
//get the editable elements.
var str_out = ''
while (cnt>0){
str1 = '\'edit' + cnt + '\': document.getElementById(\'edit' + cnt + '\').innerHTML,\n'
str_out = str_out.concat(' ', str1);
cnt--;
};
var editElems= { str_out };
alert(editElems)
//save the content to local storage. Stringify object as localstorage can only support string values
localStorage.setItem('userEdits', JSON.stringify(editElems));
}
function checkEdits(){
//find out if the user has previously saved edits
var userEdits = localStorage.getItem('userEdits');
alert(userEdits) // suppose to print {"edit1":" rpeyy7<br>","edit2":" tpruiiy<br>","edit3":" opty<br>"}
if(userEdits){
userEdits = JSON.parse(userEdits);
for(var elementId in userEdits){
document.getElementById(elementId).innerHTML = userEdits[elementId];
}
}
}
</script>
</head>
<body onload="checkEdits()">
<table id="myTable">
<thead>
<tr>
<td style="background-color:#A9A9A9" > Field#1 </td>
<td style="background-color:#A9A9A9" > Field#2 </td>
<td style="background-color:#A9A9A9" > Field#3- Each Row Under field#3 is content EditableByUser </td>
</tr>
</thead>
<tbody>
// Here is the python code that loop through a diectionary content
cnt = 0
for c in sorted(data_dict.keys()) :
cnt += 1
<tr>
<td> {0} </td> //Field#1
<td> {0} </td> //Field#2
...
...
<td id="edit{0}" contenteditable="true" onKeyUp="saveEdits({0});"> {1} </td>\n'.format(cnt,comment)]
</tr>
</table>
</body>
I'm not sure where goes wrong as when I automate the saveEdits() function with 'cnt' in while loop, the above code doesn't works for me. But when I defined each row clearly like below, the data the keyed-in are properly saved to each column.
function saveEdits(cnt) {
//get the editable elements.
var editElems = {
'edit1': document.getElementById('edit1').innerHTML,
'edit2': document.getElementById('edit2').innerHTML,
'edit3': document.getElementById('edit3').innerHTML,
};
alert(editElems) //print [object Object]
//save the content to local storage. Stringify object as localstorage can only support string values
localStorage.setItem('userEdits', JSON.stringify(editElems));
}
I would be much appreciate if someone can point out my mistake. The error is very much likely on saveEdits(cnt) function but I'm not sure how to fix that cause it I define each count 1 by 1, each update that being keyed-in is actually saved properly and able to retrieve when rerun. Thanks you!

Convert index.html to complete Vue CLI structure

I created this app to calculate cube of a number and then cube of the individual elements of the output. I created this Vue js project in JS Fiddle to learn the basics of Vue. But I want to move to complete Vue CLI project. I installed Vue.js in my computer but I can't figure out how to port this single file index.html into the different files in Vue CLI project (App.vue, HelloWorld.vue, main.js). Can anyone tell me how exactly to convert this single page file to the actual project files.
<div id="cubed">
<input v-model='mainNumber' placeholder='Enter a number.'>
<button v-on:click="cube">Submit</button>
<p>
Cube of the number is: {{ this.result }} <br>
</p>
<table id="table">
<tr v-for="row in 2" :key="item">
<td v-for="item in result" v-text="row > 1 ? cubeInt(item) : item"></td>
</tr>
</table>
</div>
#table {
border-collapse: collapse;
width: 50%;
text-align: center;
}
#table td, #customers th {
border: 1px solid #ddd;
padding: 8px;
}
#table tr:nth-child(even){background-color: #f2f2f2;}
#table tr:hover {background-color: #ddd;}
new Vue({
el: "#cubed",
data: {
mainNumber: null,
result: null
},
methods: {
cubeInt: function(int) {
return int*int*int
},
cube: function(event){
var allowedInput = /^[0-9]/;
if (this.mainNumber.match(allowedInput)){
let calc = this.cubeInt(this.mainNumber);
let strToNum = calc.toString().split('').map(Number);
this.result = strToNum
} else {
alert('Only digits are allowed.');
}
},
}
})
So using the Vue cli we have vue files, each file has a
template
script
style (optional)
I recommend checking out: The Project Anatomy section of this site:
https://www.sitepoint.com/vue-cli-intro/
And checkout some tutorials from netninja on youtube, they're really helpful!
If you want to get it working now, but are stuck on importing components etc, as a test, replace and save the HelloWorld.vue file with below your below vue format code:
<template>
<div id="cubed">
<input v-model='mainNumber' placeholder='Enter a number.'>
<button v-on:click="cube">Submit</button>
<p>
Cube of the number is: {{ this.result }} <br>
</p>
<table id="table">
<tr v-for="row in 2" :key="item">
<td v-for="item in result" v-text="row > 1 ? cubeInt(item) : item"></td>
</tr>
</table>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data: {
mainNumber: null,
result: null
},
methods: {
cubeInt: function(int) {
return int*int*int
},
cube: function(event){
var allowedInput = /^[0-9]/;
if (this.mainNumber.match(allowedInput)){
let calc = this.cubeInt(this.mainNumber);
let strToNum = calc.toString().split('').map(Number);
this.result = strToNum
} else {
alert('Only digits are allowed.');
}
},
}
}
</script>
<style scoped>
#table {
border-collapse: collapse;
width: 50%;
text-align: center;
}
#table td, #customers th {
border: 1px solid #ddd;
padding: 8px;
}
#table tr:nth-child(even){background-color: #f2f2f2;}
#table tr:hover {background-color: #ddd;}
</style>

auto refrsh api data

i need to refresh particular data line in every interval when the value change
$(document).ready(
function() {
setInterval(function() {
var randomnumber = Math.floor();
$('#output').text(
gettxt()+ randomnumber);
}, 1000);
});
function gettxt(){
fetch('https://min-api.cryptocompare.com/data/top/exchanges?fsym=BTC&tsym=USD')
.then((res)=>res.text())
.then((data)=>{
document.getElementById('output').innerHTML=data;
})
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<div id="output" style="margin:5px 0;">
</div>
<script type="text/javascript"
src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
</body></html>
Here i get all refreshed in every seconds. i need to refresh only a particular line
Hi Here I done as per your req, Just one line I have done, for other line do by your self, I just makes your string obj into obj and added table style.
js fiddle
html
<style>
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td, th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #dddddd;
}
</style>
<div id="output" style="margin:5px 0;">
</div>
<table>
<tr>
<th style="margin-left:20px">exchange</th>
<th>fromSymbol</th>
<th>toSymbol</th>
<th> volume24h</th>
<th>volume24hTo</th>
</tr>
<tr>
<td>Bitfinex</td>
<td>BTC</td>
<td>USD</td>
<td id="volume24h">BTC</td>
<td id="volume24hTo">USD</td>
</tr>
</table>
java script
$(document).ready(
function() {
setInterval(function() {
var randomnumber = Math.floor();
$('#output').text(
gettxt()) + randomnumber;
}, 1000);
gettxt()
});
function gettxt(){
fetch('https://min-api.cryptocompare.com/data/top/exchanges?fsym=BTC&tsym=USD')
.then((res)=>res.text())
.then((data)=>{
var dataTemp = JSON.parse(data);
document.getElementById('volume24h').innerHTML=dataTemp.Data[0].volume24h;
document.getElementById('volume24hTo').innerHTML=dataTemp.Data[0].volume24hTo;
console.log(dataTemp);
})
}

Javascript sorting a csv rows and displaying in table

I have a csv file which has this format:
Major;2;4;29
Major should be displayed on the 4 row 2 column.
The file can have a lot nof rows!
I have created this:
var fileInput = document.getElementById("csv"),
readFile = function () {
var reader = new FileReader();
reader.onload = function () {
document.getElementById('out').innerHTML = reader.result;
};
reader.readAsBinaryString(fileInput.files[0]);
};
fileInput.addEventListener('change', readFile);
<style type="text/css">
output {
display: block;
margin-top: 4em;
font-family: monospace;
font-size: .8em;
}
</style>
which basically takes a csv file as an input and prints all as it is raw!How can I work and divide the rows on the ";"?And I also want an honest answer what level is this for?(intern,senior?)
Here's a trivial example, it's fairly straight forward. The issue will be splitting the data, it's pretty simple if the data is simple and the delimiter unique. But if the delimiter is in the data, the splitting into values requires a little more cleverness.
This uses table.rows to get the row, then row.cells to get the cell and inserts the value. Columns and rows are zero indexed, and for rows includes the header and footer (if they exist). You can also use the tbody.rows if the header rows should be skipped.
var data = 'Major;1;2;29\nMinor;2;3;29';
function insertData(id, data) {
// Show data
console.log(data);
// Get the table
var table = document.getElementById(id);
// Split the data into records
var dataRows = data.split(/\n/);
// Split each row into values and insert in table
if (table) {
dataRows.forEach(function(s) {
var x = s.split(';');
table.rows[x[2]].cells[x[1]].textContent = x[0];
});
}
}
table {
border-collapse: collapse;
border-left: 1px solid #999999;
border-top: 1px solid #999999;
}
td, th {
border-right: 1px solid #999999;
border-bottom: 1px solid #999999;
}
<table id="t0">
<thead>
<tr>
<th>col 0<th>col 1<th>col 2
</thead>
<tbody>
<tr>
<td> <td><td>
<tr>
<td> <td><td>
<tr>
<td> <td><td>
</tbody>
</table>
<button onclick="insertData('t0', data)">Insert data</button>

Javascript Dynamic Table with each cell having an onmouse event?

I've created a dynamic table using Javascript. Now what I'm trying to do is for each cell that is dynamically generated, there is an onmouseover event that would change that particular cell's backgroundColor.
The problem I have is that when I generate the table and try to have an onmouseover function with each dynamically generated cell the function only works for the last generated cell.
Here's a copy of my code. (Note: I have only tested this on Chrome)
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
padding: 5px;
text-align: center;
}
</style>
<script type="text/javascript">
var table;
function init(){
table = document.getElementById("mytable");
}
function makeCells(){
init();
for(var a=0;a<20;a++){
var row = table.insertRow(-1);
for(var b=0;b<20;b++){
cell = row.insertCell(-1);
cell.innerHTML = a*b;
cell.onmouseover = function(){cell.style.backgroundColor = "yellow";};
}
}
}
</script>
</head>
<body onload="javascript: makeCells();">
<table id="mytable"></table>
</body>
</html>
Any advice would be greatly appreciated.
Some Improvements. 3 things I would change:
Don't edit inline styles with javascript. Instead, add or remove a class. see # 3.
Don't do so many event handlers in your "onload", "onmouseover". Its better to add an event listener.
It is better performance to add all of the new elements at one time instead of individually. See this article: https://developers.google.com/speed/articles/reflow
Here is a way to optimize the Javascript:
HTML
<table id="table"></table>
CSS
body {
padding: 40px;
}
.yellow {
background: yellow;
}
td {
padding: 10px 20px;
outline: 1px solid black;
}
JavaScript
function propegateTable() {
var table = document.getElementById("table");
//will append rows to this fragment
var fragment = document.createDocumentFragment();
for(var a=0; a<10; a++){ //rows
//will append cells to this row
var row = document.createElement("tr");
for(var b=0;b<5;b++){ //collumns
var cell = document.createElement("td");
cell.textContent = a + ", " + b;
// event listener
cell.addEventListener("mouseover", turnYellow);
row.appendChild(cell);
}
fragment.appendChild(row);
}
//everything added to table at one time
table.appendChild(fragment);
}
function turnYellow(){
this.classList.add("yellow");
}
propegateTable();
http://codepen.io/ScavaJripter/pen/c3f2484c0268856d3c371c757535d1c3
I actually found the answer myself playing around with my code.
In the line:
cell.onmouseover = function(){cell.style.backgroundColor = "yellow";};
I changed it to:
cell.onmouseover = function(){this.style.backgroundColor = "yellow";};

Categories