Search code examples
javascriptjqueryreactjsdatesanity

How is it Possible to order <DIV>s by date?


i ran into a problem when using an ordering function.

var $wrapper = $('#list');

$wrapper.find('.blogboxes').sort(function (a, b) {
    return +b.dataset.date - +a.dataset.date;
})
.appendTo( $wrapper );
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="list">

<div class="blogboxes" data-date="2023. 01. 28."></div>

<div class="blogboxes" data-date="2023. 01. 29."></div>

<div class="blogboxes" data-date="2023. 01. 30."></div>

<div class="blogboxes" data-date="2023. 01. 24."></div>
</div>

if i put numbers in the data-date it works fine(desc), but with date it doesn't. I get my date from a Sanity query in this format: "2023-01-28T12:10:00.000Z" which isn't even showing, so i use this: {new Date(post.publishedAt).toLocaleDateString()}

Can i convert my query output to be orderable by the sort function?

Example in Jsfiddle http://jsfiddle.net/5e4y9xbj/

Edit:

import React, {useState, useEffect} from "react";
import "./pagestyles.css"
import sanityClient from "../client.js"
import { NavLink } from "react-router-dom";
import $ from "jquery"

const orderBy = () => {
  var $wrapper = $('#list');

  $wrapper.find('.blogboxes').sort(function (a, b) {
      return +b.dataset.date.replaceAll(/\. ?/g, '') - +a.dataset.date.replaceAll(/\. ?/g, '');
  })
  .appendTo( $wrapper );

};

export default function Blog() {
                  const [postData, setPost] = useState(null);
                  useEffect(()=> 
                  {sanityClient.fetch('*[_type =="post"]  {title, publishedAt, slug, extract, mainImage{asset->{_id, url},alt}}'

                                    ).then((data)=> setPost(data))
                                      .catch(console.error);
                  },[]);

window.addEventListener('scroll', orderBy);

  return (
    <main>
  <div className="kontener">   
  <h1>Blog</h1>  
    <div id="list" className="flex-container">
          { postData && postData.map((post, index)=>(
          <div className="blogboxes" key={index} data-date={new Date(post.publishedAt).toLocaleDateString()} >
            <div >
            <div className="contentzoom" >
            <img className="miniblog" src ={post.mainImage.asset.url} 
                 alt ={post.mainImage.alt}   />
              </div>
                  <NavLink className="posztlink" to={"/blog/" + post.slug.current} key ={post.slug.current}>
                    {post.title}
                  </NavLink>
                  <div className="extract">{post.extract}</div>
              </div>
          </div> ))}    
    </div>
  </div>
  </main>
)
}


Solution

  • You can compare the strings. Remove the conversion to numbers:

    var $wrapper = $('#list');
    
    $wrapper.find('.blogboxes').sort(function (a, b) {
        return b.dataset.date.localeCompare(a.dataset.date);
    })
    .appendTo( $wrapper );
    div[data-date] {
        font-family: sans-serif;
        background: teal;
        padding: 10px;
        font-weight: bold;
        color: #023636;
        text-shadow: 0 1px 0 #58BBBB;
        font-size: 20px;
        width: 100px;
        margin: 4px auto;
        text-align: center;
    }
    
    div[data-date]:before {
        content: attr(data-date);
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div id="list">
    
    <div class="blogboxes" data-date="2023. 01. 28."></div>
    
    <div class="blogboxes" data-date="2023. 01. 29."></div>
    
    <div class="blogboxes" data-date="2023. 01. 30."></div>
    
    <div class="blogboxes" data-date="2023. 01. 24."></div>
    </div>

    Another approach is to convert the strings to a format that can be converted to numbers:

    var $wrapper = $('#list');
    
    $wrapper.find('.blogboxes').sort(function (a, b) {
        return +b.dataset.date.replaceAll(/\. ?/g, '') - +a.dataset.date.replaceAll(/\. ?/g, '');
    })
    .appendTo( $wrapper );
    div[data-date] {
        font-family: sans-serif;
        background: teal;
        padding: 10px;
        font-weight: bold;
        color: #023636;
        text-shadow: 0 1px 0 #58BBBB;
        font-size: 20px;
        width: 100px;
        margin: 4px auto;
        text-align: center;
    }
    
    div[data-date]:before {
        content: attr(data-date);
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div id="list">
    
    <div class="blogboxes" data-date="2023. 01. 28."></div>
    
    <div class="blogboxes" data-date="2023. 01. 29."></div>
    
    <div class="blogboxes" data-date="2023. 01. 30."></div>
    
    <div class="blogboxes" data-date="2023. 01. 24."></div>
    </div>