1

I'm trying to sort the table that contains a mix of numbers and alphabet separately per row. How can I sort the inventory volume below

ID Name Inventory Volume
1 Rachel Data is not enough
2 Ross 100
3 Monica 1
4 Connor Data is not enough
5 Dustin -5

into this sorting example is descending the letter should be the last.

ID Name Inventory Volume
1 Ross 100
2 Monica 1
3 Connor -5
4 Rachel Data is not enough
5 Connor Data is not enough

I tried to modify the following code below comparing the string but it seems I am doing something wrong

const getCellValue = (tr, idx) => tr.children[idx].innerText || tr.children[idx].textContent;

const comparer = (idx, asc) => (a, b) => ((v1, v2) => 
    v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) ? v1 - v2 : v1.toString().localeCompare(v2)
    )(getCellValue(asc ? a : b, idx), getCellValue(asc ? b : a, idx));

// do the work...
document.querySelectorAll('th').forEach(th => th.addEventListener('click', (() => {
    const table = th.closest('table');
    Array.from(table.querySelectorAll('tr:nth-child(n+2)'))
        .sort(comparer(Array.from(th.parentNode.children).indexOf(th), this.asc = !this.asc))
        .forEach(tr => table.appendChild(tr) );
})));

Reference: Sorting HTML table with JavaScript

I also want the other columns to be sorted.

Could you please show the code on how I could achieve this sorting to modify the following code above? It should sort descending and ascending. Thanks

Christian
  • 21
  • 5

2 Answers2

0
  1. First get all the data into an array.
  2. Next remove the items which are to be put last and cannot be sorted numerically.
  3. Sort the list numerically and merge the removed items at the end.

function sortData(data, method) {
  let lessData = 'Data Not Enough'
  let lastItems = []
  let sortedList;
  if (method == 'descending') {
    sortedList = data.sort((a, b) => {
      return a - b
    })
  } else if (method == 'ascending') {
    sortedList = data.sort((a, b) => {
      return b - a
    })
  }
  for (let i = 0; i < sortedList.length; i++) {
    if (sortedList[i] == lessData) {
      let item = sortedList[i]
      sortedList.splice(i, 1)
      sortedList.push(item)
    }
  }
  sortedList = sortedList.concat(lastItems)
  return sortedList
}

const items = []
let count = 0
document.querySelectorAll('td').forEach((td) => {
  if (count != 0) {
    items.push(td.innerHTML)
  }
  count++
})

document.querySelectorAll('td')[0].addEventListener('click', () => {
  let arr;
  if (count % 2 == 0) {
    arr = sortData(items, 'descending')
  } else {
    arr = sortData(items, 'ascending')
  }
  count++
  let i = 1

  arr.forEach((e) => {
    document.querySelectorAll('td')[i].innerHTML = e
    i++
  })
})
<table>
  <thead>
    <tr>
      <td>Volume</td>
    </tr>
  </thead>
  <tr>
    <td>Data Not Enough</td>
  </tr>
  <tr>
    <td>-5</td>
  </tr>
  <tr>
    <td>1</td>
  </tr>
  <tr>
    <td>100</td>
  </tr>
  <tr>
    <td>Data Not Enough</td>
  </tr>
</table>
Keshav Bajaj
  • 863
  • 1
  • 5
  • 13
  • Is the data changing once the page has loaded? If not, this is the way and it uses eventlistsener. look closely. – Keshav Bajaj Jul 14 '21 at 04:09
  • This is my last answer - https://jsfiddle.net/7wnke5q2/ If this solves your problem please accept my answer. – Keshav Bajaj Jul 14 '21 at 06:21
  • Your sort is not returning the sort correctly please check still did not accept your answer https://jsfiddle.net/awsyxo20/ – Christian Jul 19 '21 at 07:42
0

Modified the answer of @Keshav Bejaj, it important to take note of the string, integer and decimal when comparing and going through the sort.

Here is the solution that worked for me:

    const removeFirstData = "Data is Not Enough";
    const removeSecondData = "No Data";
    const lastItems = [];
    let sortedList;
    if (method === "descending") {
        sortedList = data.sort((a, b) => ((typeof b === "number") - (typeof a === "number")) || (a > b ? 1 : -1));
    } else if (method === "ascending") {
        const nums = data.filter(n => typeof n === "number").reverse();
        const non_nums = data.filter(x => typeof x !== "number").sort();

        sortedList = [...nums, ...non_nums];
    }

    for (let i = 0; i < sortedList.length; i++) {
        if (sortedList[i] === removeFirstData || sortedList[i] === removeSecondData) {
            const item = sortedList[i];
            sortedList.splice(i, 1);
            sortedList.push(item);
        }
    }
    sortedList = sortedList.concat(lastItems);
    return sortedList;
}
Christian
  • 21
  • 5