Home > database >  Why does my sortTable function not work correctly with decimal numbers?
Why does my sortTable function not work correctly with decimal numbers?

Time:04-23

The end goal of my chart is that it displays prices in ascending order (ex: $10.24, $12.44, $100.00).

But with my code, it puts the number 100.00 in second position but I don't know why... Does anyone have a solution? My code is in my JSFIDDLE

function sortTable(table, column, type) {
  var order = $(`${table} thead tr>th:eq('   column   ')`).data('order');
  order = order === 'ASC' ? 'DESC' : 'ASC';
  $(`${table} thead tr>th:eq('   column   ')`).data('order', order);

  $(`${table} tbody tr`).sort(function(a, b) {
    a = $(a).find('td:eq('   column   ')').text().trim();
    b = $(b).find('td:eq('   column   ')').text().trim();

    switch (type) {
      case 'text':
        return order === 'ASC' ? a.localeCompare(b) : b.localeCompare(a);
        break;
      case 'number':
        return order === 'ASC' ? a - b : b - a;
        break;
      case 'date':
        var dateFormat = function(dt) {
          [m, d, y] = dt.split('/');
          return [y, m - 1, d];
        }
        a = new Date(...dateFormat(a));
        b = new Date(...dateFormat(b));
        return order === 'ASC' ? a.getTime() - b.getTime() : b.getTime() - a.getTime();
        break;
    }
  }).appendTo(`${table} tbody`);
}

sortTable('#tableBidList', 1, 'text');
table {
  font-family: arial, sans-serif;
  border-collapse: collapse;
  width: 100%;
}

td,
th {
  border: 1px solid #dddddd;
  text-align: left;
  padding: 8px;
}

tr:nth-child(even) {
  background-color: #dddddd;
}

.d-none {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table >
  <thead>
    <tr>
      <th>
        <span data-key-translate="quote.vehicle">Name</span>
      </th>
      <th>
        <span data-key-translate="shaq.price">Price</span>
      </th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>A</td>
      <td  price="5 1024" data-price="10.24">
        <span  data-eur-value="10.24">10.24</span> <span >$</span>
      </td>
    </tr>
    <tr>
      <td>B</td>
      <td  price="6 10000" data-price="100.00">
        <span  data-eur-value="100.00">100.00</span> <span >$</span>
      </td>
    </tr>
    <tr>
      <td>C</td>
      <td  price="5 1244" data-price="12.44">
        <span  data-eur-value="12.44">12.44</span> <span >$</span>
      </td>
    </tr>
  </tbody>
</table>

CodePudding user response:

A lot is happening in the code provided. Instead, I will provide you with an alternative.

I tried my best to break the solution into small functions plus for each part I added comments in hopes to guide you.

I hope this is useful to you.

// We extract a value of type string or number. 
const cell = (row, index) => {
  let value = row.children[index].innerText || row.children[index].textContent;
  value = value.replace('$', '');  
  return (value === 'number') ?  value : value;
}

// We check if its a number
const isNumber = (value) => value !== '' && !isNaN(value);

// We check that both values to compare are numbers
const isComparingNumbers = (v1, v2) => isNumber(v1) && isNumber(v2); 

// We compare number vs. number or we compare string vs. string
const comparing = (v1, v2) => { 
  return isComparingNumbers(v1, v2) ? v1 - v2 : v1.toString().localeCompare(v2)
}

// We create a comparator that will compare based on the order provided at that index
const comparator = (index, order) => 
  (left, right) => (comparing)
    (cell(order ? left : right, index), 
     cell(order ? right : left, index));

// With the header selected, 
// 1. We obtain a reference to the table
// 2. We obtain a list of references of all the rows except the headers
// 3. We obtain the index by searching for the header
// 4. We perform the sorting of all rows (except the header)
//    Also, we invest the flag of the order each time we call this method.
//    As we sort, we change the table
const tableSorting = (event) => {
    const header = event.currentTarget.header;
    const table = header.closest('table');
    const rowsExceptHeaders = table.querySelectorAll('tr:nth-child(n 2)');
    let index = Array.from(header.parentNode.children).indexOf(header);
    Array.from(rowsExceptHeaders)
        .sort(comparator(index, this.asc = !this.asc))
        .forEach(row => table.appendChild(row) );
};

// The main take care of selecting all the headers.
// For each header, we set that each header should listen for the click event.
// We also pass each header so it can be used by the tableSorting function.
const main = () => {
  const headers = document.querySelectorAll('th');
  headers.forEach(header => {
    header.addEventListener('click', (tableSorting))
    header.header = header;
  });
}

// We wait for all DOMs be loaded prior running the main method.
$(function() {
  main();
  let selector = 'table tr th span[data-key-translate="shaq.price"]'
  let elem = document.querySelector(selector);
  elem.click();

  /*
  let tables = document.querySelectorAll('.table');
  tables.forEach(table => {
    let headers = table.querySelectorAll('th');    
    headers.forEach(column => {
      let span = column.querySelector('span');
      let title = span.innerHTML;
      if (title == 'Price'){
        column.click();
      }
    });
  });
  */

});
table {
  font-family: arial, sans-serif;
  border-collapse: collapse;
  width: 100%;
}

td,
th {
  border: 1px solid #dddddd;
  text-align: left;
  padding: 8px;
}

tr:nth-child(even) {
  background-color: #dddddd;
}

.d-none {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table >
        <tr>
            <th>
                <span data-key-translate="quote.vehicle">Name</span>
            </th>
            <th>
                <span data-key-translate="shaq.price">Price</span>
            </th>
        </tr>
      <tr>
        <td>A</td>
        <td  price="5 1024" data-price="10.24">
          <span  data-eur-value="10.24">10.24</span> <span >$</span>
        </td>
      </tr>
      <tr>
        <td>B</td>
        <td  price="6 10000" data-price="100.00">
          <span  data-eur-value="100.00">100.00</span> <span >$</span>
        </td>
      </tr>
      <tr>
        <td>C</td>
        <td  price="5 1244" data-price="12.44">
          <span  data-eur-value="12.44">12.44</span> <span >$</span>
        </td>
      </tr>
</table>

  • Related