Web Development

Add column sort to html table – JavaScript – SitePoint Forums


I used a js script to convert JSON data to an HTML table at https://communitychessclub.com/result.php.

convert json to table:

https://www.geeksforgeeks.org/how-to-convert-json-data-to-a-html-table-using-javascript-jquery/#approach-2-using-jsonstringify-method

It worked fine. But now I have to add a class = "order" to table thead tr th (using JS) to sort the columns… How can I do that in plain js?

I have this: <th>Country</th>
But I need this: <th class="order">Country</th>

<script> 
//Another compact but readable solution: It just requires adding the class .order to the <th> element of each column to be ordered

document.querySelectorAll('th.order').forEach(th_elem => {
 let asc=true
 const index = Array.from(th_elem.parentNode.children).indexOf(th_elem) 
 th_elem.addEventListener('click', (e) => { 
 const arr = [... th_elem.closest("table").querySelectorAll('tbody tr')]
 arr.sort( (a, b) => {
 const a_val = a.children[index].innerText
 const b_val = b.children[index].innerText 
 return (asc) ? a_val.localeCompare(b_val) : b_val.localeCompare(a_val)
 })
 arr.forEach(elem => { 
 th_elem.closest("table").querySelector("tbody").appendChild(elem)
 })
 asc = !asc
 })
})
</script>

Wern’t you using DataTables before?

Anyway…

let theader = document.createElement("th");

=>

let theader = document.createElement("th");
theader.classList.add("order");

Found a much simpler way with sortable.js as shown at:

https://communitychessclub.com/result.php

But the problem is that I want to hide the first column from the user, but still have it accessible in js.

So, how can I hide “YT_id” column, given the sortable.js script?

 <script> // JSON DATA

data = [ 
{"YT_id":'XmU4Xyl00hY', "title":"Don't Look Back", "author":'Boston'},
{"YT_id":'9wxI4KK9ZYo', "title":'Perfect day', "author":'Lou Reed'},
{"YT_id":'XFkzRNyygfk', "title":'Creep', "author":'Radiohead'},
{"YT_id":'RQsRkDobjSs', "title":'Swallow', "author":'United Strings of Europe'},
{"YT_id":'2oT0UAoe0eQ', "title":'Slave to Love', "author":'Roxy Music'}
];
 
 </script>

<script> // sortable.js
const sortable = function(data) {

 const table = document.createElement('table');
 const thead = document.createElement('thead');
 const tbody = document.createElement('tbody');
 const currentOrder = {};

 // Function to populate the tbody with the data
 const _populate = current => {
 const row = tbody.insertRow();

 row.innerHTML = Object
 .keys(current)
 .reduce((carry, key) =>
 carry + `<td>${current[key]}</td>`,
 ''
 );
 };

 // Create the thead from the object keys
 thead.innerHTML = '<tr>'+ 
 Object
 .keys(data[0])
 .reduce((carry, current) =>
 carry + `<th data-key="${current}">${current}</th>`,
 ``
 ) + 
 '</tr>';

 // Add an event listener to sort the data according
 // to the clicked th
 thead.addEventListener('click', function(event) {
 const key = event.target.dataset.key;
 const sorted = currentOrder[key]
 ? data = data.sort((a, b) => a[key] < b[key] ? 1 : -1)
 : data = data.sort((a, b) => a[key] > b[key] ? 1 : -1);

 currentOrder[key] = !currentOrder[key];
 tbody.innerHTML = '';
 sorted.forEach(_populate);
 });

 // Initialise and return the table
 data.forEach(_populate);
 table.appendChild(thead);
 table.appendChild(tbody);

 return table;
};
<script>
Also I need to call a function when user clicks on an entire <tbody> <tr>. Plus I have to pass the current  <tr> <td>
values to that function.

Probably using CSS to hide all td:nth-of-type(1) by disabling their visibility.

You’ve got a reference to the row:

and an example of how to attach a click event to an element already in your code:

I shall leave it to you to put the two together.

event.target inside the function will reference the row. That element has a .children property, which refers to all the children of that node (which, for a tr, should be all of it’s associated td’s.)

It kinda works …

[https://communitychessclub.com/result.php]
(https://communitychessclub.com/result.php)

<script> var table = sortable(data);
 document.getElementById('container').appendChild(table);

 var test = document.getElementById('container');
 var rows = container.getElementsByTagName('tr');

 for (var i = 0; i < rows.length; i++) {if (i == 0) { continue;}
 rows[i].addEventListener('click', function() {
 
 // Do something when a row is clicked
 S0 = this.cells[0].textContent;
 S1 = this.cells[1].textContent;
 S2 = this.cells[2].textContent;
 
//alert (S0); alert (S1); alert (S2);

console.log('YT_id : ' + S0);
console.log('title : ' + S1);
console.log('author : ' + S2);

window.location.href="https://www.youtube.com/watch?v=" + S0;
});
}
 
</script>

User can click on any youtube video listed in the table, and it will load just fine. But t if the user clicks on the thead th to sort the column, it sorts just fine, but then subsequent clicking on a youtube video listed in the table tr does nothing!

So I need to avoid adding a js listener to the thead tr.

I played around with the for loop, but I couldn’t get in to work properly.

Can you help?



Source

Related Articles

Back to top button