This is the HTML containing a list of <a>
tags containing the date within the .caption2
class. By default the list of these episodes are NOT sorted by date. How can I sort them by date with oldest being on top of the list and latest at the end of the list?
<div >
<h2 >All Episodes</h2>
<a href="/ R7DU820ug">
<img
src="https://example.com/1174581"
/>
<div >
<div >
<div >
489: Very Inappropriate Thoughts About This Computer
</div>
<div >Jun 30 • 114 min</div>
</div>
</div>
</a>
<a href="/ QCwmMHIhs">
<img
src="https://example.com/1051401"
/>
<div >
<div >
<div >
Priest and Joe Illidge on crafting new villain Entropy without any
rules
</div>
<div >Jun 26 • 87 min left</div>
</div>
</div>
</a>
<a href="/ QwxKgVw_o">
<img
src="https://example.com/1098514"
/>
<div >
<div >
<div >Ep. 647: Best Sci Fi Beach Reading</div>
<div >Jun 27 • 27 min</div>
</div>
</div>
</a>
<a href="/ HdT7S_15E">
<img
src="https://example.com/488766"
/>
<div >
<div >
<div >Filosofía de coyote</div>
<div >Jun 29 • 25 min</div>
</div>
</div>
</a>
</div>
CodePudding user response:
I really like @bravo's approach of generating an array with date objects first and then sorting over it. Here is his version with a few light adjustments:
- I calculate the target.element
cont
only once - instead of
.insertAdjacentElement()
I use the simplerappend()
const cont=document.querySelector(".pure-u-1");
[...document.querySelectorAll(".episodecell")]
.map(a=>({a,date:new Date(a.querySelector(".caption2").textContent.split("•")[0] "1972")}))
.sort((a,b)=>a.date-b.date)
.forEach(a=>cont.append(a.a))
<div >
<h2 >All Episodes</h2>
<a href="/ R7DU820ug">
<img src="https://example.com/1174581" />
<div >
<div >
<div >
489: Very Inappropriate Thoughts About This Computer
</div>
<div >Jun 30 • 114 min</div>
</div>
</div>
</a>
<a href="/ QCwmMHIhs">
<img src="https://example.com/1051401" />
<div >
<div >
<div >
Priest and Joe Illidge on crafting new villain Entropy without any rules
</div>
<div >Jun 26 • 87 min left</div>
</div>
</div>
</a>
<a href="/ QwxKgVw_o">
<img src="https://example.com/1098514" />
<div >
<div >
<div >Ep. 647: Best Sci Fi Beach Reading</div>
<div >Jun 27 • 27 min</div>
</div>
</div>
</a>
<a href="/ HdT7S_15E">
<img src="https://example.com/488766" />
<div >
<div >
<div >Filosofía de coyote</div>
<div >Jun 29 • 25 min</div>
</div>
</div>
</a>
</div>
CodePudding user response:
If the HTML you posted is generated from some API, it's best to sort the data, then create the HTML
However, to sort the <a>
in the existing HTML, you can do as follows
Note, since there is no year value for any date, I chose 1972 ... doesn't matter which year you use though, but pick a leap year so Feb 29
is valid
[...document.querySelectorAll(".episodecell")].map(a=>({a,date:new Date(a.querySelector(".caption2").textContent.split("•")[0] "1972")})).sort(({date:a},{date:b})=>b-a).forEach(({a})=>document.querySelector("h2.separatorbar").insertAdjacentElement('afterend',a))
<div >
<h2 >All Episodes</h2>
<a href="/ R7DU820ug">
<img src="https://example.com/1174581" />
<div >
<div >
<div >
489: Very Inappropriate Thoughts About This Computer
</div>
<div >Jun 30 • 114 min</div>
</div>
</div>
</a>
<a href="/ QCwmMHIhs">
<img src="https://example.com/1051401" />
<div >
<div >
<div >
Priest and Joe Illidge on crafting new villain Entropy without any rules
</div>
<div >Jun 26 • 87 min left</div>
</div>
</div>
</a>
<a href="/ QwxKgVw_o">
<img src="https://example.com/1098514" />
<div >
<div >
<div >Ep. 647: Best Sci Fi Beach Reading</div>
<div >Jun 27 • 27 min</div>
</div>
</div>
</a>
<a href="/ HdT7S_15E">
<img src="https://example.com/488766" />
<div >
<div >
<div >Filosofía de coyote</div>
<div >Jun 29 • 25 min</div>
</div>
</div>
</a>
</div>
CodePudding user response:
Let's use the below functions:
Document.querySelectorAll, Element.querySelector, Array.from, Array.sort, Array.reduce, Node.insertBefore, HTMLElement.innerText, Node.parentElement, Date.parse, String.prototype.split, and RegExp.
UPDATE: Performance improvements
// get date from element by inner text
const getDate = e => {
return e.parsedDate ?? (e.parsedDate = Date.parse(`${e.querySelector(".caption2").innerText.split(/\s •\s /)[0]}, 2000`));
};
// find the a elements
Array.from(document.querySelectorAll("a.episodecell"))
// sort by date
.sort((a, b) => getDate(b) - getDate(a))
// replace node position by reinserting
.reduce((prev, cur) => cur.parentElement.insertBefore(cur, prev));
<div >
<h2 >All Episodes</h2>
<a href="/ R7DU820ug">
<img
src="https://example.com/1174581"
/>
<div >
<div >
<div >
489: Very Inappropriate Thoughts About This Computer
</div>
<div >Jun 30 • 114 min</div>
</div>
</div>
</a>
<a href="/ QCwmMHIhs">
<img
src="https://example.com/1051401"
/>
<div >
<div >
<div >
Priest and Joe Illidge on crafting new villain Entropy without any
rules
</div>
<div >Jun 26 • 87 min left</div>
</div>
</div>
</a>
<a href="/ QwxKgVw_o">
<img
src="https://example.com/1098514"
/>
<div >
<div >
<div >Ep. 647: Best Sci Fi Beach Reading</div>
<div >Jun 27 • 27 min</div>
</div>
</div>
</a>
<a href="/ HdT7S_15E">
<img
src="https://example.com/488766"
/>
<div >
<div >
<div >Filosofía de coyote</div>
<div >Jun 29 • 25 min</div>
</div>
</div>
</a>
</div>