You're close, but:
- You need to actually move them in the DOM.
- You're potentially sorting ones that aren't in the same parent (though they all are in your example HTML).
- blex pointed out to me that you want to sort by the
category
in the href
, not by the href
itself. In your example, it comes to the same thing because the text prior to the category in all the href
s is the same, but still, perhaps better to extract it.
This is blex's function for extracting it:
function getLinkCategory(a) {
const matches = a.href.match(/category=([a-z]+)/i);
return matches ? matches[1] : '';
}
Or if you want to be more rigorous about extracting that parameter from the query string, this collaborative answer originally by Code Spy shows how to do that.
See comments for more:
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 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");
// 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=&category=BOIE">
<div class="committee">
<div class="color-green">BOIE</div>
<p>Board of Internal Economy</p>
</div>
</a>
<a href="/en/?s=&category=CACN">
<div class="committee">
<div class="color-green">CACN</div>
<p>Canada-China Relations</p>
</div>
</a>
<a href="/en/?s=&category=CHPC">
<div class="committee">
<div class="color-green">CHPC</div>
<p>Canadian Heritage</p>
</div>
</a>
<a href="/en/?s=&category=CIIT">
<div class="committee">
<div class="color-green">CIIT</div>
<p>International Trade</p>
</div>
</a>
</div>
If you need to add more sorting criteria (per your comment under the question), just add them in the sort
callback; this question has answers showing how to sort an array of objects on multiple criteria.
I've assumed above that there aren't hundreds of these links. If there are, and if you see a performance problem with the above, you can remove the container from the DOM before moving the links around within it, then put it back:
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=&category=BOIE">
<div class="committee">
<div class="color-green">BOIE</div>
<p>Board of Internal Economy</p>
</div>
</a>
<a href="/en/?s=&category=CACN">
<div class="committee">
<div class="color-green">CACN</div>
<p>Canada-China Relations</p>
</div>
</a>
<a href="/en/?s=&category=CHPC">
<div class="committee">
<div class="color-green">CHPC</div>
<p>Canadian Heritage</p>
</div>
</a>
<a href="/en/?s=&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>
Note: You're using modern language features, but the above relies on a modern browser feature (NodeList
being iterable). If you're transpiling, it may not be that all the browsers you're targeting have the necessary feature, but for anything even vaguely modern, you can polyfill it; see my answer here for details.