| 980 | }); |
| 981 | |
| 982 | function sortTable(columnIndex, direction) { |
| 983 | const rows = Array.from(resultsBody.querySelectorAll('tr')); |
| 984 | const rowPairs = []; |
| 985 | |
| 986 | for (let i = 0; i < rows.length; i++) { |
| 987 | if (!rows[i].classList.contains('details-row')) { |
| 988 | const detail = (i + 1 < rows.length && rows[i + 1].classList.contains('details-row')) ? rows[i + 1] : null; |
| 989 | rowPairs.push([rows[i], detail]); |
| 990 | } |
| 991 | } |
| 992 | |
| 993 | rowPairs.sort((a, b) => { |
| 994 | const cellA = a[0].querySelectorAll('td')[columnIndex]; |
| 995 | const cellB = b[0].querySelectorAll('td')[columnIndex]; |
| 996 | if (!cellA || !cellB) return 0; |
| 997 | |
| 998 | let valA = cellA.textContent.trim(); |
| 999 | let valB = cellB.textContent.trim(); |
| 1000 | valA = valA === 'N/A' ? Infinity : parseFloat(valA) || 0; |
| 1001 | valB = valB === 'N/A' ? Infinity : parseFloat(valB) || 0; |
| 1002 | |
| 1003 | return direction === 'asc' ? valA - valB : valB - valA; |
| 1004 | }); |
| 1005 | |
| 1006 | for (const pair of rowPairs) { |
| 1007 | resultsBody.appendChild(pair[0]); |
| 1008 | if (pair[1]) resultsBody.appendChild(pair[1]); |
| 1009 | } |
| 1010 | } |
| 1011 | |
| 1012 | // ─── Chart ─────────────────────────────────────────────────────────────────── |
| 1013 | |