Sort HTML table by Javascript - javascript

I have the following HTML table which I wanted to be sorted by data-sku=""
( function() {
$("table tbody tr").sort(sort_table).appendTo('table tbody');
function sort_table(a, b) {
return ($(b).data('sku')) < ($(a).data('sku')) ? 1 : -1;
}
} )();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody>
<tr class="abp-product-42" data-id="42" data-sku="A-04-0002"><td>A-04-0002</tr>
<tr class="abp-product-21" data-id="21" data-sku="A-04-0011"><td>A-04-0011</td></tr>
<tr class="abp-product-391" data-id="391" data-sku="A-02-0008"><td>A-02-0008</td></tr>
<tr class="abp-product-393" data-id="393" data-sku="A-02-0007"><td>A-02-0007</td></tr>
<tr class="abp-product-40" data-id="40" data-sku="A-04-0010"><td>A-03-0010</td></tr>
<tr class="abp-product-390" data-id="390" data-sku="A-03-0003"><td>A-04-0003</td></tr>
</tbody>
</table>
But somehow it doesn't work - what I'm doing wrong or what I'm missing?

This will call your function in every 5 seconds like I mentioned in the comment.
window.setInterval(function(){
sortData();
}, 5000);
function sortData(){
$("table tbody tr").sort(sort_table).appendTo('table tbody');
function sort_table(a, b) {
return ($(b).data('sku')) < ($(a).data('sku')) ? 1 : -1;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody>
<tr class="abp-product-42" data-id="42" data-sku="A-04-0002"><td>A-04-0002</tr>
<tr class="abp-product-21" data-id="21" data-sku="A-04-0011"><td>A-04-0011</td></tr>
<tr class="abp-product-391" data-id="391" data-sku="A-02-0008"><td>A-02-0008</td></tr>
<tr class="abp-product-393" data-id="393" data-sku="A-02-0007"><td>A-02-0007</td></tr>
<tr class="abp-product-40" data-id="40" data-sku="A-04-0010"><td>A-04-0010</td></tr>
<tr class="abp-product-390" data-id="390" data-sku="A-03-0003"><td>A-03-0003</td></tr>
<tr class="abp-product-390" data-id="390" data-sku="A-05-0003"><td>A-05-0003</td></tr>
</tbody>
</table>

Your code is working fine.
Just, The last 2 rows attribute data-sku are not match with it's cell content.
<tr class="abp-product-40" data-id="40" data-sku="A-04-0010">
<td>A-03-0010</td>
</tr>
<tr class="abp-product-390" data-id="390" data-sku="A-03-0003">
<td>A-04-0003</td>
</tr>
(function () {
function sort_table(a, b) {
return ($(b).attr('data-sku')) < ($(a).attr('data-sku')) ? 1 : -1;
}
$("table tbody tr").sort(sort_table).appendTo('table tbody');
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody>
<tr class="abp-product-42" data-id="42" data-sku="A-04-0002">
<td>A-04-0002
</tr>
<tr class="abp-product-21" data-id="21" data-sku="A-04-0011">
<td>A-04-0011</td>
</tr>
<tr class="abp-product-391" data-id="391" data-sku="A-02-0008">
<td>A-02-0008</td>
</tr>
<tr class="abp-product-393" data-id="393" data-sku="A-02-0007">
<td>A-02-0007</td>
</tr>
<tr class="abp-product-40" data-id="40" data-sku="A-03-0010">
<td>A-03-0010</td>
</tr>
<tr class="abp-product-390" data-id="390" data-sku="A-04-0003">
<td>A-04-0003</td>
</tr>
</tbody>
</table>

Related

How to get the id of a clicked element within a table row?

I have the following table
<table width="97%" border="1" class="queueList">
<thead>
<tr>
<th>Delete</th>
<th>Queue Name</th>
<th>Current queue length</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.ImportQueues)
{
<tr id="watchRow">
<td id="DeleteButton">X</td>
<td id="QueueName", value="#item.QueueName">#item.QueueName</td>
<td>#item.CurrentQueueLength</td>
</tr>
}
</tbody>
how can I get the value of the element "QueueName" when "#DeleteRow" is clicked, using JQuery ?
So far I have
$("body").on("click", "#DeleteButton", function (event) {
var queueName = $(event.target).closest("div.queueList").find("#QueueName");
alert(queueName);
}
Use the data attribute to store the desired value on the button itself
<tr class="watchRow">
<td class="DeleteButton" data-queuename="#item.QueueName">X</td>
<td class="QueueName">#item.QueueName</td>
<td>#item.CurrentQueueLength</td>
</tr>
then on click of TD (by the way, it should be a button)
$("body").on("click", ".DeleteButton", function() {
var queueName = $(this).data("queuename");
alert(queueName);
}
If you want to use this name on other buttuns also, like edit etc. then it is better to assign it to the whole row:
<tr class="watchRow" data-queuename="#item.QueueName">
<td class="DeleteButton">X</td>
<td class="QueueName">#item.QueueName</td>
<td>#item.CurrentQueueLength</td>
</tr>
and read it like this:
$("body").on("click", ".DeleteButton", function() {
var queueName = $(this).closest('tr').data("queuename");
alert(queueName);
}
Without JQuery
<tr id="watchRow">
<td class="DeleteButton" onclick="deleteItem(#item.QueueName)">X</td>
<td value="#item.QueueName">#item.QueueName</td>
<td>#item.CurrentQueueLength</td>
</tr>
<script>
function deleteItem(item) {
alert(item)
}
</script>
With JQuery
<tr id="watchRow">
<td class="DeleteButton">X</td>
<td value="#item.QueueName">#item.QueueName</td>
<td>#item.CurrentQueueLength</td>
</tr>
<script>
$(".DeleteButton").on("click", function() {
alert($(this).next("td").html());
}
</script>
</script>

universal javascript selector to interact on all html element

I started on that http://jsfiddle.net/DRFBG/
And if I add tables so mytable1, mytable2,...
<table id="mytable1" border="1">
<tr><th>Column1</th><th>Column2</th><th>Column3</th><th>Column4</th></tr>
<tr class="data"><td>1st</td><td>1.1</td><td></td><td>1</td></tr>
<tr class="data"><td>2nd</td><td>2.01</td><td></td><td>2</td></tr>
<tr class="data"><td>3rd</td><td>3.001</td><td></td><td>3</td></tr>
<tr class="data"><td>4th</td><td>4.01</td><td></td><td>4</td></tr>
</table>
<table id="mytable2" border="1">
<tr><th>Column1</th><th>Column2</th><th>Column3</th><th>Column4</th></tr>
<tr class="data"><td>1st</td><td>1.1</td><td>1</td><td></td></tr>
<tr class="data"><td>2nd</td><td>2.01</td><td>2</td><td></td></tr>
<tr class="data"><td>3rd</td><td>3.001</td><td>3</td><td></td></tr>
<tr class="data"><td>4th</td><td>4.01</td><td>4</td><td></td></tr>
</table>
How could I uniform my javascript code for all tables?
I've already tried passing by table[div^=mytable]*, but the problem is the second selector in the function.
So any ideas please? Thank you? Sorry for my english
By the way, the code is to remove th with empty td for each table
$('#mytable2 th').each(function(i) {
var remove = 0;
var tds = $(this).parents('table').find('tr td:nth-child(' + (i + 1) + ')')
tds.each(function(j) { if (this.innerHTML == '') remove++; });
if (remove == ($('#mytable2 tr').length - 1)) {
$(this).hide();
tds.hide();
}
});
One approach is, selecting tables first and get their id and after that, doing the approach of http://jsfiddle.net/DRFBG/ on each of them like the following:
$('table').each(function()
{
var tb_id = $(this).attr('id');
$('#'+tb_id+' th').each(function(i) {
var remove = 0;
var tds = $(this).parents('table').find('tr td:nth-child(' + (i + 1) + ')')
tds.each(function(j) { if (this.innerHTML == '') remove++; });
if (remove == ($('#'+tb_id+' tr').length - 1)) {
$(this).hide();
tds.hide();
}
});
});
Here is the working jsfiddle
To select all on your page you can use "table" selector.
So you'd need to use $('table2 th') instead of $('#mytable2 th')
One possible solution would be to loop through each column of each table, then check if there are any non-empty cells. If there is not, then you can safely remove() all the td and th within that column.
Note that the removal needs to be done last, otherwise it will affect the indexing of the following columns. You can do that by simply marking the cells to be removed with a class, and then selecting that class once all loops complete. Try this:
$('table').each(function() {
var $table = $(this);
var rows = $table.find('tr').length - 1; // -1 to account for the headings
$table.find('th').each(function(i, th) {
var $empty = $table.find(`td:nth-child(${i + 1}):empty`);
if ($empty.length == rows)
$empty.add(this).addClass('to-remove');
})
$table.find('.to-remove').remove();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="mytable1" border="1">
<tr>
<th>Column1</th>
<th>Column2</th>
<th>Column3</th>
<th>Column4</th>
</tr>
<tr class="data">
<td>1st</td>
<td>1.1</td>
<td></td>
<td>1</td>
</tr>
<tr class="data">
<td>2nd</td>
<td>2.01</td>
<td></td>
<td>2</td>
</tr>
<tr class="data">
<td>3rd</td>
<td>3.001</td>
<td></td>
<td>3</td>
</tr>
<tr class="data">
<td>4th</td>
<td>4.01</td>
<td></td>
<td>4</td>
</tr>
</table>
<table id="mytable2" border="1">
<tr>
<th>Column1</th>
<th>Column2</th>
<th>Column3</th>
<th>Column4</th>
</tr>
<tr class="data">
<td>1st</td>
<td>1.1</td>
<td>1</td>
<td></td>
</tr>
<tr class="data">
<td>2nd</td>
<td>2.01</td>
<td>2</td>
<td></td>
</tr>
<tr class="data">
<td>3rd</td>
<td>3.001</td>
<td>3</td>
<td></td>
</tr>
<tr class="data">
<td>4th</td>
<td>4.01</td>
<td>4</td>
<td></td>
</tr>
</table>

Sort rows based in ascending order using jQuery

This code works but checks only the first column. I want to check the 2nd column instead with the points. How do I alter it?
HTML Table:
<table width="100%">
<thead>
<tr>
<th width="60%">Name</th>
<th width="20%">School</th>
<th width="20%">Points</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="4"><h1>Event 1</h1></td>
<td>School1</td>
<td>74</td>
</tr>
<tr>
<td>School2</td>
<td>69</td>
</tr>
<tr>
<td>School3</td>
<td>71</td>
</tr>
<tr>
<td>School4</td>
<td>11</td>
</tr>
<tr>
<td> </td>
<td> </td>
</tr>
<tr>
<td rowspan="4"><h1>Event 2</h1></td>
<td>School1</td>
<td>34</td>
</tr>
<tr>
<td>School5</td>
<td>29</td>
</tr>
<tr>
<td>School3</td>
<td>62</td>
</tr>
<tr>
<td>School7</td>
<td>15</td>
</tr>
</tbody>
</table>
jQuery:
var $tbody = $('#caltbl tbody');
$tbody.find('tr').sort(function (a, b) {
var tda = $(a).find('td:eq(0)').text();
var tdb = $(b).find('td:eq(0)').text();
// if a < b return 1
return tda > tdb ? 1
// else if a > b return -1
: tda < tdb ? -1
// else they are equal - return 0
: 0;
}).appendTo($tbody);
How do I got about this?
JSFIDDLE
EDIT: I'm sorry guys but my live code is different with rowspan being used. Is there a possibility to have this in ascending order so that the events are sorted differently?
eq(0) means you are using the first index. Change it to eq(1) so that it can consider the second index.
var tda = $(a).find('td:eq(1)').text();
var tdb = $(b).find('td:eq(1)').text();
You can sort the trs. Detach the td and insert to an array. Then append them back to each row
Add some class to simplify coding.
JSFIDDLE
HTML
<table width="100%">
<thead>
<tr>
<th width="60%">Name</th>
<th width="20%">School</th>
<th width="20%">Points</th>
</tr>
</thead>
<tbody>
<tr class="event1">
<td rowspan="4"><h1>Event 1</h1></td>
<td>School1</td>
<td class="point">74</td>
</tr>
<tr class="event1">
<td>School2</td>
<td class="point">69</td>
</tr>
<tr class="event1">
<td>School3</td>
<td class="point">71</td>
</tr>
<tr class="event1">
<td>School4</td>
<td class="point">11</td>
</tr>
<tr>
<td> </td>
<td> </td>
</tr>
<tr>
<td rowspan="4"><h1>Event 2</h1></td>
<td>School1</td>
<td>34</td>
</tr>
<tr>
<td>School5</td>
<td>29</td>
</tr>
<tr>
<td>School3</td>
<td>62</td>
</tr>
<tr>
<td>School7</td>
<td>15</td>
</tr>
</tbody>
</table>
JavaScript
var $tbody = $(' tbody');
var array = [];
$tbody.find('.event1').sort(function (a, b) {
var tda = $(a).find('.point').text();
var tdb = $(b).find('.point').text();
return tda - tdb;
}).each(function (idx, tr) {
array.push($(tr).children('td').not('[rowspan]').detach());
});
$.each(array, function (idx, obj) {
$(obj).appendTo($('.event1:eq(' + idx + ')'));
});
The JavaScript only applies to event1. You can simply modify it for arbitrary events.
Change the index as Mayank Pandey said. And..
Since your second column is number, you can just return their difference.
var $tbody = $('#caltbl tbody');
$tbody.find('tr').sort(function (a, b) {
var tda = parseInt($(a).find('td:eq(1)').text(), 10); // always use the base number
var tdb = parseInt($(b).find('td:eq(1)').text(), 10);
return tda - tdb;
}).appendTo($tbody);

How To Sum All Table Rows td (TotalPrice) using td id Jquery

I am adding values to table like:
Item,Quantity,Price,TotalPrice
Now there are multiple rows: How can i sum TotalPrice of all to get GrandTotal using Jquery.
Code:
$("#Product").append(" <tr><td id='clientname'>" +ClientName+ "</td> <td id='item'>"+ItemName+"</td> <td id='quantity'>"+Quantity+"</td> <td id='price'>"+Price+"</td> <td id='totalprice'>"+TotalPrice+"</td> <td> <a onClick='deleteRow(this);'>Delete</a> </td> </tr>");
Its possible when i insert new row data its show grand total in textbox/label,Like:
function TotalPriceCalc()
{
var lblTotalPrice = document.getElementById('lblTotalPrice');
lblTotalPrice.value = sum;
}
Here's an example that will sum whatever column index you provide.
$(function() {
$("#subtotal").html(sumColumn(4));
$("#total").html(sumColumn(5));
});
function sumColumn(index) {
var total = 0;
$("td:nth-child(" + index + ")").each(function() {
total += parseInt($(this).text(), 10) || 0;
});
return total;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table style="border-spacing: 10px;">
<tr>
<td>ClientName</td>
<td>ItemName</td>
<td>Quantity</td>
<td>12</td>
<td>34</td>
</tr>
<tr>
<td>ClientName</td>
<td>ItemName</td>
<td>Quantity</td>
<td>56</td>
<td>78</td>
</tr>
<tr>
<td>ClientName</td>
<td>ItemName</td>
<td>Quantity</td>
<td>90</td>
<td>12</td>
</tr>
<tr>
<td colspan="3">Totals</td>
<td id="subtotal"></td>
<td id="total"></td>
</tr>
</table>
After you use class= instead of id= .Cause ID MUST be unique. you need to loop through each row and find totalPrice
$(document).ready(function(){
var TotalValue = 0;
$("#Product tr").each(function(){
TotalValue += parseFloat($(this).find('.totalprice').text());
});
alert(TotalValue);
});
While you tagged Jquery .. This is a Jquery solution so please be sure to include Jquery
You should use classes, not IDs, to name repeated elements. So it should be:
...<td class="totalprice">'+TotalPrice+'</td>...
Then you can do
function TotalPriceCalc() {
var total = 0;
$(".totalprice").each(function() {
total += parseFloat($(this).text());
});
$("#lblTotalPrice").val(total);
}
Have look, this is our table
<table class="table table-bordered">
<thead>
<tr>
<th>1</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td id="loop">50</td>
</tr>
<tr>
<td>1</td>
<td id="loop">60</td>
</tr>
<tr>
<td>1</td>
<td id="loop">70</td>
</tr>
</tbody>
<tbody>
<tr>
<td class="text-right">Total</td>
<td></td>
</tr>
</tbody>
And this is loop to have sum of price
$(function() {
var TotalValue = 0;
$("tr #loop").each(function(index,value){
currentRow = parseFloat($(this).text());
TotalValue += currentRow
});
console.log(TotalValue);
});

Sort only few rows of table - jquery/ javascript

I want to sort only child tr's data and don't want to move parent tr. Only child tr's will move until next parent. I have a table like this :
<table>
<tr>
<th id="column1">Column 1</th>
<th id="column2">Column 2</th>
<th>Column 3</th>
</tr>
<tr class="parent">
<td>text</td>
<td>text</td>
<td>text</td>
</tr>
<tr class="child">
<td>96</td>
<td>102</td>
<td>121</td>
</tr>
<tr class="child">
<td>455</td>
<td>422</td>
<td>410</td>
</tr>
<tr class="child">
<td>212</td>
<td>430</td>
<td>203</td>
</tr>
<tr class="parent">
<td>text</td>
<td>text</td>
<td>text</td>
</tr>
<tr class="child">
<td>363</td>
<td>581</td>
<td>231</td>
</tr>
<tr class="child">
<td>632</td>
<td>115</td>
<td>212</td>
</tr>
</table>
Javascript code :
$('#column1, #column2')
.each(function(){
var th = $(this),
thIndex = th.index(),
inverse = false;
th.click(function() {
// sorting classes don't work here b/c this function gets called repeatedly - moved to afterRequest: function
table.find('tr.parent td').filter(function(){
return $(this).index() === thIndex;
}).sortElements(function(a, b){
return $.text([a]) > $.text([b]) ?
inverse ? 1 : -1
: inverse ? -1 : 1;
}, function(){
// parentNode is the element we want to move
return this.parentNode;
// this.parentNode
});
inverse = !inverse;
});
});
fiddle : demo
Wrap each "section" in its own <tbody />
<tbody>
<tr class="parent"><!-- ... --></tr>
<tr class="child"><!-- ... --></tr>
<tr class="child"><!-- ... --></tr>
<tr class="child"><!-- ... --></tr>
</tbody>
<tbody>
<tr class="parent"><!-- ... --></tr>
<tr class="child"><!-- ... --></tr>
<tr class="child"><!-- ... --></tr>
</tbody>
<!-- ... -->
And do the sorting on each of the <tbody />'s
$("tbody").each(function() {
$(this).find('tr:not(.parent) td') // ignore the "parent" row
.filter(function () {
return $(this).index() === thIndex;
}).sortElements(function (a, b) {
return $(a).text() > $(b).text() ? inverse ? -1 : 1 : inverse ? 1 : -1;
}, function () {
return this.parentNode;
});
});
Example

Categories