Sorting function in javascript - javascript

Hi I have html structure with table. I want to sort td according to their value. I trying it but cant find the logic to make it happen. My function is
<head>
<script type="text/javascript">
function sorting(){
var sortvalue= document.getElementsByTagName('td');
for(i=0; i<sortvalue.length;i++){
var val= sortvalue[i].value
}
}
</script>
</head>
<body>
<table width="500" border="0" cellspacing="0" cellpadding="0">
<tr>
<td>5</td>
</tr>
<tr>
<td>3</td>
</tr>
<tr>
<td>2</td>
</tr>
<tr>
<td>4</td>
</tr>
<tr>
<td>1</td>
</tr>
</table>
click to sort
</body>

If you plan to do more than just organize those numbers: those saying you should use a plugin are correct. It'd take more effort than it's worth to try to make your own table sorter.
If all you want to do is sort those numbers (small to large):
function sorting() {
td = document.getElementsByTagName("td");
sorted = [];
for (x = 0; x < td.length; x++)
sorted[x] = Number(td[x].innerHTML);
sorted.sort();
for (x = 0; x < sorted.length; x++)
td[x].innerHTML = sorted[x];
}
Largest to smallest:
function sorting() {
td = document.getElementsByTagName("td");
sorted = [];
for (x = 0; x < td.length; x++)
sorted[x] = Number(td[x].innerHTML);
sorted.sort().reverse();
for (x = 0; x < sorted.length; x++)
td[x].innerHTML = sorted[x];
}

Assuming that you're putting the script under your link, or adding it on domready:
function sorting(){
var tbl = document.getElementsByTagName('table')[0];
var store = [];
for(var i=0, len=tbl.rows.length;i<len; i++){
var row = tbl.rows[i];
var sortnr = parseFloat(row.cells[0].textContent || row.cells[0].innerText);
if(!isNaN(sortnr)) store.push([sortnr, row]);
}
store.sort(function(x,y){
return x[0] - y[0];
});
for(var i=0, len=store.length; i<len; i++){
tbl.appendChild(store[i][1]);
}
store = null;
}
link here: http://jsfiddle.net/UMjDb/

For your example you can make an array of the cell data from the node list and sort that array, and then replace the cells data with the sorted data. Simpler than moving elements.
<head>
<script type= "text/javascript">
function sorting(){
var T= [], tds= document.getElementsByTagName('td');
for(var i= 0;i<tds.length;i++){
T.push(tds[i].firstChild.data);
}
T.sort(function(a, b){
return a-b
});
for(var i= 0;i<tds.length;i++){
tds[i].replaceChild(document.createTextNode(T[i]), tds[i].firstChild);
}
}
</script>
</head>
<body>
<table width= "500" border= "0" cellspacing= "0" cellpadding= "0">
<tr>
<td>5</td>
</tr>
<tr>
<td>3</td>
</tr>
<tr>
<td>2</td>
</tr>
<tr>
<td>4</td>
</tr>
<tr>
<td>1</td>
</tr>
</table>
click to sort
</body>

i giving a jquery solution, hope this post helps you.
var tdData = Array();
$(document).ready(function(){
$('td').each(function(i){
tdData [i] = $(this).text();
});
});
function sorting(){
var sortedData = tdData.sort();
$('td').each(function(i){
$(this).text(sortedData[i]);
} );
}
complete solution: link

step 1: find all td's
step 2: fetch their values
step 3: sort them on their values
step 4: put them back into their parent in the correct order. This can simply be done with an $(parent).html("").append(sortedNodes) (if you use jQuery that is).
As #FelixKling points out below, the .html("") is not strictly necessary other than for code clarity since "If you have nodes that already exist in the tree, then .append will remove them first from their current location and add them to the new parent"

You need to re-organise the table.
The simplest approach would be to use a plugin like this one for jQuery
You need to modify the DOM, they would be different way to do that, like grabbing all the data, removing all the rows and adding them back in the right order.
It could be improved better using detach and reattaching.

Related

Change the background colour of a table cell if the content is not the same as another cell

I have an output.php. It creates an html table with 3 columns: Question number, Correct Answer, Student Answer. Works just as I want it to.
Now what I would like is to paint the cells with incorrect student answers red. I think Javascript is the best way to do this, rather than php.
Looking at other answers here, I was hoping this might do the job, but, alas ...
Can you please help me get this working?
<script type="text/javascript" >
function paint_cells() {
var tds = document.querySelectorAll('tbody td'), i;
for(i = 0; i < tds.length; i += 3) {
if(tds[i+1].textContent != tds[i+2].textContent){
tds[i+2].bgColor = "red";
}
}
</script>
You code working good! I think your problem occurs that your js run before the dom already loaded. You have multiple opportunities to fix this. 1) you can add your script to the bottom inside the body tag. 2) work with onload event. https://developer.mozilla.org/de/docs/Web/API/GlobalEventHandlers/onload
Note Maybe you forgot to call the function? paint_cells()
function paint_cells() {
var tds = document.querySelectorAll('tbody td'), i;
for(i = 0; i < tds.length; i += 3) {
if(tds[i+1].textContent != tds[i+2].textContent){
tds[i+2].bgColor = "red";
}
}
}
paint_cells();
<table border="1">
<thead>
<tr>
<th>Question</th>
<th>Correct Answer</th>
<th>Students Answer</th>
</tr>
</thead>
<tbody>
<tr>
<td>abc</td>
<td>right</td>
<td>false</td>
</tr>
<tr>
<td>abc</td>
<td>right</td>
<td>right</td>
</tr>
<tr>
<td>abc</td>
<td>right</td>
<td>false</td>
</tr>
</tbody>
</table>
I think you need to wait for page DOM loaded, try below. And it also depends on how and when the table in your page is generated, if it doesn't work, please provide more details.
<script type="text/javascript" >
window.addEventListener('DOMContentLoaded', (event) => {
var tds = document.querySelectorAll('tbody td'), i;
for(i = 0; i < tds.length; i += 3) {
if(tds[i+1].textContent != tds[i+2].textContent){
tds[i+2].bgColor = "red";
}
}
});
</script>

Getting a checkbox from a table field

Good afternoon, below is the code in it I am getting fields from my table. The 0 field contains a checkbox, how can I find out if it is checked or not(true or false)? You need to change this line: console.log (td.item (f));
var table = document.getElementsByClassName("table-sm");
for (var i = 0; i < table.length; i++) {
var tr = table.item(i).getElementsByTagName("tr");
for (var j = 0; j < tr.length; j++) {
var trr = tr.item(j);
var td = tr.item(j).getElementsByTagName("td");
for (var f = 0; f < td.length; f++) {
if (f === 0) console.log(td.item(f));
console.log(td.item(f).innerText);
}
}
}
Firstly, please learn about JavaScript Table API is much better than just making complex for-loops.
Next time please add full code (HTML/JavaScript) so people can help you.
Now let's fix your code.
Suppose we have this table
<table class="table-sm" id="myTable">
<thead>
<tr>
<th>Checkbox</th>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" name="selected[]" checked /></td>
<td>1</td>
<td>Mohammed</td>
</tr>
<tr>
<td><input type="checkbox" name="selected[]" /></td>
<td>2</td>
<td>Ali</td>
</tr>
</tbody>
</table>
and we want to get the first item of each rows, and check whether the checkbox is checked or not.
We can do it easly using JS Table APIs.
Get the table by it's ID.
var table = document.getElementById("myTable");
Get the table rows
I use Array.from() to convert HTMLCollection to normal array, so I can use Array APIs (Like .forEach).
var rows = Array.from(table.rows);
Loop into table rows, and get cells of each row.
rows.map((row) => {
var cells = Array.from(row.cells);
// TODO add logic here.
});
Get the firstChild of first cell.
rows.map((row) => {
var cells = Array.from(row.cells);
if (Array.isArray(cells) && cells.length > 0) {
var firstChild = cells[0].firstChild;
console.log(firstChild.checked);
}
});
Live Example

Javascript - Add new row to an HTML table that sums columns

With JavaScript, how can I add a new row to an HTML table that sums the values following the 2nd row.
Here's an example of what the above depicts:
Expected outcome:
Here is the html markup:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<!DOCTYPE html>
<html>
<body>
<table border="1" style="width:100%">
<tr>
<td>Branch</td>
<td>Division</td>
<td>TallyA</td>
<td>TallyB</td>
<td>TallyC</td>
</tr>
<tr>
<td>Alpha</td>
<td>A101</td>
<td>6</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>Bravo</td>
<td>B102</td>
<td>16</td>
<td>8</td>
<td>10</td>
</tr>
<tr>
<td>Charlie</td>
<td>C103</td>
<td>11</td>
<td>17</td>
<td>21</td>
</tr>
</table>
</body>
</html>
</body>
</html>
Here is my solution. It may look verbose, but that's necessary with the complexity of this task.
First, I referenced the button and table elements. To prevent repeated clicks that will add more rows, and destroy the code, I created a boolean variable that checks whether the rows have already been summed. The code only runs the first time inside the if(!summedItems) conditional.
I then created new td elements for all five columns in the table and created text nodes for all but the division one.
I then created selectors and this is where it got tricky. The first row does not contain numerical value, so I had to query all rows from the second further. I did that with tr:nth-child(n+2).
I then need to find the third cell in each of these rows. The descendant or child selectors can be used for this. The full selector is tr:nth-child(n+2) td:nth-child(3). Repeat that for the next two, only increment the values inside td:nth-child.
Since we need to iterate through all these values, I created three separate arrays to store the values inside the third, fourth and fifth columns respectively. It's important to note that these values are of type string and they need to be converted to integers. To do that simply add a + sign before the string. Iterating over the number of elements in each query, I populated the arrays.
Now we need to add up all of these items, and we can do that with the reduce method.
Now add the textnodes to the cells, the cells to the row and finally the row to the table. Finally, set the summedItems variable to true to prevent crazy behavior.
var button = document.getElementById("total-items");
var table = document.getElementById("my-table");
var summedItems = false;
function sumItems() {
if (!summedItems) {
var row = document.createElement("tr");
var branch = document.createElement("td");
var division = document.createElement("td");
var tallyA = document.createElement("td");
var tallyB = document.createElement("td");
var tallyC = document.createElement("td");
var branchText = document.createTextNode("Total");
var sumA = document.querySelectorAll("tr:nth-child(n+2) td:nth-child(3)");
var sumB = document.querySelectorAll("tr:nth-child(n+2) td:nth-child(4)");
var sumC = document.querySelectorAll("tr:nth-child(n+2) td:nth-child(5)");
var aSums = [], bSums = [], cSums = [];
for (var i = 0; i < sumA.length; i++) {
aSums.push(+(sumA[i].innerHTML));
}
for (var i = 0; i < sumB.length; i++) {
bSums.push(+(sumB[i].innerHTML));
}
for (var i = 0; i < sumC.length; i++) {
cSums.push(+(sumC[i].innerHTML));
}
aSums = aSums.reduce((a,b) => a + b)
bSums = bSums.reduce((a,b) => a + b)
cSums = cSums.reduce((a,b) => a + b)
var tallyAText = document.createTextNode(aSums);
var tallyBText = document.createTextNode(bSums);
var tallyCText = document.createTextNode(cSums);
branch.appendChild(branchText);
tallyA.appendChild(tallyAText);
tallyB.appendChild(tallyBText);
tallyC.appendChild(tallyCText);
[branch, division, tallyA, tallyB, tallyC].forEach((e) => row.appendChild(e)
)
table.appendChild(row);
summedItems = true;
}
}
button.addEventListener("click", function() {
sumItems();
});
<table id="my-table" border="1" style="width:100%">
<tr>
<td>Branch</td>
<td>Division</td>
<td>TallyA</td>
<td>TallyB</td>
<td>TallyC</td>
</tr>
<tr>
<td>Alpha</td>
<td>A101</td>
<td>6</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>Bravo</td>
<td>B102</td>
<td>16</td>
<td>8</td>
<td>10</td>
</tr>
<tr>
<td>Charlie</td>
<td>C103</td>
<td>11</td>
<td>17</td>
<td>21</td>
</tr>
</table>
<button id="total-items">Total Items</button>
with jQuery:
$("table").each(function() {
var $table = $(this);
$row = $("<tr>")
$row.append("<td>Totale</td>")
var sums = [];
$table.find("tr").each(function(){
var index = 0;
$(this).find("td").each(function() {
if (!sums[index]) sums[index] = 0;
sums[index] += parseInt($(this).html());
index++;
})
})
for(var i=1;i<sums.length;i++) {
var el = sums[i];
if (isNaN(el)) el = "";
$row.append("<td>"+el+"</td>")
}
$table.append($row)
})
jsFiddle

for each table push to array

I'm a beginner with code,
I'm trying to run on this table and get the text from each .winner class and push it to an Array, so instead of getting:
["aa","aa","dd"]
I'm getting
["aaaadd","aaaadd","aaaadd"]
$(document).ready(function(){
var arr = [];
var winner = $('.winner').text() ;
for ( i = 0; i < $('table').length ; i++ ) {
arr.push(winner);
}
console.log(arr);
});
HTML:
<table>
<tr>
<td>#</td>
<td class="winner">aa</td>
<td>bb</td>
<td>cc</td>
<td>dd</td>
</tr>
</table>
<table>
<tr>
<td>#</td>
<td class="winner">aa</td>
<td>bb</td>
<td>cc</td>
<td>dd</td>
</tr>
</table>
<table>
<tr>
<td>#</td>
<td class="winner">dd</td>
<td>cc</td>
<td>bb</td>
<td>aa</td>
</tr>
</table>
I guess something is wrong with my for loop
var arr = [];
$('table .winner').each(function () {
arr.push($(this).text());
})
Example
or version without class .winner
$('table').each(function () {
arr.push($(this).find('tr').eq(0).find('td').eq(1).text());
});
Example
$('table .winner') - returns 3 td's with class .winner
$(this).text() - get text from current element.
In your example $('.winner').text() returns text "aaaadd", then you get $('table').length (will be 3) and three times push the same text to arr
The sentence
var winner = $('.winner')
will give you an array of objects, so you need to loop each of them and call text() method for each one.
With this:
var winner = $('.winner').text();
You are getting a combined texts from all the td elements marked as winner (see docs here).
Then, for each table, to push this value to the array:
for ( i = 0; i < $('table').length ; i++ ) {
arr.push(winner);
}
This is actually not necessary.
What you want is probably:
var winners = $('.winner');
for (var i = 0; i < winners.length(); ++i) {
arr.push(winners.eq(i).text());
}

Dynamically delete multiple columns in html table

I am trying to delete multiple columns from html table using javascript.
The logic it is using is that it searches in top row for tag "" and then deletes that column.
The problem is if only one cell in top row is having '', then it deletes that columns fine, but if there are multiple columns it throws error.
Here is my code
<!DOCTYPE html>
<html>
<body>
<table style="width:100%" border='1' id='Just_for_california'>
<tr>
<td><span></span></td>
<td>S</td>
<td><span></span></td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>80</td>
</tr>
</table>
</body>
<script>
var dataTable_length = document.getElementById('Just_for_california').rows[0].cells.length;
var count_rows = document.getElementById('Just_for_california').rows.length;
var column_array = [];
for(var i=0; i<dataTable_length; i++)
{
var str = document.getElementById("Just_for_california").rows[0].cells[i].innerHTML;
if(str.search("<span></span>") != -1)
{
column_array.push(i);
}
}
var len = column_array.length;
for(var i=count_rows-1 ; i>=0;i--)
{
rows_number = document.getElementById('Just_for_california').rows[i];
console.log("row_number:"+i);
for(var j=0; j<len;j++)
{
rows_number.deleteCell(column_array[j]);
}
}
</script>
</html>
It happens because you calculate indexes incorrectly when you delete cells. I refactored you code (making it clearer) and it seems to work now:
var table = document.getElementById('Just_for_california'),
rows = table.rows;
for (var i = 0; i < rows[0].cells.length; i++) {
var str = rows[0].cells[i].innerHTML;
if (str.search("<span></span>") != -1) {
for (var j = 0; j < rows.length; j++) {
rows[j].deleteCell(i);
}
}
}
The problem is that you are trying to remove cells "horizontally" in the row. So say you want to delete cells at indexes 1 and 3 and there are 4 columns in the table. When you delete the first cell 1 it works fine. However then you move to the right and try to remove cell at index 3. This fails because since you have already removed cell 1, there is no cell with index 3 anymore. The maximum index now is 2. Hence the error.
In my improved code I'm removing columns "vertically", so such an issue can't happen.
Demo: http://jsfiddle.net/t2q60aag/

Categories

Resources