-1

I have a list of books in HTML, which contains multiple elements:

  • The book's title
  • The author's name
  • Whether the book is finished or not (Completed / Ongoing)
  • The book's synopsis

I am trying to make a button that would allow me to sort the list by whether a book is Completed or Ongoing. Additionally, I would like the list to be alphabetically sorted by title (so that, in the end, all the completed books appear at the top, in alphabetical order).

Another thing I'd like to accomplish is to have the list be sorted in ascending order in priority, and then, if the list is already in ascending order, have it sorted in descending order instead. This isn't super important, but it would be nice to have.

This all needs to be in pure javascript due to reasons outside my control :(

Unfortunately, I'm having no luck so far. Here's the code I have right now:

HTML:

<button class="button-9" onclick="sortByCompleted()">Sort by Completed</button>
<ul class="links-list" id="id01">
<li>
    <a class="is-external-link" href="www.google.com">TITLE 1<span class="author" style="color:black">by AUTHOR1</span><span class="badge">Ongoing</span>
        <em>Synopsis 1</em>
    </a>
</li>
<li>
    <a class="is-external-link" href="www.twitter.com">TITLE 3<span class="author" style="color:black">by AUTHOR3</span><span class="badge">Ongoing</span>
        <em>Synopsis 3</em>
    </a>
</li>
<li>
    <a class="is-external-link" href="www.facebook.com">TITLE 2<span class="author" style="color:black">by AUTHOR3</span><span class="badge">Completed</span>
        <em>Synopsis 2</em>
    </a>
</li>
</ul>

Javascript:

function sortByCompleted(){
   ul = document.getElementById("id01");
   const li = ul.getElementsByTagName('li');
   const sortedItems = Array.from(li).sort((a, b) => {
      a = a.getElementsByClassName('badge')[0];
      b = b.getElementsByClassName('badge')[0];
      return (a < b) ? -1 : (a > b) ? 1 : 0;
   });
   ul.append(sortedItems[0]);
}

If someone could give me a helping hand I'd be very grateful!

GDelavy
  • 1
  • 2
  • And what's the actual problem/question? -> [How do I ask a good question?](https://stackoverflow.com/help/how-to-ask) – Andreas Aug 14 '22 at 13:28
  • Try this super function to sort by selected properties. https://stackoverflow.com/a/22672370/3807365 – IT goldman Aug 14 '22 at 14:17

1 Answers1

0

There are many ways of getting there. The following is just one of them. The snippet is based on a single sort function that can take one or two parameters in form of CSS selectors that are used to extract the information from the individual elements for sorting.

The latest sel+sel2 selectors are stored in the lis.last property. This property is used to determine whether the array needs to be sorted again or whether it should simply be reversed instead.

const ul=document.getElementById("id01"),
  lis=[...ul.querySelectorAll("li")];

function sortBy(sel,sel2=0){
  if (lis.last==sel+sel2) lis.reverse() // reverse the array in place
  else lis.sort((a, b) => { // sort the array in place
    return      a.querySelector(sel ).textContent.localeCompare(b.querySelector(sel ).textContent) 
     || sel2 && a.querySelector(sel2).textContent.localeCompare(b.querySelector(sel2).textContent)
  });
  lis.forEach(li=>ul.append(li)) // put lis back on the page in the new order 
  lis.last=sel+sel2; // remember last selectors
}
<button class="button-9" onclick='sortBy(".badge","a")'>Sort by Completed, Title</button>
<button class="button-9" onclick='sortBy("a")'>Sort by Title</button>
<button class="button-9" onclick='sortBy(".author")'>Sort by Author</button>
<button class="button-9" onclick='sortBy("em")'>Sort by Synopsis</button>
<ul class="links-list" id="id01">
<li>
<a class="is-external-link" href="www.google.com">TITLE 2<span class="author" style="color:black">by AUTHOR1</span><span class="badge">Ongoing</span>
    <em>Synopsis 3</em>
</a>
</li>
<li>
<a class="is-external-link" href="www.twitter.com">TITLE 1<span class="author" style="color:black">by AUTHOR3</span><span class="badge">Ongoing</span>
    <em>Synopsis 1</em>
</a>
</li>
<li>
<a class="is-external-link" href="www.facebook.com">TITLE 3<span class="author" style="color:black">by AUTHOR2</span><span class="badge">Completed</span>
    <em>Synopsis 2</em>
</a>
</li>
</ul>
Carsten Massmann
  • 26,510
  • 2
  • 22
  • 43
  • This is exactly what I needed, I cannot thank you enough! I've been struggling with this issue for a while now and everything works! I'll be sure to mark this as solved once I can, thank you! – GDelavy Aug 14 '22 at 16:07