2

I am trying to sort post-titles alphabetically using jQuery but nothing happens when I click on the sort filter (I might have wrong syntax). By default the All filter displays all of the posts I have currently. What would be the best and cleanest way to implement this? Thanks!

(Edited, I added some code that kmoser mentioned below)

$(document).ready(function () {
    $(".filter-item").click(function () {
        const value = $(this).attr("data-filter");
        if (value == "all") {
            $(".post-box").show("1000");

            let html = $('.post-box').sort(
                (a, b) => {
                    return (
                        $(a).attr('data-id')
                            >
                        $(b).attr('data-id')
                    )
                }
            )

            $('.post.container').html(html)

        } else if (value == "sort") {
            let html = $('.post-box').sort(
                (a, b) => {
                    return (
                        $(a).find('.post-title').text().trim().localeCompare(
                            $(b).find('.post-title').text().trim()
                        )
                    )
                }
            )

            $('.post.container').html(html)

          // Or to sort by date:
        } else if (value == "sort-date") {

            let html = $('.post-box').sort(
                (a, b) => {
                    return (
                        Date.parse(
                            $(a).find('.post-date').text().trim()
                        )
                            >
                        Date.parse(
                            $(b).find('.post-date').text().trim()
                        )
                    )
                }
            )

            $('.post.container').html(html)
        }
    });

    $(".filter-item").click(function () {
        $(this).addClass("active-filter").siblings().removeClass("active-filter");
    });
});

// Header BackGround Change On Scroll
let header = document.querySelector("header");

window.addEventListener("scroll", () => {
  header.classList.toggle("shadow", window.scrollY > 0);
});
<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
<!-- Sort Filter -->

<div class="post-filter container">
    <span class="filter-item active-filter" data-filter='all'>All</span>
    <span class="filter-item" data-filter='sort'>Sort by Date</span>
    <span class="filter-item" data-filter='sort-date'>Sort by Date</span>
</div>

<!-- Posts -->

<section class="post container">
    <div class="post-box" data-id="1">
        <img src="img/post-1.jpg" alt="" class="post-img">
        <a href="post-page.html" class="post-title">
          B  foo (first)
        </a>
        <span class="post-date">2012-11-03</span>
        <p class="post-decription">Lorem foo</p>
    </div>
    <div class="post-box" data-id="2">
        <img src="img/post-1.jpg" alt="" class="post-img">
        <a href="post-page.html" class="post-title">
          A  bar (second)
        </a>
        <span class="post-date">2012-11-05</span>
        <p class="post-decription">Lorem bar</p>
    </div>
    <div class="post-box" data-id="3">
        <img src="img/post-1.jpg" alt="" class="post-img">
        <a href="post-page.html" class="post-title">
          C  baz (third)
        </a>
        <span class="post-date">2012-11-01</span>
        <p class="post-decription">Lorem baz</p>
    </div>
</section>
Jabba the Hutt
  • 654
  • 3
  • 15

2 Answers2

2

I updated your code.

I think the mistake is when you want to display the result, and the date comparison I think could've been better, so I update the condition:

<!-- Sort Filter -->
<body>
  <div class="post-filter container">
    <span class="filter-item active-filter" data-filter="all">All</span>
    <span class="filter-item" data-filter="sort">Sort by Alphabetically</span>
    <span class="filter-item" data-filter="sort-date">Sort by Date</span>
  </div>

  <!-- Posts -->

  <section class="post container">
    <div class="post-box" data-id="1">
      <img src="img/post-1.jpg" alt="" class="post-img" />
      <a href="post-page.html" class="post-title"> C TEST </a>
      <span class="post-date">2021-11-01</span>
      <p class="post-decription">Lorem ipsum dolor</p>
    </div>
    <div class="post-box" data-id="2">
      <img src="img/post-1.jpg" alt="" class="post-img" />
      <a href="post-page.html" class="post-title"> B TEST </a>
      <span class="post-date">2020-11-01</span>
      <p class="post-decription">Lorem ipsum dolor</p>
    </div>
    <div class="post-box" data-id="3">
      <img src="img/post-1.jpg" alt="" class="post-img" />
      <a href="post-page.html" class="post-title"> B TEST </a>
      <span class="post-date">2020-11-01</span>
      <p class="post-decription">Lorem ipsum dolor</p>
    </div>
  </section>

  <script src="https://code.jquery.com/jquery-3.6.0.js"></script>
  <script>
    $(document).ready(function () {
      $(".filter-item").click(function () {
        console.log("test");
        const value = $(this).attr("data-filter");
        let html = "";
        if (value == "all") {
          $(".post-box").show("1000");

          html = $(".post-box").sort((a, b) => {
            return $(a).attr("data-id") < $(b).attr("data-id") ? -1 : 1;
          });
        } else if (value == "sort") {
          console.log("here");
          html = $(".post-box").sort((a, b) => {
            return $(a)
              .find(".post-title")
              .text()
              .trim()
              .localeCompare($(b).find(".post-title").text().trim());
          });
          // Or to sort by date:
        } else if (value == "sort-date") {
          html = $(".post-box").sort((a, b) => {
            const value =
              new Date($(a).find(".post-date").text().trim()).getTime() <
              new Date($(b).find(".post-date").text().trim()).getTime();
            
            return !value ? -1 : 1;
          });
        }
        $(".post.container").html(html);
      });

      $(".filter-item").click(function () {
        $(this)
          .addClass("active-filter")
          .siblings()
          .removeClass("active-filter");
      });
    });

    // Header BackGround Change On Scroll
    let header = document.querySelector("header");

    window.addEventListener("scroll", () => {
      header.classList.toggle("shadow", window.scrollY > 0);
    });
  </script>
</body>


owenizedd
  • 1,187
  • 8
  • 17
  • So this code seems to be working. But when I click either sort filters and then click back on "all" filter, it doesn't display the default order. – Jabba the Hutt May 22 '22 at 03:57
  • Updated the code. it now support to display default order, however you need to define in each post-box the data-id attribute there to remember the default order. like what I did – owenizedd May 22 '22 at 04:01
  • Yea, I have the data-ids. This seems to work now. Thank you very much! – Jabba the Hutt May 22 '22 at 04:09
1

Assuming multiple .post-box elements (as in my example below), you need to sort them and then insert them back into the DOM, replacing the contents of .post-container:

EDITED to sort by original order and by date.

$(document).ready(function () {
    $(".filter-item").click(function () {
        const value = $(this).attr("data-filter");
        if (value == "all") {
            $(".post-box").show("1000");

            let html = $('.post-box').sort(
                (a, b) => {
                    return (
                        $(a).attr('data-id')
                            >
                        $(b).attr('data-id')
                    )
                }
            )

            $('.post.container').html(html)

        } else if (value == "sort") {
            let html = $('.post-box').sort(
                (a, b) => {
                    return (
                        $(a).find('.post-title').text().trim().localeCompare(
                            $(b).find('.post-title').text().trim()
                        )
                    )
                }
            )

            // Or to sort by date:
            html = $('.post-box').sort(
                (a, b) => {
                    return (
                        Date.parse(
                            $(a).find('.post-date').text().trim()
                        )
                            >
                        Date.parse(
                            $(b).find('.post-date').text().trim()
                        )
                    )
                }
            )

            $('.post.container').html(html)
        }
    });

    $(".filter-item").click(function () {
        $(this).addClass("active-filter").siblings().removeClass("active-filter");
    });
});
<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>

<!-- Sort Filter -->

<div class="post-filter container">
    <span class="filter-item active-filter" data-filter='all'>All</span>
    <span class="filter-item" data-filter='sort'>Sort by Date</span>
</div>

<!-- Posts -->

<section class="post container">
    <div class="post-box" data-id="1">
        <img src="img/post-1.jpg" alt="" class="post-img">
        <a href="post-page.html" class="post-title">
            foo (first)
        </a>
        <span class="post-date">2 Feb 2022</span>
        <p class="post-decription">Lorem foo</p>
    </div>
    <div class="post-box" data-id="2">
        <img src="img/post-1.jpg" alt="" class="post-img">
        <a href="post-page.html" class="post-title">
            bar (second)
        </a>
        <span class="post-date">12 Feb 2022</span>
        <p class="post-decription">Lorem bar</p>
    </div>
    <div class="post-box" data-id="3">
        <img src="img/post-1.jpg" alt="" class="post-img">
        <a href="post-page.html" class="post-title">
            baz (third)
        </a>
        <span class="post-date">9 Feb 2022</span>
        <p class="post-decription">Lorem baz</p>
    </div>
</section>
kmoser
  • 8,780
  • 3
  • 24
  • 40
  • Thanks. So it does show the posts alphabetically but when I click the "All" filter, it doesn't revert back. Also, how would the function look like if I wanted to sort by date instead of name? – Jabba the Hutt May 21 '22 at 20:49
  • You need to add separate code to sort back to the original order. That would necessitate giving each `.post-box` its own `data-id="1"`, etc. so the sort function would know the expected order. As for sorting by date, that's just a question of changing `.find('.post-title')` to `.find('.post-date')` and changing the comparison function to [compare two string dates](https://stackoverflow.com/questions/14781153/how-to-compare-two-string-dates-in-javascript). – kmoser May 21 '22 at 22:19
  • @JabbatheHutt I have edited my answer to sort by the original order as well as by date. – kmoser May 21 '22 at 22:31
  • I added the data-id for each post-box. When I click the "sort" filter, it reverses the order of the posts and nothing happens when I click "all" to revert it back. Also, sorting by date doesn't seem to work either (I thought it might be the date format so i changed it to "2012-11-01") to no avail. – Jabba the Hutt May 21 '22 at 23:06
  • I will edit my OP with what I have. – Jabba the Hutt May 21 '22 at 23:14
  • @JabbatheHutt I just edited your question to include a line that you forgot: `$('.post.container').html(html)`. – kmoser May 21 '22 at 23:25
  • Pardon? I have '$('.post.container').html(html)' appear twice – Jabba the Hutt May 21 '22 at 23:40
  • Right, you forgot the one that I added. Without that, the HTML never gets updated when you click "sort". – kmoser May 22 '22 at 03:00
  • Where do I add it? I don't see any difference – Jabba the Hutt May 22 '22 at 03:02
  • In your last edit, you removed the necessary line: `$('.post.container').html(html) // FORGOT THIS!` – kmoser May 22 '22 at 03:08
  • I edited my post again, pasting my JS file. I have that line in 2 places. Not sure where you mean. – Jabba the Hutt May 22 '22 at 03:14
  • Sorry meant 3*. But it still doesn't revert when I click the "All" filter or "Sort-Date" – Jabba the Hutt May 22 '22 at 03:29
  • @JabbatheHutt You didn't add the `data-id` attributes to the HTML, like I have in my answer. Please read my answer more carefully, since it is working perfectly. You just need to follow all the details. – kmoser May 22 '22 at 03:39
  • Sorry, I do have the data-id on my end. I just forgot to add them in the OP. I edited it just now again. – Jabba the Hutt May 22 '22 at 03:42
  • Your edited question seems to be working now. What's the problem exactly? – kmoser May 22 '22 at 03:44
  • The sort date filter on click doesn't do anything. Also, when I click on "all" filter, after clicking on either sort or sort date, it doesn't change it back to the default order.. – Jabba the Hutt May 22 '22 at 03:54
  • You have two links that are both labeled "Sort by Date" so it's very confusing. In any case, clicking "All" does indeed return them to their original order. Are you running the code snippet? – kmoser May 22 '22 at 04:04
  • I am not sure, but owenized's code seems to work correctly. Anyway I will try yours again to see. I might of missed something. Thank you for the help regardless! – Jabba the Hutt May 22 '22 at 04:10