Create vertical column table based on Array of Objects - javascript

Let's say I have a Javascript Array of Product Objects
function Product() {
this.Name = "";
this.Cost = "";
this.Color = "";
}
var ProductsArray = [];
var product1 = new Product();
product1.Name = "Name1";
product1.Cost = "Cost1";
product1.Color = "Color1";
var product2 = new Product();
product2.Name = "Name2";
product2.Cost = "Cost2";
product2.Color = "Color2";
var product3 = new Product();
product3.Name = "Name3";
product3.Cost = "Cost3";
product3.Color = "Color3";
ProductsArray.push(product1);
ProductsArray.push(product2);
ProductsArray.push(product3);
ProductsArray now has the following
product1: [Name1, Cost1, Color1],
product2: [Name2, Cost2, Color2],
product3: [Name3, Cost3, Color3]
How do I loop through this Array of Objects so that I'm able to create table dynamically through jQuery which as the following format:
It's sort of like a table whose columns are horizontal
+-----------------------------------+
| Names | Name 1 | Name 2 | Name 3 |
+-----------------------------------+
| Costs | Cost 1 | Cost 2 | Cost 3 |
+-----------------------------------+
| Colors | Color1 | Color2 | Color3 |
+-----------------------------------+
<table>
<tr>
<th>Names</th>
<td>Name1</>
<td>Name2</>
<td>Name3</>
</tr>
<tr>
<th>Costs</th>
<td>Cost1</>
<td>Cost2</>
<td>Cost3</>
</tr>
<tr>
<th>Colors</th>
<td>Color1</>
<td>Color2</>
<td>Color3</>
</tr>
<table>
I guess the problem I'm having is since I loop through the Array in this fashion:
for (var i = 0; i < ProductsArray.length; i++) {
ProductsArray[i].Name
ProductsArray[i].Cost
ProductsArray[i].Color
}
I can only go through one object at time so I need a way to go through the values of each section each iteration, for example I need to go through the values of each Name and put them in <td> columns, then go through the values of each Cost and put them in a <td> etc...

I would suggest a slightly different approach. First I'd pass the arguments in the constructor, then I'd create the products array with instances and a function to make the HTML for your table.
You can use this with any collection, not only instances, but regular objects as well, just pass an array of objects, the properties to show, and the headers for each of those properties.
Demo: http://jsbin.com/gibez/1
function Product(name, cost, color) {
this.name = name;
this.cost = cost;
this.color = color;
}
var products = [
new Product('name1', 'cost1', 'color1'),
new Product('name2', 'cost2', 'color2'),
new Product('name3', 'cost3', 'color3')
];
function pluck(prop) {
return function(x) {
return x[prop];
};
}
function table(data, props, headers) {
var cells = props.map(function(prop) {
return '<td>'+ data.map(pluck(prop)).join('</td><td>') +'</td>';
});
var rows = headers.map(function(head, i) {
return '<tr><th>'+ head +'</th>'+ cells[i] +'<tr>';
});
return '<table>'+ rows.join('') +'</table>';
}
var tableHtml = table(
products,
['name', 'cost', 'color'],
['Names', 'Costs', 'Colors']
);

You can select the 3 trs ahead of time and use those as you iterate the array:
http://jsfiddle.net/QR7UZ/
<table>
<tr>
<th>Names</th>
</tr>
<tr>
<th>Costs</th>
</tr>
<tr>
<th>Colors</th>
</tr>
</table>
var $trs = $('table tr');
var $nameTr = $trs.eq(0);
var $costTr = $trs.eq(1);
var $colorTr = $trs.eq(2);
$.each(ProductsArray, function(idx, item) {
$('<td />').text(item.Name).appendTo($nameTr);
$('<td />').text(item.Cost).appendTo($costTr);
$('<td />').text(item.Color).appendTo($colorTr);
});

Hmm...you could add to three separate strings, that would each end up constituting a table row. Set up a skeleton table beforehand with the <tr> elements already in there, then run the script to fill each of them with <td> elements.
Maybe something like this (not sure how you're creating the elements, so I'll just use the jQuery .append() function).
HTML:
<table>
<tr class="name">
<th>Name</th>
</tr>
<tr class="cost">
<th>Cost</th>
</tr>
<tr class="color">
<th>Color</th>
</tr>
</table>
JavaScript:
var nameHtml = "";
var costHtml = "";
var colorHtml = "";
// Building strings
for (var i = 0; i < ProductsArray.length; i++) {
nameHtml += "<td>" + ProductsArray[i].Name + "</td>";
costHtml += "<td>" + ProductsArray[i].Cost + "</td>";
colorHtml += "<td>" + ProductsArray[i].Color + "</td>";
}
// Adding to rows
$(".name").append(nameHtml);
$(".cost").append(costHtml);
$(".color").append(colorHtml);
Here's a JSFiddle that demonstrates the example. There are plenty of ways to do this though, others have suggested some interesting ones. Main benefit here is that you can switch around table rows freely in the HTML without needing to change the JavaScript. Let me know if you have any questions. Hope this helps!

Related

How to print out result data in a table cell (and not on the same row) using Axios and vanilla JavaScript?

I want to be able to print out the next three upcoming train departure time, arrival time and train number when using Axios in JavaScript in a table that I have created with HTML.
I do get the output result after I have typed in the city name in the search bar and clicked search. However, the problem is that I get the output for the next upcoming train numbers in the same table cell, and same issue happens with the departure and arrival time as you can see down below in the image link.
Output result
I have tried changing the CSS using display: flex; but it doesn't work. I have even tried hard coding the array index using 0, 1, 2 instead of i and removed the for-loop but then the output result will only show one of the latest train departure time, arrival time and train number, and not all three of them at the same time which is what I wish to have, which is like this:
Trainnr: Departure Arrival
Regional Tåg 971 19:11:00 19:48:00
Regional Tåg 863 19:21:00 19:53:00
Länstrafik - Tåg 40 19:26:00 20:25:00
This is my code in the HTML for the train table:
<section class="trainSchedule">
<strong><p class="train-title">Railway Time Table</p></strong>
<div class="box">
Does the train go to Stockholm?
<br />
I'm departing from..
<input type="text" class="request-input" placeholder="Ex: Göteborg" />
<button class="request-btn">Search...</button>
<div class="message-box">
<table class="table">
<thead>
<tr>
<th class="trainNumber">TrainNr:</th>
<th class="departure">Departure:</th>
<th class="arrival">Arrival:</th>
</tr>
<tr>
<td class="trainNum"></td>
<td class="trainDep"></td>
<td class="trainArr"></td>
</tr>
</thead>
</table>
</div>
Departing from: <strong><div class="response-result"></div></strong>
</div>
</section>
And here is vanilla JavaScript code using axios:
let reqBtn = document.querySelector(".request-btn");
let reqInput = document.querySelector(".request-input");
let respResult = document.querySelector(".response-result");
const API_KEY = "xxxxxxxxxxxxxxx";
const DEST_ID_FIXED = "740000001";
function getOriginIdURL(city, key) {
return `https://api.resrobot.se/v2.1/location.name?input=${city}&format=json&accessId=${key}`;
}
function getRouteURL(originId, destId, key) {
return `https://api.resrobot.se/v2.1/trip?format=json&originId=${originId}&destId=${destId}&passlist=true&showPassingPoints=true&accessId=${key}`;
}
function findRoute(fromCity) {
let searchURL = getOriginIdURL(fromCity, API_KEY);
axios.get(searchURL).then((response) => {
let data = response.data;
let originId = data.stopLocationOrCoordLocation[0].StopLocation.extId;
let routeURL = getRouteURL(originId, DEST_ID_FIXED, API_KEY);
axios.get(routeURL).then((response) => {
let data = response.data;
// console.log(response.data.Trip[0].LegList.Leg[0].Product[0].name);
let trainNum = document.querySelector(".trainNum");
let trainDep = document.querySelector(".trainDep");
let trainArr = document.querySelector(".trainArr");
for (let i = 0; i < 3; i++) {
trainNum.textContent += "\n" + data.Trip[i].LegList.Leg[0].Product[0].name;
trainDep.textContent += "\n" + data.Trip[i].Origin.time;
trainArr.textContent += "\n" + data.Trip[i].Destination.time;
let table = document.querySelector('table');
let tr = document.createElement('tr');
let tr2 = document.createElement('td');
let tr3 = document.createElement('td');
let tr4 = document.createElement('td');
tr2 = trainNum.textContent;
tr3 = trainDep.textContent;
tr4 = trainArr.textContent;
// tr.append(tr2, tr3, tr4);
table.append(tr);
}
respResult.textContent = `${reqInput.value}`;
// console.log(data.Trip[0].Origin.time);
// console.log(data.Trip[1].Origin.time);
// console.log(data.Trip[2].Destination.name);
// console.log("");
});
});
}
reqBtn.addEventListener("click", (event) => {
findRoute(reqInput.value);
});
What am I doing wrong here?
I really appreciate if anyone can help me out and explain.
Thank you
I'm just re-writing the part where you process the response, because I think that's the only part of interest here. Basically, you should create your new row (<tr>) and your new cells (<td>) before to add content to them. And then you set the text content of them. And then you append the row to the table.
axios.get(routeURL).then((response) => {
let data = response.data;
for (let i = 0; i < 3; i++) {
let newRow = document.createElement("tr");
let trainNumCell = document.createElement("td");
trainNumCell.classList.add("trainNum");
newRow.append(trainNumCell);
let trainDepCell = document.createElement("td")
trainDepCell.classList.add("trainDep")
newRow.append(trainDepCell);
let trainArrCell = document.createElement("td")
trainArrCell.classList.add("trainArr")
newRow.append(trainArrCell);
trainNumCell.textContent = data.Trip[i].LegList.Leg[0].Product[0].name;
trainDepCell.textContent = data.Trip[i].Origin.time;
trainArrCell.textContent = data.Trip[i].Destination.time;
let table = document.querySelector('table');
table.append(newRow);
}
respResult.textContent = `${reqInput.value}`;
});
Concerning the HTML, you could simplify it, you don't to pre-create a row. So you table could be only this
<table class="table">
<thead>
<tr>
<th class="trainNumber">TrainNr:</th>
<th class="departure">Departure:</th>
<th class="arrival">Arrival:</th>
</tr>
</thead>
</table>

What am I doing wrong in creating this dynamically generated table?

Apologies for any simple mistakes, this is my first Stack Overflow post and I'm relatively new to coding.
I am attempting to create a website that displays a dynamically generated table using DOM elements. This table's rows and columns have been defined using DOM elements, and it should now populate itself on page load when storeItemOutput() is called from initialize(). It should be pulling the data from a loop through the previously defined and populated array storeItems, and displaying their attributes in the table id "storeItemOutput". It should also get one of five values from a dropdown box, and display items that match the selected category whenever it is changed.
However, I can't get the table itself or it's contents to actually display on the page. I'm unsure what is preventing this, and the lack of any output has left me stumped. Am I missing some code in my function? Is the table not created properly?
I've included parts of my code below, as well as expected output and actual output to try and help you understand my issue.
<select class="categoryDropDown" style="margin: 30px;">
<p>
<option selected value="All" onload="storeItemOutput();">All</option>
<option value="Tops" onchange="storeItemOutput();">Tops</option>
<option value="Bottoms" onchange="storeItemOutput();">Bottoms</option>
<option value="Shoes" onchange="storeItemOutput();">Shoes</option>
<option value="Accessories" onchange="storeItemOutput();">Accessories</option>
</p>
</select>
<table id="storeItemOutput">
<span><strong>| ID | Product Name | Price | Qty | Max | Category | Image |</strong></span>
</br>
<tbody>
<tr>
<th>b</th>
<th>b</th>
<th>b</th>
<th>b</th>
<th>b</th>
<th>b</th>
<th>b</th>
</tr>
<tr>
<td>b</td>
<td>b</td>
<td>b</td>
<td>b</td>
<td>b</td>
<td>b</td>
<td>b</td>
</tr>
</tbody>
(Output all store items via DOM table here)
</table>
This is some of my HTML code with an ID'd dummy table, and a dropdown menu class.
var storeItems = [];
function StoreItem(id, name, price, qtyOnHand, maxPerCust, category, shipping, reviews, description, image) {
this.id = id; //String
this.name = name; //String
this.price = price; //Number
this.qtyOnHand = qtyOnHand; //Number
this.maxPerCust = maxPerCust; //Number
this.category = category; //String
this.shipping = shipping; //Number
this.reviews = reviews; //Array
this.description = description; //String
this.image = image; //String
}
storeItems.push(new StoreItem("Y2k111", "Black Hoodie", 119.99, 10, 1, "Tops", 19.99, this.reviews, "100% Cotton Hoodie in Black", "/img/home_img/link"));
Some Javascript code of creating an empty array for store items, creating an object constructor for store items, and pushing a new item to the array (normally there is more than one item being pushed, I used just one here to save space).
function storeItemOutput() {
var itemTableDiv = document.getElementById("cartItemOutput");
var table = document.createElement("table");
itemTableDiv.innerHTML = "";
document.getElementsByTagName("tbody")[0].remove();
var tBody = document.createElement("tbody");
var headerRow = document.createElement("tr");
var hC1 = document.createElement("th");
var hC2 = document.createElement("th");
var hC3 = document.createElement("th");
var hC4 = document.createElement("th");
var hC5 = document.createElement("th");
var hC6 = document.createElement("th");
var hC7 = document.createElement("th");
hC1.innerHTML = "Item ID";
hC2.innerHTML = "Item Name";
hC3.innerHTML = "Item Price";
hC4.innerHTML = "Item Quantity";
hC5.innerHTML = "Max Items Per Customer";
hC6.innerHTML = "Category";
hC7.innerHTML = "Image";
headerRow.appendChild(hC1);
headerRow.appendChild(hC2);
headerRow.appendChild(hC3);
headerRow.appendChild(hC4);
headerRow.appendChild(hC5);
headerRow.appendChild(hC6);
headerRow.appendChild(hC7);
tbody.appendChild(headerRow);
for (var index = 0; index < storeItems.length; index++) {
var products = storeItems[i];
var theRow = document.createElement("tr");
var c1 = document.createElement("td");
var c2 = document.createElement("td");
var c3 = document.createElement("td");
var c4 = document.createElement("td");
var c5 = document.createElement("td");
var c6 = document.createElement("td");
var c7 = document.createElement("td");
c1.innerHTML = products.id;
c2.innerHTML = products.name;
c3.innerHTML = "$" + products.price.toFixed(2);
c4.innerHTML = products.qtyOnHand;
c5.innerHTML = products.maxPerCust;
c6.innerHTML = products.category;
c7.innerHTML = products.image;
theRow.appendChild(c1);
theRow.appendChild(c2);
theRow.appendChild(c3);
theRow.appendChild(c4);
theRow.appendChild(c5);
theRow.appendChild(c6);
theRow.appendChild(c7);
tbody.appendChild(theRow);
}
itemTableDiv.appendChild(tbody);
var selectedCategory = document.getElementByClass("categoryDropDown").value;
var filteredItems = [];
var index = 0;
while (index < storeItems.length) {
if (storeItems[index].category == selectedCategory) {
filteredItems.push(storeItems[index]);
}
index++;
}
storeItemOutput(filteredItems);
And finally, my function that is meant to create and populate the table, before displaying the items that match the selected category.
Here is an image of what the table should look like:
working table
And the lack of output for my table:
my missing table
Any help would be appreciated.
Here's a working example. A few things worthy of mention:
I've used a template element, since it makes repeatedly creating
similar content very much faster.
Floating-point math has rounding errors. For this reason, I've stored the
prices in cents rather than dollars. Perform all math on the number
of cents, then present it as dollars & cents
A NodeList is very similar to, but slightly different than an array. It does not for instance have a forEach member function. For this reason, I used Array.from in the appendRow function. (which is actually shorter by 1 line if you use the commented code instead)
"use strict";
function newEl(tag) {
return document.createElement(tag)
}
function byId(id) {
return document.getElementById(id)
}
function qs(sel, parent = document) {
return parent.querySelector(sel)
}
function qsa(sel, parent = document) {
return parent.querySelectorAll(sel)
}
window.addEventListener('load', onLoaded, false);
function onLoaded(evt) {
var tableData = [
["PID01", "Fluffy Bear", 599, 600, 20, "Toy", "bear.png"],
["PID02", "Rubber Ducky", 1599, 40, 5, "Toy", "duck.png"],
["PID03", "Cool Handbag", 599, 1, 2, "Fashion", "bag.png"],
["PID04", "Fidget Spinner", 999, 120, 10, "Toy", "spinner.png"],
["PID05", "Lame Handbag", 4599, 60, 3, "Fashion", "bag.png"],
["PID06", "UltraMega Genuine Laptop", 170599, 20, 2, "Technology", "laptop.png"],
];
populateTable(tableData);
var categoryNames = ["All", "Fashion", "Toy", "Technology"];
populateSelect(byId('catSelector'), categoryNames);
qs('select').addEventListener('change', updateFilter, false);
}
function populateSelect(selElem, data) {
selElem.innerHTML = '';
data.forEach(txt => selElem.appendChild(new Option(txt, txt)));
}
function populateTable(data) {
data.forEach(appendRow);
function appendRow(itemData, itemIndex, items) {
let newRow = byId('productRowTemplate').content.cloneNode(true);
let cells = Array.from(newRow.firstChild.cells);
cells.forEach((cell, index) => {
if (index == 2)
cell.textContent = '$' + (itemData[index] / 100).toFixed(2);
else
cell.textContent = itemData[index];
});
// cells[0].textContent = itemData[0];
// cells[1].textContent = itemData[1];
// cells[2].textContent = '$'+(itemData[2]/100).toFixed(2);
// cells[3].textContent = itemData[3];
// cells[4].textContent = itemData[4];
// cells[5].textContent = itemData[5];
byId('storeItemOutput').tBodies[0].appendChild(newRow);
}
}
function updateFilter() {
let filter = byId('catSelector').value;
let prodRows = qsa('#storeItemOutput > tbody > tr');
if (filter == 'All') {
prodRows.forEach(row => row.classList.remove('notShown'));
} else {
prodRows.forEach(
row => {
if (row.cells[5].textContent == filter)
row.classList.remove('notShown');
else
row.classList.add('notShown');
}
);
}
}
.notShown {
display: none;
}
.price,
.qty,
.max {
text-align: right;
}
<template id='productRowTemplate'><tr>
<td class='id'></td>
<td class='name'></td>
<td class='price'></td>
<td class='qty'></td>
<td class='max'></td>
<td class='cat'></td>
<td><img class='icon'/></td>
</tr></template>
<body>
Filter:
<select id='catSelector'></select>
<table id='storeItemOutput'>
<thead>
<tr>
<th>ID</th>
<th>Product</th>
<th>Price</th>
<th>Qty</th>
<th>Max</th>
<th>Category</th>
<th>Image</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</body>

jQuery/Javascript compare two tables against each other

I need to compare two HTML tables' rows assuming that data in first cell can be duplicated but data in second cell is always unique. I need to find whether first cell AND second cell in table1 is the same as data in first cell AND second cell in table2 for instance:
Table1:
<Table>
<tr>
<td>123</td>
<td>321</td>
</tr>
<tr>
<td>545</td>
<td>345</td>
</tr>
<tr>
<td>0</td>
<td>312</td>
</tr>
<tr>
<td>123</td>
<td>323331</td>
</tr>
</Table>
Second table:
<table>
<tr>
<td>545</td>
<td>345</td>
</tr>
<tr>
<td>545</td>
<td>3122</td>
</tr>
<tr>
<td>123</td>
<td>321</td>
</tr>
</table>
The result of this should be:
123 321 - good, do nothing
545 345 - good, do nothing
545 3122 - wrong its not in table1 <-
Here's what I've got so far...
$('#runCheck').click(function(){
var firstTable = $('#firstDiv table tr');
var secondTable = $('#secDiv table tr');
$(secondTable).each(function(index){
var $row = $(this);
var secTableCellZero = $row.find('td')[0].innerHTML;
var secTableCellOne = $row.find('td')[1].innerHTML;
$(firstTable).each(function(indexT){
if ($(this).find('td')[0].innerHTML === secTableCellZero){
if ($(this).find('td')[1].innerHTML !== secTableCellOne){
$('#thirdDiv').append("first: " + secTableCellZero + " second: " + secTableCellOne+"<br>");
}
}
});
});
});
Where am I going it wrong?
Just to clarify once again:
2nd table says :
row1 - john|likesCookies
row2 - peter|likesOranges
1st table says :
row1 - john|likesNothing
row2 - john|likesCookies
row3 - steward|likesToTalk
row4 - peter|likesApples
now it should say :
john - value okay
peter - value fail.
a lot alike =VLOOKUP in excel
Check this working fiddle : here
I've created two arrays which store values in each row of tables 1 and 2 as strings. Then I just compare these two arrays and see if each value in array1 has a match in array 2 using a flag variable.
Snippet :
$(document).ready(function() {
var table_one = [];
var table_two = [];
$("#one tr").each(function() {
var temp_string = "";
count = 1;
$(this).find("td").each(function() {
if (count == 2) {
temp_string += "/";
}
temp_string = temp_string + $(this).text();
count++;
});
table_one.push(temp_string);
});
$("#two tr").each(function() {
var temp_string = "";
count = 1;
$(this).find("td").each(function() {
if (count == 2) {
temp_string += "/";
temp_string = temp_string + $(this).text();
} else {
temp_string = temp_string + $(this).text();
}
count++;
});
table_two.push(temp_string);
});
var message = "";
for (i = 0; i < table_two.length; i++) {
var flag = 0;
var temp = 0;
table_two_entry = table_two[i].split("/");
table_two_cell_one = table_two_entry[0];
table_two_cell_two = table_two_entry[1];
for (j = 0; j < table_one.length; j++) {
table_one_entry = table_one[j].split("/");
table_one_cell_one = table_one_entry[0];
table_one_cell_two = table_one_entry[1];
console.log("1)" + table_one_cell_one + ":" + table_one_cell_two);
if (table_two_cell_one == table_one_cell_one) {
flag++;
if (table_one_cell_two == table_two_cell_two) {
flag++;
break;
} else {
temp = table_one_cell_two;
}
} else {}
}
if (flag == 2) {
message += table_two_cell_one + " " + table_two_cell_two + " found in first table<br>";
} else if (flag == 1) {
message += table_two_cell_one + " bad - first table has " + temp + "<br>";
} else if (flag == 0) {
message += table_two_cell_one + " not found in first table<br>";
}
}
$('#message').html(message);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<hr>
<table id="one">
<tr>
<td>123</td>
<td>321</td>
</tr>
<tr>
<td>545</td>
<td>345</td>
</tr>
<tr>
<td>0</td>
<td>312</td>
</tr>
<tr>
<td>123</td>
<td>323331</td>
</tr>
</table>
<hr>
<table id="two">
<tr>
<td>545</td>
<td>345</td>
</tr>
<tr>
<td>545</td>
<td>3122</td>
</tr>
<tr>
<td>123</td>
<td>321</td>
</tr>
</table>
<hr>
<div id="message">
</div>
</div>
If I understand your requirements, it would be easier to read the first table and store the couples as strings: 123/321, 545/345, etc...
Than you can read the second table and remove from the first list all the rows found in both.
What remains in the list are couples that do not match.
From purely an efficiency standpoint if you loop through the first table just once and create an object using the first cell value as keys and an array of values for second cells, you won't have to loop through that table numerous times
this then makes the lookup simpler also
var firstTable = $('#firstDiv table tr');
var secondTable = $('#secDiv table tr');
var firstTableData = {}
firstTable.each(function() {
var $tds = $(this).find('td'),
firstCellData = $tds.eq(0).html().trim(),
secondCellData == $tds.eq(1).html().trim();
if (!firstTableData[firstCellData]) {
firstTableData[firstCellData] = []
}
firstTableData[firstCellData].push(secondCellData)
})
$(secondTable).each(function(index) {
var $tds = $(this).find('td');
var secTableCellZero = $tds.eq(0).html().trim();
var secTableCellOne = $tds.eq(1).html().trim();
if (!firstTableData.hasOwnProperty(secTableCellZero)) {
console.log('No match for first cell')
} else if (!firstTableData[secTableCellZero].indexOf(secTableCellOne) == -1) {
console.log('No match for second cell')
}
});
I'm not sure what objective is when matches aren't found

Getting coordinates of table cells and comparing with different tables via Javascript

It's really easy to access to coordinates of table cells with this and this example ways. But when I'm trying to get cells and compare with another table's cell which is avaible on page, a problem occurs. Because I don't know how to compare them in same time. After many hours I tried to do this, unfortunately, still there is no luck.
In following classic tables list below, shows 2 different tables with different id numbers:
<table id="a1">
<tbody>
<tr>
<td>RED</td>
<td>GREEN</td>
<td>BLUE</td>
</tr>
<tr>
<td>YELLOW</td>
<td>PINK</td>
<td>samespothere</td>
</tr>
</tbody>
</table>
<hr>
<table id="a2">
<tbody>
<tr>
<td>BLACK</td>
<td>BROWN</td>
<td>WHITE</td>
</tr>
<tr>
<td>CYAN</td>
<td>GRAY</td>
<td>samespothereANDsomeextra</td>
</tr>
</tbody>
</table>
And also, I'm using modified version of this JS example to get location of cells. This modified version I did is not able to make compare operation. I've just edited for make it easier.
var cells = document.getElementsByTagName("td"); //For all table cells on page.
var i;
for(i = 0; i < cells.length; i++)
{
cells[i].onclick = vera;
}
function vera()
{
var cellIndex = this.cellIndex + 1;
var rowIndex = this.parentNode.rowIndex + 1;
var centra = cellIndex +","+ rowIndex; //This gives the coordinate of cell which you clicked on.
alert(centra);
}
Here is my question: I need to make a compare operation when I click on samespothere(Example text I wrote) table cell. Compare operation should be able with the same location of other table. Lets think like this: If second table cell(same location, different table) includes some of clicked cell's text(from first table), alert must show up and say "This clicked text in table id=1 cell:2row:2, matched in table id=2 cell:2row:2".
And here is the online code: http://jsfiddle.net/LujydnaL/
I think this is what you want:
function vera()
{
var cellIndex = this.cellIndex + 1;
var rowIndex = this.parentNode.rowIndex + 1;
var centra = cellIndex +","+ rowIndex; //This gives the coordinate of cell which you clicked on.
alert(centra);
// new code here
table2 = document.getElementById('a2');
rowInTable2 = table2.getElementsByTagName('tr')[rowIndex-1];
cellInTable2 = rowInTable2.getElementsByTagName('td')[cellIndex-1];
console.log(cellInTable2);
// do something with cellInTable2 now
}
window.onload = function () {
document.getElementsByTagName('table')[0].addEventListener('click', function(element) {
var rowIndex = element.target.parentElement.rowIndex;
var cellIndex = element.target.cellIndex;
var compare = document.getElementsByTagName('table')[1].rows[rowIndex].cells[cellIndex];
var myNodelist = document.querySelectorAll("td");
var i;
for (i = 0; i < myNodelist.length; i++) {
myNodelist[i].style.backgroundColor = "white";
}
compare.style.backgroundColor = "grey";
document.getElementById('alert1').innerHTML = ('CLICK => Row index = ' + rowIndex + ', Column index = ' + cellIndex);
document.getElementById('alert2').innerHTML = ('COMPARE = ' + compare.innerHTML)
}, false);
}
tr, th, td {
padding: 0.2rem;
border: 1px solid black
}
table:hover {
cursor: pointer;
}
<table>
<tbody>
<tr>
<td>a11</td>
<td>a12</td>
<td>a13</td>
</tr>
<tr>
<td>a21</td>
<td>a22</td>
<td>a23</td>
</tr>
</tbody>
</table>
<p id="alert1"></p>
<hr>
<table>
<tbody>
<tr>
<td>b11</td>
<td>b12</td>
<td>b13</td>
</tr>
<tr>
<td>b21</td>
<td>b22</td>
<td>b23</td>
</tr>
</tbody>
</table>
<p id="alert2"></p>

Jquery - Sum of each same class li value

Currently I'm Developing an Invoice app with php , mysql & jquery. I want to show some details with jquery. I have dynamically created tables with dynamic data.
<table class="report_table">
<tr>
<td class="items_id">
<ul>
<li class="KKTF0">KKTF0</li>
<li class="PEN01">PEN01</li>
</ul>
</td>
<td class="items_qty">
<ul>
<li class="KKTF0">1</li>
<li class="PEN01">2</li>
</ul>
</td>
</tr>
</table>
<table class="report_table">
<tr>
<td class="items_id">
<ul>
<li class="BKK01">BKK01</li>
<li class="KKTF0">KKTF0</li>
<li class="PEN01">PEN01</li>
</ul>
</td>
<td class="items_qty">
<ul>
<li class="BKK01">4</li>
<li class="KKTF0">2</li>
<li class="PEN01">3</li>
</ul>
</td>
</tr>
</table>
li classes are dynamically created. my jquery code
jQuery(document).ready(function() {
$('.report_table').each(function() {
$('.items_id ul li').each(function() {
$(this).addClass($(this).text());
var className = $(this).attr("class");
$(this).parents('tr').find('td.items_qty li').eq($(this).index()).addClass(className);
});
});
});
I want this result
<table>
<tr>
<th>Item Id</th>
<th>Sum of Item</th>
</tr>
<tr>
<td>KKTF0</td>
<td>3</td>
</tr>
<tr>
<td>PEN01</td>
<td>5</td>
</tr>
<tr>
<td>BKK01</td>
<td>4</td>
</tr>
</table>
I don't have any idea. please help me... Thanks.
Pretty short solution:
var data = {};
$('.report_table .items_qty li').each(function() {
data[this.className] = (data[this.className] || 0) + +$(this).text();
});
var table = '<table class="result"><tr><tr><th>Item Id</th><th>Sum of Item</th></tr>' +
$.map(data, function(qty, key) {
return '<td>' + key + '</td><td>' + qty + '</td>';
}).join('</tr><tr>') + '</tr></table>';
http://jsfiddle.net/VF7bz/
Brief explanation:
1). each collects the data into an object:
{"KKTF0":3,"PEN01":5,"BKK01":4}
2). map creates an array:
["<td>KKTF0</td><td>3</td>","<td>PEN01</td><td>5</td>","<td>BKK01</td><td>4</td>"]
3). array items are joined into a string using </tr><tr> as separator.
Create an array of "items" and increment the associated quantity of each as you loop through every li. Then output the table.
function sum() {
// This will hold each category and value
var sums = new Array();
$('li').each(function() {
var item = new Object();
// Get category
item.category = $(this).attr('class');
// Get count
if (isFinite($(this).html())) {
item.count = parseInt($(this).html());
}
else {
// Skip if not a number
return;
}
// Find matching category
var exists = false;
for (var i = 0; i < sums.length; i++) {
if (sums[i].category == item.category) {
exists = true;
break;
}
}
// Increment total count
if (exists) {
sums[i].count += item.count;
}
else {
// Add category if it doesn't exist yet
sums.push(item);
}
});
var table = '<table><tr><th>Item Id</th><th>Sum of Item</th></tr><tbody>';
// Add rows to table
for (var i = 0; i < sums.length; i++) {
table += '<tr><td>' + sums[i].category + '</td><td>'
+ sums[i].count + '</td></tr>';
}
// Close table
table += '</tbody></table>';
// Append table after the last table
$('table :last').after(table);
}
Please omit the jquery code that you have posted in your question and use the one below:
Complete Jquery Solution:
Tested and Working
$(document).ready(function() {
//Create table to fill with data after last report table
$('<table id="sumtable"><th>Item Id</th><th>Sum of Item</th></table>').insertAfter($('.report_table').last());
//Loop through each report table, fetch amount and update sum in '#sumtable'
$('.report_table').each(function(){
var currtable = $(this);
$(this).find('.items_id ul li').each(function(){
//cache obj for performance
var curritem = $(this);
var itemid = curritem.html();
var itemvalue = parseInt(currtable.find('.items_qty ul li:eq('+curritem.index()+')').html());
var sumrow = $('#sumtable tbody').find('tr.'+itemid);
if(sumrow.length == 0){
//no rows found for this item id in the sum table, let's insert it
$('#sumtable tbody').append('<tr class="'+itemid+'"><td>'+itemid+'</td><td>'+itemvalue+'</td></tr>');
} else {
//Row found, do sum of value
sumrow.find('td').eq(1).html(parseInt(sumrow.find('td').eq(1).html())+itemvalue);
console.log(sumrow.find('td').eq(1).html());
}
});
})
});
DEMO: http://jsfiddle.net/N3FdB/
I am using .each loop on all li and store the values in the Object variable as key-value pairs.
Then, looping over created object properties building the desired table.
var resultObj = {};
$('li').each(function (idx, item) {
var $item = $(item);
var prop = $item.attr('class');
if (!resultObj[prop]) {
resultObj[prop] = 0;
}
var parsedVal = parseInt($item.text(), 10);
resultObj[prop] += isNaN(parsedVal) ? 0 : parsedVal;
});
var $resultTable = $('<table />');
$resultTable.append('<tr><th>Item Id</th><th>Sum of Item</th></tr>');
for (var key in resultObj) {
var $row = $('<tr />');
$row.append($('<td />', {
text: key
}))
.append($('<td />', {
text: resultObj[key]
}));
$resultTable.append($row);
}
$('body').append($resultTable);
Have a look at this FIDDLE.

Categories

Resources