сортировать элементы dom по атрибуту href в JS - PullRequest
1 голос
/ 28 февраля 2020

У меня есть элементы DOM, как показано ниже. Я хочу отсортировать его по атрибуту href.

Это то, что я пробовал в JS, но нужно сделать больше.

document.addEventListener("DOMContentLoaded", function () {
    let elems = Array.from(document.querySelectorAll(".house-senate a"));
    elems.sort((a, b) => a.textContent.localeCompare(b.textContent));

});

Постановка задачи:

Мне интересно, какой JS код мне нужно добавить, чтобы он сортировал все на основе атрибутов href.

1 Ответ

4 голосов
/ 28 февраля 2020

Вы близки, но:

  • Вам действительно нужно переместить их в DOM.
  • Вы потенциально сортируете те, которые не принадлежат одному и тому же родителю ( хотя все они в вашем примере HTML).
  • blex указал мне, что вы хотите отсортировать по category в href, а не по href сам. В вашем примере речь идет о том же, потому что текст перед категорией во всех href одинаков, но все же, возможно, лучше извлечь его.

Это функция blex для его извлечения:

function getLinkCategory(a) {
  const matches = a.href.match(/category=([a-z]+)/i);
  return matches ? matches[1] : '';
}

Или, если вы хотите быть более строгим при извлечении этого параметра из строки запроса, этот совместный ответ, первоначально разработанный Code Spy , показывает, как это сделать.

См. Комментарии для более:

document.addEventListener("DOMContentLoaded", function () {
    // Get the container
    const container = document.querySelector(".house-senate");
    // Get its immediate child `a` elements
    const elems = [...container.children].filter(child => child.tagName === "A");
    // Sort them
    elems.sort((a, b) => getLinkCategory(a).localeCompare(getLinkCategory(b)));
    // Add them back, which moves them
    for (const el of elems) {
        container.appendChild(el);
    }
});

Live Пример:

function getLinkCategory(a) {
  const matches = a.href.match(/category=([a-z]+)/i);
  return matches ? matches[1] : '';
}
document.addEventListener("DOMContentLoaded", function () {
    // Get the container
    const container = document.querySelector(".house-senate");
    // Get its immediate child `a` elements
    const elems = [...container.children].filter(child => child.tagName === "A");
    // Sort them
    elems.sort((a, b) => getLinkCategory(a).localeCompare(getLinkCategory(b)));
    // Add them back, which moves them
    for (const el of elems) {
        container.appendChild(el);
    }
});
<div class="house-senate widget widget-cpac-depth -horizontal">
    <h1 class="widget__title">Committees</h1>
    <a href="/en/?s=&amp;category=BOIE">
        <div class="committee">
            <div class="color-green">BOIE</div>
            <p>Board of Internal Economy</p>
        </div>
    </a>
    <a href="/en/?s=&amp;category=CACN">
        <div class="committee">
            <div class="color-green">CACN</div>
            <p>Canada-China Relations</p>
        </div>
    </a>
    <a href="/en/?s=&amp;category=CHPC">
        <div class="committee">
            <div class="color-green">CHPC</div>
            <p>Canadian Heritage</p>
        </div>
    </a>
    <a href="/en/?s=&amp;category=CIIT">
        <div class="committee">
            <div class="color-green">CIIT</div>
            <p>International Trade</p>
        </div>
    </a>
</div>

Если вам нужно добавить больше критериев сортировки (согласно вашему комментарию под вопросом), просто добавьте их в обратный вызов sort; на этот вопрос есть ответы, показывающие, как отсортировать массив объектов по нескольким критериям.

Выше я предположил, что сотен этих ссылок нет. Если есть, и , если вы видите проблему с производительностью, описанную выше, вы можете удалить контейнер из DOM, прежде чем перемещать ссылки внутри него, а затем поместить его обратно:

Live Example :

function getLinkCategory(a) {
  const matches = a.href.match(/category=([a-z]+)/i);
  return matches ? matches[1] : '';
}
document.addEventListener("DOMContentLoaded", function () {
    // Get the container
    const container = document.querySelector(".house-senate");
    // Remember its parent and following sibling and remove it
    const parent = container.parentNode;
    const sibling = container.nextSibling;
    parent.removeChild(container);
    // Get its immediate child `a` elements
    const elems = [...container.children].filter(child => child.tagName === "A");
    // Sort them
    elems.sort((a, b) => getLinkCategory(a).localeCompare(getLinkCategory(b)));
    // Add them back, which moves them
    for (const el of elems) {
        container.appendChild(el);
    }
    // Put the container back -- note this works even if the
    // container was the last child in the parent
    // and `sibling` is `null`.
    parent.insertBefore(container, sibling);
});
<div>This is before the <code>div</code> with the links in it.</div>
<div class="house-senate widget widget-cpac-depth -horizontal">
    <h1 class="widget__title">Committees</h1>
    <a href="/en/?s=&amp;category=BOIE">
        <div class="committee">
            <div class="color-green">BOIE</div>
            <p>Board of Internal Economy</p>
        </div>
    </a>
    <a href="/en/?s=&amp;category=CACN">
        <div class="committee">
            <div class="color-green">CACN</div>
            <p>Canada-China Relations</p>
        </div>
    </a>
    <a href="/en/?s=&amp;category=CHPC">
        <div class="committee">
            <div class="color-green">CHPC</div>
            <p>Canadian Heritage</p>
        </div>
    </a>
    <a href="/en/?s=&amp;category=CIIT">
        <div class="committee">
            <div class="color-green">CIIT</div>
            <p>International Trade</p>
        </div>
    </a>
</div>
<div>This is after the <code>div</code> with the links in it.</div>

Примечание. Вы используете современные языковые функции, но в приведенном выше примере используется современная браузерная функция (NodeList быть повторяемым). Если вы перемещаетесь, возможно, не все браузеры, на которые вы ориентируетесь, имеют необходимую функцию, но для всего, что даже неопределенно современного, вы можете заполнить его; см. мой ответ здесь для деталей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...