JS表排序失败的铬

发布于 2025-01-28 18:17:17 字数 2139 浏览 3 评论 0原文

我正在一个网站上工作,该网站允许人们参加ERG划船者的在线竞赛。

我显示一个包含等级,姓名和其他字段的大表(600多行),我想允许访问者飞行(客户端JS)。
我设置了一个在Firefox上非常有效的函数,但在Chrome浏览器上根本不起作用。

我真的看不到我的代码中的哪个部分可以带来这个问题,这就是为什么我向您寻求帮助!

我的HTML代码看起来像:

<table>
  <thead>
    <tr>
      <th>Rank</th>
      <th>Name</th>
      <th>...</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>USER 1</td>
      <td>...</td>
    </tr>
  </tbody>
</table>

和我的JavaScript:

for (const table of document.getElementsByTagName('table')) {
  const headers = table.querySelectorAll('thead tr th');
  for (let i = 0; i < headers.length-1; i++) {
    headers[i].addEventListener('click', sortTable(i, table.id));
  }
}

function sortTable(n, tableId) {
  return () => {
    const table = document.getElementById(tableId);

    const newTable = document.createElement('table');
    newTable.className = table.className;
    newTable.id = table.id;

    const tbody = document.createElement('tbody');
    const thead = document.createElement('thead');

    const rows = Array.from(table.rows);
    thead.appendChild(rows.shift());
    const th = thead.getElementsByTagName('th');

    const dir = th[n].className == 'asc' ? 'desc' : 'asc';

    rows.sort((a, b) => {
      let x = a.getElementsByTagName('td')[n].innerText.toLowerCase();
      let y = b.getElementsByTagName('td')[n].innerText.toLowerCase();

      const compare = x.localeCompare(y, 'fr', { sensitivity: 'base', numeric: true });

      return ((dir == 'asc' && compare > 0) || (dir == 'desc' && compare < 0));
    })
      .forEach(row => tbody.appendChild(row));

    for (const header of th) {
      header.className = '';
    }

    th[n].className = dir;

    newTable.appendChild(thead);
    newTable.appendChild(tbody);

    table.parentNode.replaceChild(newTable, table);
  };
}

感谢您的帮助!

I am working on a website that allow people to participate in an online race on erg rowers.

I display a large table (600+ rows) containing rank, name and other fields, and I want to allow visitors to sort it on the fly (client-side JS).
I set up a function that works really well on Firefox, but it doesn't work at all on Chrome browsers.

I really don't see what part of my code can bring this problem, this is why I reach to you for some help !

My html code looks like:

<table>
  <thead>
    <tr>
      <th>Rank</th>
      <th>Name</th>
      <th>...</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>USER 1</td>
      <td>...</td>
    </tr>
  </tbody>
</table>

And my JavaScript:

for (const table of document.getElementsByTagName('table')) {
  const headers = table.querySelectorAll('thead tr th');
  for (let i = 0; i < headers.length-1; i++) {
    headers[i].addEventListener('click', sortTable(i, table.id));
  }
}

function sortTable(n, tableId) {
  return () => {
    const table = document.getElementById(tableId);

    const newTable = document.createElement('table');
    newTable.className = table.className;
    newTable.id = table.id;

    const tbody = document.createElement('tbody');
    const thead = document.createElement('thead');

    const rows = Array.from(table.rows);
    thead.appendChild(rows.shift());
    const th = thead.getElementsByTagName('th');

    const dir = th[n].className == 'asc' ? 'desc' : 'asc';

    rows.sort((a, b) => {
      let x = a.getElementsByTagName('td')[n].innerText.toLowerCase();
      let y = b.getElementsByTagName('td')[n].innerText.toLowerCase();

      const compare = x.localeCompare(y, 'fr', { sensitivity: 'base', numeric: true });

      return ((dir == 'asc' && compare > 0) || (dir == 'desc' && compare < 0));
    })
      .forEach(row => tbody.appendChild(row));

    for (const header of th) {
      header.className = '';
    }

    th[n].className = dir;

    newTable.appendChild(thead);
    newTable.appendChild(tbody);

    table.parentNode.replaceChild(newTable, table);
  };
}

Thanks for your help !

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦晓ヶ微光ヅ倾城 2025-02-04 18:17:17

您的比较函数传递给.sort()正在返回布尔值:

return ((dir == 'asc' && compare > 0) || (dir == 'desc' && compare < 0));

但是, .sort()方法期望此比较功能返回一个数字。我怀疑Firefox正在宽恕或为您做某种类型的转换。如果我将其更改为:

return ((dir == 'asc' && 0 + compare) || (dir == 'desc' && 0 - compare));

... 将按预期进行排序。

for (const table of document.getElementsByTagName('table')) {
  const headers = table.querySelectorAll('thead tr th');
  for (let i = 0; i < headers.length - 1; i++) {
    headers[i].addEventListener('click', sortTable(i, table.id));
  }
}

function sortTable(n, tableId) {
  return () => {
    const table = document.getElementById(tableId);

    const newTable = document.createElement('table');
    newTable.className = table.className;
    newTable.id = table.id;

    const tbody = document.createElement('tbody');
    const thead = document.createElement('thead');

    const rows = Array.from(table.rows);
    thead.appendChild(rows.shift());
    const th = thead.getElementsByTagName('th');

    const dir = th[n].className == 'asc' ? 'desc' : 'asc';

    rows.sort((a, b) => {
        let x = a.getElementsByTagName('td')[n].innerText.toLowerCase();
        let y = b.getElementsByTagName('td')[n].innerText.toLowerCase();

        const compare = x.localeCompare(y, 'fr', {
          sensitivity: 'base',
          numeric: true
        });

        return ((dir == 'asc' && 0 + compare) || (dir == 'desc' &&  0 - compare));
      })
      .forEach(row => tbody.appendChild(row));

    for (const header of th) {
      header.className = '';
    }

    th[n].className = dir;

    newTable.appendChild(thead);
    newTable.appendChild(tbody);

    table.parentNode.replaceChild(newTable, table);
  };
}
<table id="mytable">
  <thead>
    <tr>
      <th>Rank</th>
      <th>Name</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>USER 1</td>
    </tr>
    <tr>
      <td>3</td>
      <td>USER 3</td>
    </tr>
    <tr>
      <td>2</td>
      <td>USER 2</td>
    </tr>
    <tr>
      <td>4</td>
      <td>USER 4</td>
    </tr>
    <tr>
      <td>5</td>
      <td>USER 5</td>
    </tr>
    <tr>
      <td>6</td>
      <td>USER 6</td>
    </tr>
    <tr>
      <td>7</td>
      <td>USER 7</td>
    </tr>
    <tr>
      <td>8</td>
      <td>USER 8</td>
    </tr>
    <tr>
      <td>9</td>
      <td>USER 9</td>
    </tr>
    <tr>
      <td>10</td>
      <td>USER 10</td>
    </tr>
    <tr>
      <td>11</td>
      <td>USER 11</td>
    </tr>
    <tr>
      <td>12</td>
      <td>USER 12</td>
    </tr>
    <tr>
      <td>13</td>
      <td>USER 13</td>
    </tr>
    <tr>
      <td>14</td>
      <td>USER 14</td>
    </tr>
    <tr>
      <td>15</td>
      <td>USER 15</td>
    </tr>
    <tr>
      <td>16</td>
      <td>USER 16</td>
    </tr>
    <tr>
      <td>17</td>
      <td>USER 17</td>
    </tr>
    <tr>
      <td>18</td>
      <td>USER 18</td>
    </tr>
    <tr>
      <td>19</td>
      <td>USER 19</td>
    </tr>
    <tr>
      <td>20</td>
      <td>USER 20</td>
    </tr>
    <tr>
      <td>21</td>
      <td>USER 21</td>
    </tr>
    <tr>
      <td>22</td>
      <td>USER 22</td>
    </tr>
    <tr>
      <td>23</td>
      <td>USER 23</td>
    </tr>
    <tr>
      <td>24</td>
      <td>USER 24</td>
    </tr>
    <tr>
      <td>25</td>
      <td>USER 25</td>
    </tr>
    <tr>
      <td>26</td>
      <td>USER 26</td>
    </tr>
    <tr>
      <td>27</td>
      <td>USER 27</td>
    </tr>
    <tr>
      <td>28</td>
      <td>USER 28</td>
    </tr>
    <tr>
      <td>29</td>
      <td>USER 29</td>
    </tr>
    <tr>
      <td>30</td>
      <td>USER 30</td>
    </tr>
  </tbody>
</table>


(作为参考,这是原始版本,仅返回了布尔值,而排序根本不起作用):

for (const table of document.getElementsByTagName('table')) {
  const headers = table.querySelectorAll('thead tr th');
  for (let i = 0; i < headers.length - 1; i++) {
    headers[i].addEventListener('click', sortTable(i, table.id));
  }
}

function sortTable(n, tableId) {
  return () => {
    const table = document.getElementById(tableId);

    const newTable = document.createElement('table');
    newTable.className = table.className;
    newTable.id = table.id;

    const tbody = document.createElement('tbody');
    const thead = document.createElement('thead');

    const rows = Array.from(table.rows);
    thead.appendChild(rows.shift());
    const th = thead.getElementsByTagName('th');

    const dir = th[n].className == 'asc' ? 'desc' : 'asc';

    rows.sort((a, b) => {
        let x = a.getElementsByTagName('td')[n].innerText.toLowerCase();
        let y = b.getElementsByTagName('td')[n].innerText.toLowerCase();

        const compare = x.localeCompare(y, 'fr', {
          sensitivity: 'base',
          numeric: true
        });

        return ((dir == 'asc' && compare > 0) || (dir == 'desc' && compare < 0));
      })
      .forEach(row => tbody.appendChild(row));

    for (const header of th) {
      header.className = '';
    }

    th[n].className = dir;

    newTable.appendChild(thead);
    newTable.appendChild(tbody);

    table.parentNode.replaceChild(newTable, table);
  };
}
<table id="mytable">
  <thead>
    <tr>
      <th>Rank</th>
      <th>Name</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>USER 1</td>
    </tr>
    <tr>
      <td>3</td>
      <td>USER 3</td>
    </tr>
    <tr>
      <td>2</td>
      <td>USER 2</td>
    </tr>
    <tr>
      <td>4</td>
      <td>USER 4</td>
    </tr>
    <tr>
      <td>5</td>
      <td>USER 5</td>
    </tr>
    <tr>
      <td>6</td>
      <td>USER 6</td>
    </tr>
    <tr>
      <td>7</td>
      <td>USER 7</td>
    </tr>
    <tr>
      <td>8</td>
      <td>USER 8</td>
    </tr>
    <tr>
      <td>9</td>
      <td>USER 9</td>
    </tr>
    <tr>
      <td>10</td>
      <td>USER 10</td>
    </tr>
    <tr>
      <td>11</td>
      <td>USER 11</td>
    </tr>
    <tr>
      <td>12</td>
      <td>USER 12</td>
    </tr>
    <tr>
      <td>13</td>
      <td>USER 13</td>
    </tr>
    <tr>
      <td>14</td>
      <td>USER 14</td>
    </tr>
    <tr>
      <td>15</td>
      <td>USER 15</td>
    </tr>
    <tr>
      <td>16</td>
      <td>USER 16</td>
    </tr>
    <tr>
      <td>17</td>
      <td>USER 17</td>
    </tr>
    <tr>
      <td>18</td>
      <td>USER 18</td>
    </tr>
    <tr>
      <td>19</td>
      <td>USER 19</td>
    </tr>
    <tr>
      <td>20</td>
      <td>USER 20</td>
    </tr>
    <tr>
      <td>21</td>
      <td>USER 21</td>
    </tr>
    <tr>
      <td>22</td>
      <td>USER 22</td>
    </tr>
    <tr>
      <td>23</td>
      <td>USER 23</td>
    </tr>
    <tr>
      <td>24</td>
      <td>USER 24</td>
    </tr>
    <tr>
      <td>25</td>
      <td>USER 25</td>
    </tr>
    <tr>
      <td>26</td>
      <td>USER 26</td>
    </tr>
    <tr>
      <td>27</td>
      <td>USER 27</td>
    </tr>
    <tr>
      <td>28</td>
      <td>USER 28</td>
    </tr>
    <tr>
      <td>29</td>
      <td>USER 29</td>
    </tr>
    <tr>
      <td>30</td>
      <td>USER 30</td>
    </tr>
  </tbody>
</table>

Your comparison function passed to .sort() is returning a boolean:

return ((dir == 'asc' && compare > 0) || (dir == 'desc' && compare < 0));

However, the .sort() method expects this comparison function to return a number. I suspect that Firefox is being forgiving or doing some type conversion for you where Chrome is not. If I change it to:

return ((dir == 'asc' && 0 + compare) || (dir == 'desc' && 0 - compare));

...it will sort as expected.

for (const table of document.getElementsByTagName('table')) {
  const headers = table.querySelectorAll('thead tr th');
  for (let i = 0; i < headers.length - 1; i++) {
    headers[i].addEventListener('click', sortTable(i, table.id));
  }
}

function sortTable(n, tableId) {
  return () => {
    const table = document.getElementById(tableId);

    const newTable = document.createElement('table');
    newTable.className = table.className;
    newTable.id = table.id;

    const tbody = document.createElement('tbody');
    const thead = document.createElement('thead');

    const rows = Array.from(table.rows);
    thead.appendChild(rows.shift());
    const th = thead.getElementsByTagName('th');

    const dir = th[n].className == 'asc' ? 'desc' : 'asc';

    rows.sort((a, b) => {
        let x = a.getElementsByTagName('td')[n].innerText.toLowerCase();
        let y = b.getElementsByTagName('td')[n].innerText.toLowerCase();

        const compare = x.localeCompare(y, 'fr', {
          sensitivity: 'base',
          numeric: true
        });

        return ((dir == 'asc' && 0 + compare) || (dir == 'desc' &&  0 - compare));
      })
      .forEach(row => tbody.appendChild(row));

    for (const header of th) {
      header.className = '';
    }

    th[n].className = dir;

    newTable.appendChild(thead);
    newTable.appendChild(tbody);

    table.parentNode.replaceChild(newTable, table);
  };
}
<table id="mytable">
  <thead>
    <tr>
      <th>Rank</th>
      <th>Name</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>USER 1</td>
    </tr>
    <tr>
      <td>3</td>
      <td>USER 3</td>
    </tr>
    <tr>
      <td>2</td>
      <td>USER 2</td>
    </tr>
    <tr>
      <td>4</td>
      <td>USER 4</td>
    </tr>
    <tr>
      <td>5</td>
      <td>USER 5</td>
    </tr>
    <tr>
      <td>6</td>
      <td>USER 6</td>
    </tr>
    <tr>
      <td>7</td>
      <td>USER 7</td>
    </tr>
    <tr>
      <td>8</td>
      <td>USER 8</td>
    </tr>
    <tr>
      <td>9</td>
      <td>USER 9</td>
    </tr>
    <tr>
      <td>10</td>
      <td>USER 10</td>
    </tr>
    <tr>
      <td>11</td>
      <td>USER 11</td>
    </tr>
    <tr>
      <td>12</td>
      <td>USER 12</td>
    </tr>
    <tr>
      <td>13</td>
      <td>USER 13</td>
    </tr>
    <tr>
      <td>14</td>
      <td>USER 14</td>
    </tr>
    <tr>
      <td>15</td>
      <td>USER 15</td>
    </tr>
    <tr>
      <td>16</td>
      <td>USER 16</td>
    </tr>
    <tr>
      <td>17</td>
      <td>USER 17</td>
    </tr>
    <tr>
      <td>18</td>
      <td>USER 18</td>
    </tr>
    <tr>
      <td>19</td>
      <td>USER 19</td>
    </tr>
    <tr>
      <td>20</td>
      <td>USER 20</td>
    </tr>
    <tr>
      <td>21</td>
      <td>USER 21</td>
    </tr>
    <tr>
      <td>22</td>
      <td>USER 22</td>
    </tr>
    <tr>
      <td>23</td>
      <td>USER 23</td>
    </tr>
    <tr>
      <td>24</td>
      <td>USER 24</td>
    </tr>
    <tr>
      <td>25</td>
      <td>USER 25</td>
    </tr>
    <tr>
      <td>26</td>
      <td>USER 26</td>
    </tr>
    <tr>
      <td>27</td>
      <td>USER 27</td>
    </tr>
    <tr>
      <td>28</td>
      <td>USER 28</td>
    </tr>
    <tr>
      <td>29</td>
      <td>USER 29</td>
    </tr>
    <tr>
      <td>30</td>
      <td>USER 30</td>
    </tr>
  </tbody>
</table>


(For reference, here is the original version, where simply a boolean was returned, and the sorting does not work at all):

for (const table of document.getElementsByTagName('table')) {
  const headers = table.querySelectorAll('thead tr th');
  for (let i = 0; i < headers.length - 1; i++) {
    headers[i].addEventListener('click', sortTable(i, table.id));
  }
}

function sortTable(n, tableId) {
  return () => {
    const table = document.getElementById(tableId);

    const newTable = document.createElement('table');
    newTable.className = table.className;
    newTable.id = table.id;

    const tbody = document.createElement('tbody');
    const thead = document.createElement('thead');

    const rows = Array.from(table.rows);
    thead.appendChild(rows.shift());
    const th = thead.getElementsByTagName('th');

    const dir = th[n].className == 'asc' ? 'desc' : 'asc';

    rows.sort((a, b) => {
        let x = a.getElementsByTagName('td')[n].innerText.toLowerCase();
        let y = b.getElementsByTagName('td')[n].innerText.toLowerCase();

        const compare = x.localeCompare(y, 'fr', {
          sensitivity: 'base',
          numeric: true
        });

        return ((dir == 'asc' && compare > 0) || (dir == 'desc' && compare < 0));
      })
      .forEach(row => tbody.appendChild(row));

    for (const header of th) {
      header.className = '';
    }

    th[n].className = dir;

    newTable.appendChild(thead);
    newTable.appendChild(tbody);

    table.parentNode.replaceChild(newTable, table);
  };
}
<table id="mytable">
  <thead>
    <tr>
      <th>Rank</th>
      <th>Name</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>USER 1</td>
    </tr>
    <tr>
      <td>3</td>
      <td>USER 3</td>
    </tr>
    <tr>
      <td>2</td>
      <td>USER 2</td>
    </tr>
    <tr>
      <td>4</td>
      <td>USER 4</td>
    </tr>
    <tr>
      <td>5</td>
      <td>USER 5</td>
    </tr>
    <tr>
      <td>6</td>
      <td>USER 6</td>
    </tr>
    <tr>
      <td>7</td>
      <td>USER 7</td>
    </tr>
    <tr>
      <td>8</td>
      <td>USER 8</td>
    </tr>
    <tr>
      <td>9</td>
      <td>USER 9</td>
    </tr>
    <tr>
      <td>10</td>
      <td>USER 10</td>
    </tr>
    <tr>
      <td>11</td>
      <td>USER 11</td>
    </tr>
    <tr>
      <td>12</td>
      <td>USER 12</td>
    </tr>
    <tr>
      <td>13</td>
      <td>USER 13</td>
    </tr>
    <tr>
      <td>14</td>
      <td>USER 14</td>
    </tr>
    <tr>
      <td>15</td>
      <td>USER 15</td>
    </tr>
    <tr>
      <td>16</td>
      <td>USER 16</td>
    </tr>
    <tr>
      <td>17</td>
      <td>USER 17</td>
    </tr>
    <tr>
      <td>18</td>
      <td>USER 18</td>
    </tr>
    <tr>
      <td>19</td>
      <td>USER 19</td>
    </tr>
    <tr>
      <td>20</td>
      <td>USER 20</td>
    </tr>
    <tr>
      <td>21</td>
      <td>USER 21</td>
    </tr>
    <tr>
      <td>22</td>
      <td>USER 22</td>
    </tr>
    <tr>
      <td>23</td>
      <td>USER 23</td>
    </tr>
    <tr>
      <td>24</td>
      <td>USER 24</td>
    </tr>
    <tr>
      <td>25</td>
      <td>USER 25</td>
    </tr>
    <tr>
      <td>26</td>
      <td>USER 26</td>
    </tr>
    <tr>
      <td>27</td>
      <td>USER 27</td>
    </tr>
    <tr>
      <td>28</td>
      <td>USER 28</td>
    </tr>
    <tr>
      <td>29</td>
      <td>USER 29</td>
    </tr>
    <tr>
      <td>30</td>
      <td>USER 30</td>
    </tr>
  </tbody>
</table>

肩上的翅膀 2025-02-04 18:17:17

a.getElementsbytagname('td')是一个非常昂贵的操作,在每个比较期间都将其称为慢。

表行具有一个单元格属性,其中包含所有tdth元素,您可以使用它。

      let x = a.cells[n].innerText.toLowerCase();
      let y = b.cells[n].innerText.toLowerCase();

a.getElementsByTagName('td') is a pretty expensive operation, calling it during every comparison is going to be slow.

Table rows have a cells property that contains all the td and th elements, you can use that instead.

      let x = a.cells[n].innerText.toLowerCase();
      let y = b.cells[n].innerText.toLowerCase();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文