I am trying to sort some dynamically created Divs by date/time using JS/jQuery. There are 2 different types of divs (.note and .activity) which are using data-datetime="" or just datetime="" so I am attempting to sort them by the content in elements with the class name .timeago.
setTimeout(function() {
function sortDescending(a, b) {
var date1 = $(a).find(".timeago").text();
date1 = date1.split('/');
date1 = new Date(date1[2], date1[1] - 1, date1[0]);
var date2 = $(b).find(".timeago").text();
date2 = date2.split('/');
date2 = new Date(date2[2], date2[1] - 1, date2[0]);
return date1 < date2 ? 1 : -1;
};
$('.notes .note').sort(sortDescending).appendTo('.notes');
}, 3000);
.note { margin-bottom:30px;}
.note .timeago {color:red; font-weight:bold;}
.activity .timeago {color:green; font-weight:bold;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="accordion">
<!------ Notes ------>
<div data-toggle="collapse" href="#collapse0">
<div >
<div >
<div >
<abbr data-datetime="2022-10-30T18:54:39Z" title="10/30/2022 11:54 AM">10/30/2022 11:54 AM</abbr>
</div>
<div >Should Be 1</div>
</div>
<div id="collapse0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
</div>
<div data-toggle="collapse" href="#collapse1">
<div >
<div >
<div >
<abbr data-datetime="2022-08-11T15:39:41Z" title="8/11/2022 8:39 AM">8/11/2022 8:39 AM</abbr>
</div>
<div >Should Be 5</div>
</div>
<div id="collapse1">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
</div>
<div data-toggle="collapse" href="#collapse2">
<div >
<div >
<div >
<abbr data-datetime="2022-10-05T14:53:01Z" title="10/5/2022 7:53 AM">10/5/2022 7:53 AM</abbr>
</div>
<div >Should Be 2</div>
</div>
<div id="collapse2">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
</div>
<!------ End Notes ------>
<!------ Activities ------>
<div data-toggle="collapse" href="#collapse3">
<div >
<div >Should Be 6</div>
<div >
<time datetime="2022-04-03T15:41:09-07:00">4/3/2022 3:41 PM</time>
</div>
</div>
<div id="collapse3">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
<div data-toggle="collapse" href="#collapse4">
<div >
<div >Should Be 3</div>
<div >
<time datetime="2022-10-03T06:55:52-07:00">10/3/2022 6:55 AM</time>
</div>
</div>
<div id="collapse4">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
<div data-toggle="collapse" href="#collapse5">
<div >
<div >Should Be 4</div>
<div >
<time datetime="2022-09-03T09:29:33-07:00">9/3/2022 9:29 AM</time>
</div>
</div>
<div id="collapse5">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
<!------ End Activities ------>
</div>
I have created a JS Fiddle for this - https://jsfiddle.net/bstime/oyec69g5/11/
CodePudding user response:
You can do that...
function sortNotes()
{
let divParent = document.querySelector('#accordion');
[...document.querySelectorAll('#accordion > div.note')]
.sort( (a,b) =>
{
let aDate = new Date(a.querySelector('.timeago').textContent).getTime()
, bDate = new Date(b.querySelector('.timeago').textContent).getTime();
return bDate - aDate;
})
.forEach(note => divParent.appendChild(note) )
}
sortNotes();
.note { margin-bottom:30px;}
.note .timeago {color:red; font-weight:bold;}
.activity .timeago {color:green; font-weight:bold;}
<div id="accordion">
<div >
<div >
<div >
<div >
<abbr data-datetime="2022-10-30T18:54:39Z" title="10/30/2022 11:54 AM">10/30/2022 11:54 AM</abbr>
</div>
<div>Should Be 1</div>
</div>
<div >
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
</div>
<div >
<div >
<div >
<div >
<abbr data-datetime="2022-08-11T15:39:41Z" title="8/11/2022 8:39 AM">8/11/2022 8:39 AM</abbr>
</div>
<div>Should Be 5</div>
</div>
<div id="collapse1">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
</div>
<div >
<div >
<div >
<div >
<abbr data-datetime="2022-10-05T14:53:01Z" title="10/5/2022 7:53 AM">10/5/2022 7:53 AM</abbr>
</div>
<div>Should Be 2</div>
</div>
<div id="collapse2">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
</div>
<div >
<div >
<div >Should Be 6</div>
<div >
<time datetime="2022-04-03T15:41:09-07:00">4/3/2022 3:41 PM</time>
</div>
</div>
<div >
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
<div >
<div >
<div >Should Be 3</div>
<div >
<time datetime="2022-10-03T06:55:52-07:00">10/3/2022 6:55 AM</time>
</div>
</div>
<div >
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
<div >
<div >
<div >Should Be 4</div>
<div >
<time datetime="2022-09-03T09:29:33-07:00">9/3/2022 9:29 AM</time>
</div>
</div>
<div >
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
</div>
from PO comment :
that works when using on the fiddle but when I apply it to the site im getting: Uncaught TypeError: Cannot read properties of null (reading 'textContent')
in case of invalid date values...
function sortNotes()
{
let divParent = document.querySelector('#accordion')
, allNotes = [...document.querySelectorAll('#accordion > div.note')]
;
allNotes.forEach( note =>
{
let refTimeago = note.querySelector('.timeago');
note._refDate = refTimeago ? new Date(refTimeago.textContent).getTime() : 0;
if (isNaN(note._refDate) ) note._refDate = 0;
});
allNotes
.sort( (a,b) => b._refDate - a._refDate )
.forEach( note =>
{
delete note._refDate;
divParent.appendChild(note);
})
}
sortNotes();
CodePudding user response:
Your date constructor params were incorrect so the date being parsed failed. I split the last date part (the year time eg: 2022 9:29 AM) with space and get the first item to only get the year.
setTimeout(function() {
function sortDescending(a, b) {
var date1 = $(a).find(".timeago").text();
date1 = date1.split('/');
date1 = new Date(date1[2].split(' ')[0], date1[0], date1[1]);
var date2 = $(b).find(".timeago").text();
date2 = date2.split('/');
date2 = new Date(date2[2].split(' ')[0], date2[0], date2[1]);
return date1 < date2 ? 1 : -1;
};
$('.notes .note').sort(sortDescending).appendTo('.notes');
}, 3000);
CodePudding user response:
There is already a good plain Javascript solution, but since you are using jQuery, here is a jQuery option. It also seems clunky to me to have to use the text of your page for the sorting, when you do have an attribute which is presumably there explicitly for this kind of programmatic manipulation - eg maybe in future the text will change format and won't be parseable in JS.
function sortDescending(a, b) {
// Find the element with the attributes we're after ...
let $timeElementA = $('.timeago', a);
let $timeElementB = $('.timeago', b);
// ... and use whichever of the 2 attribute possibilities are there
let timeA = $timeElementA.data('datetime')
? new Date($timeElementA.data('datetime'))
: new Date($timeElementA.attr('datetime'));
let timeB = $timeElementB.data('datetime')
? new Date($timeElementB.data('datetime'))
: new Date($timeElementB.attr('datetime'));
// Javascript sort should return a value >0, <0, or 0.
// Simply subtracting our 2 values works here.
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#description
return timeB - timeA;
}
setTimeout(function() {
$('.notes .note').sort(sortDescending).each(function(i, el) {
$('.notes').append(el);
});
}, 3000);
.note {
margin-bottom: 30px;
}
.note .timeago {
color: red;
font-weight: bold;
}
.activity .timeago {
color: green;
font-weight: bold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="accordion">
<!------ Notes ------>
<div data-toggle="collapse" href="#collapse0">
<div >
<div >
<div >
<abbr data-datetime="2022-10-30T18:54:39Z" title="10/30/2022 11:54 AM">10/30/2022 11:54 AM</abbr>
</div>
<div >Should Be 1</div>
</div>
<div id="collapse0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
</div>
<div data-toggle="collapse" href="#collapse1">
<div >
<div >
<div >
<abbr data-datetime="2022-08-11T15:39:41Z" title="8/11/2022 8:39 AM">8/11/2022 8:39 AM</abbr>
</div>
<div >Should Be 5</div>
</div>
<div id="collapse1">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
</div>
<div data-toggle="collapse" href="#collapse2">
<div >
<div >
<div >
<abbr data-datetime="2022-10-05T14:53:01Z" title="10/5/2022 7:53 AM">10/5/2022 7:53 AM</abbr>
</div>
<div >Should Be 2</div>
</div>
<div id="collapse2">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
</div>
<!------ End Notes ------>
<!------ Activities ------>
<div data-toggle="collapse" href="#collapse3">
<div >
<div >Should Be 6</div>
<div >
<time datetime="2022-04-03T15:41:09-07:00">4/3/2022 3:41 PM</time>
</div>
</div>
<div id="collapse3">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
<div data-toggle="collapse" href="#collapse4">
<div >
<div >Should Be 3</div>
<div >
<time datetime="2022-10-03T06:55:52-07:00">10/3/2022 6:55 AM</time>
</div>
</div>
<div id="collapse4">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
<div data-toggle="collapse" href="#collapse5">
<div >
<div >Should Be 4</div>
<div >
<time datetime="2022-09-03T09:29:33-07:00">9/3/2022 9:29 AM</time>
</div>
</div>
<div id="collapse5">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
<!------ End Activities ------>
</div>