Turn HTML table into array with javascript - javascript

Hi I have the following table:
<tbody>
<tr class="odd first-child">
<td class="first-child account_name">Label 1</td>
<td class="last-child balance">Amount 1</td>
</tr>
<tr class="even">
<td class="first-child account_name">Label 2</td>
<td class="last-child balance">Amount 2</td>
</tr>
<tr class="odd">
<td class="first-child account_name">Label 3</td>
<td class="last-child balance">Amount 3</td>
</tr>
<tr class="even">
<td class="first-child account_name">Label 4</td>
<td class="last-child balance">Amount 4</td>
</tr>
<tr class="odd">
<td class="first-child account_name">Label 5</td>
<td class="last-child balance">Amount 5</td>
</tr>
</tbody>
I need to turn it into an array using javascript, so that "Label 1" is the key for value "Amount 1," "Label 2" is the key for value "Amount 2," etc.
How might I go about this?
Thanks!

All you need to do is simply loop over the nodes.
var c = document.querySelectorAll('#tgt td');
var d = {};
for (var i = 0; i < c.length; i += 2) {
d[c[i].innerHTML] = c[i + 1].innerHTML;
}
console.log(d);
<table id="tgt">
<tbody>
<tr class="odd first-child">
<td class="first-child account_name">Label 1</td>
<td class="last-child balance">Amount 1</td>
</tr>
<tr class="even">
<td class="first-child account_name">Label 2</td>
<td class="last-child balance">Amount 2</td>
</tr>
<tr class="odd">
<td class="first-child account_name">Label 3</td>
<td class="last-child balance">Amount 3</td>
</tr>
<tr class="even">
<td class="first-child account_name">Label 4</td>
<td class="last-child balance">Amount 4</td>
</tr>
<tr class="odd">
<td class="first-child account_name">Label 5</td>
<td class="last-child balance">Amount 5</td>
</tr>
</tbody>
</table>

You could try simulate key/value pairs using following javascript:
var trElements = document.getElementsByTagName('tr');
var keyValue = [];
for(var i = 0; i < trElements.length; i++)
{
var tdElements = trElements[i].getElementsByTagName('td');
keyValue.push({"key":tdElements[0].innerHTML,"value":tdElements[1].innerHTML});
}
With following html:
<body>
<table>
<tr>
<td>Key1</td>
<td>Value1</td>
</tr>
<tr>
<td>Key2</td>
<td>Value2</td>
</tr>
</table>
</body>
That way you can get the value of your key or value by either choosing keyValue[i].key or keyValue[i].value. I think it's the simplest way. I don't think js supports key-value pairs by default.

Related

How to remove the contents of a <td> in a table dynamically using JS

I want when the user clicks the button with the class name "removeElement" the next "td" with class "forRemove" should have its contents removed.
How can I do it?
<table class="table">
<tbody class="list" id="list">
<tr>
<td>BODY 1</td>
<td>BODY 2</td>
<td>
<button class="removeElement">removeNextTd</button>
</td>
<td class="forRemove">BODY 4</td>
</tr>
<tr>
<td>BODY 1</td>
<td>BODY 2</td>
<td>
<button class="removeElement">removeNextTd</button>
</td>
<td class="forRemove">BODY 4</td>
</tr>
<tr>
<td>BODY 1</td>
<td>BODY 2</td>
<td>
<button class="removeElement">removeNextTd</button>
</td>
<td class="forRemove">BODY 4</td>
</tr>
</tbody>
</table>
The solution to your problem is here.
$('.removeElement').click(function(e){
$(this).parent().next().remove();
});
Also, I create the fiddle for you.
checkout this
<table class="table">
<tbody class="list" id="list">
<tr>
<td>BODY 1</td>
<td>BODY 2</td>
<td>
<button class="removeElement">removeNextTd</button>
</td>
<td class="forRemove">BODY 4</td>
</tr>
<tr>
<td>BODY 1</td>
<td>BODY 2</td>
<td>
<button class="removeElement">removeNextTd</button>
</td>
<td class="forRemove">BODY 4</td>
</tr>
<tr>
<td>BODY 1</td>
<td>BODY 2</td>
<td>
<button class="removeElement">removeNextTd</button>
</td>
<td class="forRemove">BODY 4</td>
</tr>
</tbody>
</table>
<script>
const buttons = document.getElementsByClassName('removeElement');
for(let i =0; i < buttons.length; ++i) {
buttons[i].onclick = function(event) {
const parent = event.currentTarget.parentNode.parentNode;
parent.children[parent.children.length - 1].innerHTML = "";
}
}
</script>
Is this more or less what you're looking for? To be honest I wouldn't access table elements like this, this is doing a bit much for such simple functionality, for exmaple, on the buttons I would add an indexer at the end of the class name or id, I would use IDs for in this case not only because is faster but also because you'd want quicker access to these elements without the hassle of having to go through so many nodes. i.e.:
<table class="table">
<tbody class="list" id="list">
<tr>
<td>BODY 1</td>
<td>BODY 2</td>
<td>
<button id="removeElement-0" class="removeElement">removeNextTd</button>
</td>
<td class="forRemove-0">BODY 4</td>
</tr>
<tr>
<td>BODY 1</td>
<td>BODY 2</td>
<td>
<button id="removeElement-1" class="removeElement">removeNextTd</button>
</td>
<td class="forRemove-1">BODY 4</td>
</tr>
<tr>
<td>BODY 1</td>
<td>BODY 2</td>
<td>
<button id="removeElement-2" class="removeElement">removeNextTd</button>
</td>
<td class="forRemove-2">BODY 4</td>
</tr>
</tbody>
</table>
<script>
const buttons = document.getElementsByClassName('removeElement');
for(let i =0; i < buttons.length; ++i) {
buttons[i].onclick = function(event) {
document.getElementsByClassName("forRemove-"+event.currentTarget.id[event.currentTarget.id.length-1])[0].innerHTML = "";
}
}
</script>
But Whatever works for you mate.
This clears the td. It is still there so the table wouldn't brake, but it is emty.
$('.removeElement').on('click', function() {
$(this).closest('tr').find('.forRemove').empty();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="table">
<tbody class="list" id="list">
<tr>
<td>BODY 1</td>
<td>BODY 2</td>
<td>
<button class="removeElement">removeNextTd</button>
</td>
<td class="forRemove">BODY 4</td>
</tr>
<tr>
<td>BODY 1</td>
<td>BODY 2</td>
<td>
<button class="removeElement">removeNextTd</button>
</td>
<td class="forRemove">BODY 4</td>
</tr>
<tr>
<td>BODY 1</td>
<td>BODY 2</td>
<td>
<button class="removeElement">removeNextTd</button>
</td>
<td class="forRemove">BODY 4</td>
</tr>
</tbody>
</table>
This will remove the contents of the next TD, with the class forRemove
$(".removeElement").on("click", function() {
$(this).closest("tr").find(".forRemove").empty();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table class="table">
<tbody class="list" id="list">
<tr>
<td>BODY 1</td>
<td>BODY 2</td>
<td>
<button class="removeElement">removeNextTd</button>
</td>
<td class="forRemove">BODY 4</td>
</tr>
<tr>
<td>BODY 1</td>
<td>BODY 2</td>
<td>
<button class="removeElement">removeNextTd</button>
</td>
<td class="forRemove">BODY 4</td>
</tr>
<tr>
<td>BODY 1</td>
<td>BODY 2</td>
<td>
<button class="removeElement">removeNextTd</button>
</td>
<td class="forRemove">BODY 4</td>
</tr>
</tbody>
</table>
In short, when you click the button it will find the nearest tr element by traversing up the DOM tree, and then find the element within that with the class forRemove, and then empty() it.
not exactly what you asked but you can do it like this with jquery
$this .parent()
.parent()
.remove();
since the delete button is within the row you want to delete this should work

Grouping selectors by ID

I have this code
<table>
<tr id="groupItem-12863">
<td>10</td>
<td class="selCost">34</td>
</tr>
<tr id="groupItem-12863">
<td>20</td>
<td class="selCost">5</td>
</tr>
<tr>
<td>14</td>
<td class="selCost">23</td>
</tr>
<tr id="groupItem-73632">
<td>28</td>
<td class="selCost">8</td>
</tr>
<tr id="groupItem-73632">
<td>54</td>
<td class="selCost">55</td>
</tr>
<tr id="groupItem-73632">
<td>13</td>
<td class="selCost">99</td>
</tr>
<tr>
<td>18</td>
<td class="selCost">55</td>
</tr>
<tr>
<td>99</td>
<td class="selCost">66</td>
</tr>
</table>
I want a jquery selector where I can loop over the group of id and fetch the value of td cell. Note: the tr id are generated dynamically and can have none or N rows for each group of id. For example (groupItem-12863 has 2 and groupItem-73632 has 3 rows)
Even if the following solution should do what you are expecting, I strongly suggest you to change the id to another attribute, a custom one like group-id or use CSS classes. By the way:
$(function() {
var groupedRows = {};
$.each($('tr[id^=groupItem]'), function() {
if (groupedRows[$(this).attr('id')]) {
groupedRows[$(this).attr('id')].push($(this));
}
else {
groupedRows[$(this).attr('id')] = [$(this)];
}
});
console.log(groupedRows);
});
HTML must not have same ids, it will be better to use class for your use-case.
After this you can get the elements with a given class and loop over them like
$(function(){
$('.groupItem-73632').each(function() {
console.log('grp');
$(this).find('td').each(function(){
console.log($(this).text());
})
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr class="groupItem-12863">
<td>10</td>
<td class="selCost">34</td>
</tr>
<tr class="groupItem-12863">
<td>20</td>
<td class="selCost">5</td>
</tr>
<tr>
<td>14</td>
<td class="selCost">23</td>
</tr>
<tr class="groupItem-73632">
<td>28</td>
<td class="selCost">8</td>
</tr>
<tr class="groupItem-73632">
<td>54</td>
<td class="selCost">55</td>
</tr>
<tr class="groupItem-73632">
<td>13</td>
<td class="selCost">99</td>
</tr>
<tr>
<td>18</td>
<td class="selCost">55</td>
</tr>
<tr>
<td>99</td>
<td class="selCost">66</td>
</tr>
</table>
I had to do bit of hack, I know the html was not ideal, we can't have same id's. But sometimes refactoring the older code is out of scope. Here is the solution, not ideal but works :
$('tr[id^=groupItem-]').each(function(){
var s = 0 ;
var text = $(this).attr('id');
var arr = text.split('-');
var elem = 'tr[id^=groupItem-' + arr[1] + ']';
$(elem).find("td.selCost").each(function(){
s += parseFloat($(this).text());
});
console.log($(this).attr('id')+ '=='+s);
});
You can use the wildcard selector like tr[id^=groupItem]. Check Attribute Selector for more example.
$(function() {
$('tr[id^=groupItem]').css({
'background-color': 'red'
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr id="groupItem-12863">
<td>10</td>
<td class="selCost">34</td>
</tr>
<tr id="groupItem-12863">
<td>20</td>
<td class="selCost">5</td>
</tr>
<tr>
<td>14</td>
<td class="selCost">23</td>
</tr>
<tr id="groupItem-73632">
<td>28</td>
<td class="selCost">8</td>
</tr>
<tr id="groupItem-73632">
<td>54</td>
<td class="selCost">55</td>
</tr>
<tr id="groupItem-73632">
<td>13</td>
<td class="selCost">99</td>
</tr>
<tr>
<td>18</td>
<td class="selCost">55</td>
</tr>
<tr>
<td>99</td>
<td class="selCost">66</td>
</tr>
</table>

Hide entire row when input is checked

So far I am only finding solutions to this in Jquery, but I am trying to solve this in Javascript.
I want to check a box and hide the other cells in the row's text content.
Javascript:
var rowElements = document.getElementsByClassName('tr-checked'),
for (var i = 0; i < rowElements.length; i++ ) {
rowElements[i].addEventListener('click', function(e){
var clickedElement = e.target;
if ( clickedElement.nodeName === 'input' && clickedElement.checked === true ) {
// if the clicked element is an input element, and is checked, meaning it's a checkbox, do the following:
this.parent.children.textContent = "";
}
})
}
HTML:
<table>
<thead>
<tr>
<td></td>
<td class="column-a">Course 1</td>
<td class="column-b">Course 2</td>
<td class="column-c">Course 3</td>
</tr>
</thead>
<tbody>
<tr class="row-a tr-checked">
<td><input type="checkbox"></input></td>
<td class="column-a">Specification 1</td>
<td class="column-b">Specification 1</td>
<td class="column-c">Specification 1</td>
</tr>
<tr class="row-b tr-checked">
<td><input type="checkbox"></input></td>
<td class="column-a">Specification 2</td>
<td class="column-b">Specification 2</td>
<td class="column-c">Specification 2</td>
</tr>
<tr class="row-c tr-checked">
<td><input type="checkbox"></input></td>
<td class="column-a">Specification 3</td>
<td class="column-b">Specification 3</td>
<td class="column-c">Specification 3</td>
</tr>
</tbody>
<tfoot>
<tr></tr>
</tfoot>
</table>
You can do it like this,
var rowElements = document.querySelectorAll('.tr-checked input[type="checkbox"]');
for (var i = 0; i < rowElements.length; i++) {
rowElements[i].addEventListener('change', function(e) {
var nextElement = this.parentElement.nextElementSibling;
while(nextElement) {
nextElement.style.display = this.checked ? "none" : "table-cell";
nextElement = nextElement.nextElementSibling;
}
});
}
DEMO
Here is my solution:
<table>
<thead>
<tr>
<td></td>
<td class="column-a">Course 1</td>
<td class="column-b">Course 2</td>
<td class="column-c">Course 3</td>
</tr>
</thead>
<tbody>
<tr class="row-a tr-checked">
<td>
<input type="checkbox" onchange="say(this)"></input>
</td>
<td class="column-a">Specification 1</td>
<td class="column-b">Specification 1</td>
<td class="column-c">Specification 1</td>
</tr>
<tr class="row-b tr-checked">
<td>
<input type="checkbox" onchange="say(this)"></input>
</td>
<td class="column-a">Specification 2</td>
<td class="column-b">Specification 2</td>
<td class="column-c">Specification 2</td>
</tr>
<tr class="row-c tr-checked">
<td>
<input type="checkbox" onchange="say(this)"></input>
</td>
<td class="column-a">Specification 3</td>
<td class="column-b">Specification 3</td>
<td class="column-c">Specification 3</td>
</tr>
</tbody>
<tfoot>
<tr></tr>
</tfoot>
</table>
Javascript
function say(v)
{
$(v.parentNode.parentNode).hide();
}

JQuery get cell value from row object

There is a table with few rows, one of row has .active class, each cell of row has each class, in JQuery selecting table row with .active class, how can i get cell with specific class value/text ('.html()')
var curentRow = $("#selectProduct tr.active);
//how can i get from curentRow value/text of cell with class .prod_name?
<table id="selectProduct" class="productTable">
<tr>
<td>Nr</td>
<td>ID</td>
<td>Product</td>
<td>Buy Price</td>
<td>Precent</td>
<td>Sell Price</td>
<td>Provider</td>
</tr>
<tr>
<td class="">1</td>
<td class="prod_id">1</td>
<td class="prod_name">Product 1</td>
<td class="buy_price">100</td>
<td class="plus_percent">10</td>
<td class="sell_price">110</td>
<td class="provider_name">provider 1</td>
</tr>
<tr class="active">
<td class="">2</td>
<td class="prod_id">2</td>
<td class="prod_name">Product 2</td>
<td class="buy_price">1000</td>
<td class="plus_percent">10</td>
<td class="sell_price">1100</td>
<td class="provider_name">provider 2</td>
</tr>
<tr>
<td class="">3</td>
<td class="prod_id">3</td>
<td class="prod_name">Product 3</td>
<td class="buy_price">50</td>
<td class="plus_percent">20</td>
<td class="sell_price">60</td>
<td class="provider_name">provider 3</td>
</tr>
</table>
Use function find() to find the cell that you need in the row:
var curentRow = $("#selectProduct tr.active");
var yourCell = curentRow.find('.prod_id');
var value = yourCell.text();

Resizable columns tables with fixed header

I'm trying to create a table with resizable columns and fixed header.
But when I'm trying to drag the header column, table columns change their size, but some gap is created.
For example:
What I get after dragging:
My sample:
<script>
$(document).ready(function(){
$('#tableHeader').colResizable({
liveDrag: true,
onDrag: resFun
});
function resFun() {
var c1 = $('#c1').width();
var c2 = $('#c2').width();
var c3 = $('#c3').width();
$('.c1').width(c1);
$('.c2').width(c2);
$('.c3').width(c3);
};
resFun();
});
</script>
<div style="padding-right: 17px; height: 39px;">
<table class="table table-bordered" id="tableHeader" style="width: 100%; height: 39px;">
<tr>
<th id="c1">first</th>
<th id="c2">second</th>
<th id="c3">third</th>
</tr>
</table>
</div>
<div style="overflow: auto; height: 200px;">
<table class="table table-bordered" id="table">
<tr>
<td class="c1">col 1</td>
<td class="c2">col 2</td>
<td class="c3">col 3</td>
</tr>
<tr>
<td class="c1">col 1</td>
<td class="c2">col 2</td>
<td class="c3">col 3</td>
</tr>
<tr>
<td class="c1">col 1</td>
<td class="c2">col 2</td>
<td class="c3">col 3</td>
</tr>
<tr>
<td class="c1">col 1</td>
<td class="c2">col 2</td>
<td class="c3">col 3</td>
</tr>
<tr>
<td class="c1">col 1</td>
<td class="c2">col 2</td>
<td class="c3">col 3</td>
</tr>
<tr>
<td class="c1">col 1</td>
<td class="c2">col 2</td>
<td class="c3">col 3</td>
</tr>
<tr>
<td class="c1">col 1</td>
<td class="c2">col 2</td>
<td class="c3">col 3</td>
</tr>
<tr>
<td class="c1">col 1</td>
<td class="c2">col 2</td>
<td class="c3">col 3</td>
</tr>
</table>
</div>
The problem is that the cells of the second table have a padding set and the cells of the header doesn't.. add padding to the header as well and should be ok

Categories