Home > Blockchain >  Javascript insensitive table sorting does not work when <a href=> is around td
Javascript insensitive table sorting does not work when <a href=> is around td

Time:02-18

I want to sort a table when user clicks on a table header. My code works well, everything gets sorted but only when there are no <a href=#> around <td>.

sorttable.js

function sortTable(n) {
  var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
  table = document.getElementById("data_table");
  switching = true;
  dir = "asc";
  while (switching) {
    switching = false;
    rows = table.rows;
    for (i = 1; i < (rows.length - 1); i  ) {
      shouldSwitch = false;
      x = rows[i].getElementsByTagName("TD")[n];
      y = rows[i   1].getElementsByTagName("TD")[n];
      if (dir == "asc") {
        if (x.innerHTML.toUpperCase() > y.innerHTML.toUpperCase()) {
          shouldSwitch = true;
          break;
        }
      } else if (dir == "desc") {
        if (x.innerHTML.toUpperCase() < y.innerHTML.toUpperCase()) {
          shouldSwitch = true;
          break;
        }
      }
    }
    if (shouldSwitch) {
      rows[i].parentNode.insertBefore(rows[i   1], rows[i]);
      switching = true;
      switchcount   ;
    } else {
      if (switchcount == 0 && dir == "asc") {
        dir = "desc";
        switching = true;
      }
    }
  }
}
<table  id="data_table">
  <thead>
<tr>
  <th onclick="sortTable(0)">Name</th>
  <th onclick="sortTable(1)">Number</th>
</tr>
  </thead>
  <tbody>
  <tr>
    <td><a href="/registrants/45">caregiver testing testing</a></td>
    <td>23</td>
  </tr>
  <tr>
    <td><a href="/registrants/72">aaaaaaa test GoodeE</a></td>
    <td>1</td>
  </tr>
  <tr>
    <td><a href="/registrants/74">bbbBBBbb GoodeX</a></td>
    <td>2</td>
  </tr>
  <tr>
    <td><a href="/registrants/76">EEEEeFFFFgggHH GoodeC</a></td>
    <td>-7</td>
  </tr>
  </tbody>
</table>

I'm JS newbie so no I'm not entirely sure what's going on with my code but I think that's the issue. How to cover such case?

CodePudding user response:

You can check if a <td> includes an <a>, and if so, replace the <td> with the <a>. Like this:

function sortTable(n) {
  var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
  table = document.getElementById("data_table");
  switching = true;
  dir = "asc";
  while (switching) {
    switching = false;
    rows = table.rows;
    for (i = 1; i < (rows.length - 1); i  ) {
      shouldSwitch = false;
      x = rows[i].getElementsByTagName("TD")[n];
      // new code starts
      x_a = x.getElementsByTagName("a")[0];
      if (x_a != undefined) {
        x = x_a;
      };
      // new code ends
      y = rows[i   1].getElementsByTagName("TD")[n];
      // new code starts
      y_a = y.getElementsByTagName("a")[0];
      if (y_a != undefined) {
        y = y_a;
      };
      // new code ends
      if (dir == "asc") {
        if (x.innerHTML.toUpperCase() > y.innerHTML.toUpperCase()) {
          shouldSwitch = true;
          break;
        }
      } else if (dir == "desc") {
        if (x.innerHTML.toUpperCase() < y.innerHTML.toUpperCase()) {
          shouldSwitch = true;
          break;
        }
      }
    }
    if (shouldSwitch) {
      rows[i].parentNode.insertBefore(rows[i   1], rows[i]);
      switching = true;
      switchcount   ;
    } else {
      if (switchcount == 0 && dir == "asc") {
        dir = "desc";
        switching = true;
      }
    }
  }
}
<table  id="data_table">
  <thead>
<tr>
  <th onclick="sortTable(0)">Name</th>
  <th onclick="sortTable(1)">Number</th>
</tr>
  </thead>
  <tbody>
  <tr>
    <td><a href="/registrants/45">caregiver testing testing</a></td>
    <td>23</td>
  </tr>
  <tr>
    <td><a href="/registrants/72">aaaaaaa test GoodeE</a></td>
    <td>1</td>
  </tr>
  <tr>
    <td><a href="/registrants/74">bbbBBBbb GoodeX</a></td>
    <td>2</td>
  </tr>
  <tr>
    <td><a href="/registrants/76">EEEEeFFFFgggHH GoodeC</a></td>
    <td>-7</td>
  </tr>
  </tbody>
</table>


Edit:

Come to think of it, it would be much simpler and safer to just replace innerHTML with textContent in the original code.

Like this:

function sortTable(n) {
  var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
  table = document.getElementById("data_table");
  switching = true;
  dir = "asc";
  while (switching) {
    switching = false;
    rows = table.rows;
    for (i = 1; i < (rows.length - 1); i  ) {
      shouldSwitch = false;
      x = rows[i].getElementsByTagName("TD")[n];
      y = rows[i   1].getElementsByTagName("TD")[n];
      if (dir == "asc") {
        if (x.textContent.toUpperCase() > y.textContent.toUpperCase()) {
          shouldSwitch = true;
          break;
        }
      } else if (dir == "desc") {
        if (x.textContent.toUpperCase() < y.textContent.toUpperCase()) {
          shouldSwitch = true;
          break;
        }
      }
    }
    if (shouldSwitch) {
      rows[i].parentNode.insertBefore(rows[i   1], rows[i]);
      switching = true;
      switchcount   ;
    } else {
      if (switchcount == 0 && dir == "asc") {
        dir = "desc";
        switching = true;
      }
    }
  }
}
<table  id="data_table">
  <thead>
<tr>
  <th onclick="sortTable(0)">Name</th>
  <th onclick="sortTable(1)">Number</th>
</tr>
  </thead>
  <tbody>
  <tr>
    <td><a href="/registrants/45">caregiver testing testing</a></td>
    <td>23</td>
  </tr>
  <tr>
    <td>aaaaaaa test GoodeE</td>
    <td>1</td>
  </tr>
  <tr>
    <td><a href="/registrants/74">bbbBBBbb GoodeX</a></td>
    <td>2</td>
  </tr>
  <tr>
    <td><a href="/registrants/76">EEEEeFFFFgggHH GoodeC</a></td>
    <td>-7</td>
  </tr>
  </tbody>
</table>

  • Related