Home > OS >  Sort date a list of <a> tags that contain a date along with other non-date text?
Sort date a list of <a> tags that contain a date along with other non-date text?

Time:07-03

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 simpler append()

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>

  • Related