Reputation: 11
I am not at all an HTML expert. I program microcontrollers and got off onto a tangent.
I created an html doc to show a table of microcontroller registers, register addresses and register descriptions. I created a table with 3 columns - and about 120 rows. Some of the register addresses are bit addressable - if their addresses end in 0 or 8.
I wanted to highlight these 'special' register addresses - by showing them in red. So, in the table cells with a register address ending in 0 or 8, I use "" and "" to surround the address value.
My table has 3 columns, Register, Address, and Description. Then one row might look like
"ACC 0xE0 Accumulator".
I got my table all done and it looks great. Then I got the idea that I want to be able to sort the table on any column. For example, if I click on "Address" I want the table to re-display and sort by the values in that column.
I searched, and found a way to do it. It works by having a "sort" button - click on that and it re-displays sort on the first column values. I implemented a simple version of it and got it working. I then changed it to instead sort on the second column when the "sort" button was clicked.
That didn't exactly work .... because of all those "" whatevers.
The example I copied from his here:
https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_sort_table
Is there anything 'simple' I can do to use this method - but still be able have certain entries in the Address column be shown red ?
I should probably stick to programming microcontrollers, but I like a challenge.
Upvotes: 1
Views: 8338
Reputation: 22320
sample code for sort on a selected column,
that's free...
const
myButtonSort = document.querySelector('#my-button-sort')
, colSelector = document.querySelector('#sel-col')
, myTable_tBody = document.querySelector('#my-table > tbody')
;
myButtonSort.onclick = _ =>
{
let col = parseInt(colSelector.value );
[...myTable_tBody.querySelectorAll('tr')]
.map(row=>({row, str:row.cells[col].textContent }))
.sort((a,b)=>a.str.localeCompare(b.str))
.forEach(el=>
{
myTable_tBody.appendChild(el.row)
})
}
table {
border-collapse : collapse;
margin : 2em 1em;
}
td,th {
padding : .2em .8em;
border : 1px solid darkblue;
}
thead {
background : lightseagreen ;
}
<select id="sel-col">
<option value="0">column x</option>
<option value="1">column y</option>
</select>
<button id="my-button-sort">sort</button>
<table id="my-table">
<thead>
<tr> <th>x</th> <th>y</th> </tr>
</thead>
<tbody>
<tr> <td>aa</td><td> 1 </td></tr>
<tr> <td>zz</td><td> 2 </td></tr>
<tr> <td>ee</td><td> 3 </td></tr>
<tr> <td>cc</td><td> 4 </td></tr>
</tbody>
</table>
Ascending and descending sort example:
const myArray =
[ { worth: '100', name: 'jessca', reason: 'money', email: '[email protected]', number: '4456', instagram: 'hvg_ujh', tiktok: 'hhgh.thg' }
, { worth: '265', name: 'e', reason: 'money', email: '[email protected]', number: '3456', instagram: 'hvg_ujh', tiktok: 'hhgh.thg' }
, { worth: '6000', name: 'ssica', reason: 'sex', email: '[email protected]', number: '0456', instagram: 'hvg_ujh', tiktok: 'hhgh.thg' }
, { worth: '855', name: 'sica', reason: 'sex', email: '[email protected]', number: '9456', instagram: 'hvg_ujh', tiktok: 'hhgh.thg' }
, { worth: '8679', name: 'ica', reason: 'sex', email: '[email protected]', number: '0756', instagram: 'hvg_ujh', tiktok: 'hhgh.thg' }
, { worth: '1', name: 'ca', reason: 'money', email: '[email protected]', number: '14856', instagram: 'hvg_ujh', tiktok: 'hhgh.thg' }
]
const
t_Head = document.querySelector('#myTable thead')
, t_Head_THs = document.querySelectorAll('#myTable thead tr th')
, th_list = [...t_Head_THs].map( TH => TH.dataset.column)
, t_Body = document.querySelector('#myTable tbody')
, sortOrder = [ 'none' ,'asc', 'desc' ]
, sortType = { worth: 'num', name:'str', reason:'str', email:'str', number:'num', instagram:'str', tiktok:'str' }
, sortProcess =
{ 'asc:num' : (a,b) => +a.str - +b.str
, 'desc:num' : (a,b) => +b.str - +a.str
, 'asc:str' : (a,b) => a.str.localeCompare(b.str)
, 'desc:str' : (a,b) => b.str.localeCompare(a.str)
};
myArray.forEach( row =>
{
let TR = t_Body.insertRow()
for (col of th_list)
TR.insertCell().textContent = row[col]
})
t_Head.onclick = ({target}) =>
{
if (!target.matches('th')) return
let
dataOrder = sortOrder[(sortOrder.indexOf(target.dataset.order) +1 )% sortOrder.length]
, dataType = sortType[target.dataset.column]
;
t_Head_THs.forEach( TH => { TH.dataset.order = (TH===target) ? dataOrder : 'none' })
if (dataOrder !== 'none')
{
[...t_Body.querySelectorAll('tr')]
.map ( row => ({row, str:row.cells[target.cellIndex].textContent }))
.sort ( sortProcess[`${dataOrder}:${dataType}`])
.forEach ( elm => t_Body.appendChild(elm.row ))
}
}
body {
font-family : Arial, Helvetica, sans-serif;
font-size : 16px;
}
table {
border-collapse : separate;
border-spacing : 1px;
background-color : darkblue;
margin : 1em;
}
th, td {
border : none;
background : whitesmoke;
padding : .3em .4em;
}
th {
background-color : #76ced1;
white-space : nowrap;
cursor : pointer;
}
th::before {
content : attr(data-column) ' ';
text-transform : capitalize;
}
th[data-order=asc]::after { content : '\25B2'; }
th[data-order=desc]::after { content : '\25BC'; }
th[data-order=none]::after { content : '\25B2'; color:transparent; } /* get the same width */
<table id="myTable">
<thead>
<tr>
<th data-column="worth" data-order="none"></th>
<th data-column="name" data-order="none"></th>
<th data-column="reason" data-order="none"></th>
<th data-column="email" data-order="none"></th>
<th data-column="number" data-order="none"></th>
<th data-column="instagram" data-order="none"></th>
<th data-column="tiktok" data-order="none"></th>
</tr>
</thead>
<tbody></tbody>
</table>
Upvotes: 3
Reputation: 10201
This might get you started:
const table = document.getElementById("test"),
th = test.querySelectorAll("th"),
sortDefault = 0, //default sorted column number
orderDefault = 0; //default order: 0 = ascending, 1 = descending
table.dataset.sort = sortDefault;
table.dataset.order = orderDefault;
/* add click listeners on table headers */
for(let i = 0; i < th.length; i++)
{
th[i].addEventListener("click", e =>
{
/* if this column was sorted, change it's order */
if (+table.dataset.sort == e.target.cellIndex)
table.dataset.order = +table.dataset.order ? 0 : 1;
/* tell table which column is currently sorted */
table.dataset.sort = e.target.cellIndex;
sortColumn();
});
}
populateTable(); //fill table with random data
sortColumn(); //initial sort of the table
function sortColumn()
{
const rows = Array.from(table.children);
rows.splice(0, 1); //remove header from the list
rows.sort((a, b) =>
{
a = a.children[table.dataset.sort].textContent;
b = b.children[table.dataset.sort].textContent;
a = a.replace(/\W/g, ""); //remove non alphanumerical characters
b = b.replace(/\W/g, ""); //remove non alphanumerical characters
a = a.replace(/0x[a-fA-F0-9]+/, n => Number(n)); //convert 0xHEX to decimal
b = b.replace(/0x[a-fA-F0-9]+/, n => Number(n)); //convert 0xHEX to decimal
return a.localeCompare(b, undefined, {numeric: true, sensitivity: 'base'})
});
if (+table.dataset.order)
rows.reverse();
for(let i = 0; i < rows.length; i++)
{
table.appendChild(rows[i]);
}
}
function populateTable()
{
for(let i = 0, _tr = document.createElement("tr"), _td = document.createElement("td"); i < 10; i++)
{
const tr = _tr.cloneNode(true);
let td = _td.cloneNode(true);
td.textContent = "reg " + rand(0, 199);
tr.appendChild(td);
td = _td.cloneNode(true);
td.textContent = "address 0x" + rand(0, 255).toString(16);
if (rand(0,1))
td.textContent = td.textContent.replace(/ (.*)/, ' "$1"');
tr.appendChild(td);
td = _td.cloneNode(true);
td.textContent = "desc " + rand(0, 99999).toString(16);
tr.appendChild(td);
table.appendChild(tr);
}
function rand(min, max)
{
return Math.floor(Math.random() * (max - min + 1)) + min;
}
}
#test
{
border-collapse: collapse;
}
#test tr td
{
border: 1px solid black;
}
#test td
{
padding: 0.5em 1em;
}
#test th
{
user-select: none;
cursor: pointer;
}
#test th:after
{
visibility: hidden;
}
#test[data-order="0"] th:after
{
content: "▲";
}
#test[data-order="1"] th:after
{
content: "▼";
}
#test[data-sort="0"] th:nth-child(1):after,
#test[data-sort="1"] th:nth-child(2):after,
#test[data-sort="2"] th:nth-child(3):after
{
visibility: visible;
}
<table id="test">
<tr>
<th>Register</th>
<th>Address</th>
<th>Description</th>
</tr>
</table>
Upvotes: 1