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>

3
  • You have a syntax error in your jQuery: .show("1000") is not a valid statement. Please open your browser's console and fix your errors first. Commented May 21, 2022 at 2:07
  • @kmoser Oh, I missed that. I removed it, no errors in the console. Commented May 21, 2022 at 2:31
  • @kmoser On click action, nothing happens though. Commented May 21, 2022 at 4:34

2 Answers 2

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>


Sign up to request clarification or add additional context in comments.

3 Comments

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.
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
Yea, I have the data-ids. This seems to work now. Thank you very much!
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>

18 Comments

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?
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.
@JabbatheHutt I have edited my answer to sort by the original order as well as by date.
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.
I will edit my OP with what I have.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.