Javascript sort table div by time date

Viewed 347

I have a table like this

<div class="wrapper-3OdqYJdx">
  <div class="bodyRow-OX45">
    <div class="cell-OX45 symbolCell-OX45">
      <div class="name-OX45">John</div>
    </div>
    <div class="cell-OX45 descriptionCell-OX45">paid</div>
    <div class="cell-OX45 timeCell-OX45"><span>1/11/2022</span><span>1:59:08 PM</span></div>
    <div class="cell-OX45 buttonsCell-OX45">
      <div role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA"></div>
      <div role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA dangerous-165AA"></div>
    </div>
  </div>
  <div class="bodyRow-OX45">
    <div class="cell-OX45 symbolCell-OX45">
      <div class="name-OX45">David</div>
    </div>
    <div class="cell-OX45 descriptionCell-OX45">paid</div>
    <div class="cell-OX45 timeCell-OX45"><span>1/11/2022</span><span>12:10:00 AM</span></div>
    <div class="cell-OX45 buttonsCell-OX45">
      <div role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA"></div>
      <div title="Remove" role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA dangerous-165AA"></div>
    </div>
  </div>
  <div class="bodyRow-OX45">
    <div class="cell-OX45 symbolCell-OX45">
      <div class="name-OX45">Vonn</div>
    </div>
    <div class="cell-OX45 descriptionCell-OX45">paid</div>
    <div class="cell-OX45 timeCell-OX45"><span>1/11/2022</span><span>12:40:02 AM</span></div>
    <div class="cell-OX45 buttonsCell-OX45">
      <div title="Edit" role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA"></div>
      <div role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA dangerous-165AA"></div>
    </div>
  </div>
  <div class="bodyRow-OX45">
    <div class="cell-OX45 symbolCell-OX45">
      <div class="name-OX45">Anna</div>
    </div>
    <div class="cell-OX45 descriptionCell-OX45">paid</div>
    <div class="cell-OX45 timeCell-OX45"><span>1/11/2022</span><span>3:02:01 PM</span></div>
    <div class="cell-OX45 buttonsCell-OX45">
      <div title="Edit" role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA"></div>
      <div title="Remove" role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA dangerous-165AA"></div>
    </div>
  </div>
</div>

How I can sort this table by time date, only with javascript, without using jquery, newest on top?

I read about sorting by number here: https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_sort_table_number

But I dont know how to do it. Can you please help me?

4 Answers

Here is a sort on date and time

I assume the classnames are static. If dynamic we need more code

I also added some CSS for visualisation

The datestring of 1/11/2022 1:59:08 PM is parsable without RegExp so I use it as is

const container = document.querySelector(".wrapper-3OdqYJdx")
const getDateFromSpans = spans => new Date(`${spans[0].textContent} ${spans[1].textContent}`);

const rows = [...container.querySelectorAll(".bodyRow-OX45")]
  .sort((a,b)=> getDateFromSpans(a.querySelectorAll('.timeCell-OX45 span')) - getDateFromSpans(b.querySelectorAll('.timeCell-OX45 span')))
container.append(...rows)
.bodyRow-OX45 { border: 1px solid black; }
span::after { content: " - " }
<div class="wrapper-3OdqYJdx">
  <div class="bodyRow-OX45">
    <div class="cell-OX45 symbolCell-OX45">
      <div class="ticker-OX45">John</div>
    </div>
    <div class="cell-OX45 descriptionCell-OX45">paid</div>
    <div class="cell-OX45 timeCell-OX45"><span>1/11/2022</span><span>1:59:08 PM</span></div>
    <div class="cell-OX45 buttonsCell-OX45">
      <div role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA"></div>
      <div role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA dangerous-165AA"></div>
    </div>
  </div>
  <div class="bodyRow-OX45">
    <div class="cell-OX45 symbolCell-OX45">
      <div class="ticker-OX45">David</div>
    </div>
    <div class="cell-OX45 descriptionCell-OX45">paid</div>
    <div class="cell-OX45 timeCell-OX45"><span>1/11/2022</span><span>12:10:00 AM</span></div>
    <div class="cell-OX45 buttonsCell-OX45">
      <div role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA"></div>
      <div title="Remove" role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA dangerous-165AA"></div>
    </div>
  </div>
  <div class="bodyRow-OX45">
    <div class="cell-OX45 symbolCell-OX45">
      <div class="ticker-OX45">Vonn</div>
    </div>
    <div class="cell-OX45 descriptionCell-OX45">paid</div>
    <div class="cell-OX45 timeCell-OX45"><span>1/11/2022</span><span>12:40:02 AM</span></div>
    <div class="cell-OX45 buttonsCell-OX45">
      <div title="Edit" role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA"></div>
      <div role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA dangerous-165AA"></div>
    </div>
  </div>
  <div class="bodyRow-OX45">
    <div class="cell-OX45 symbolCell-OX45">
      <div class="ticker-OX45">Anna</div>
    </div>
    <div class="cell-OX45 descriptionCell-OX45">paid</div>
    <div class="cell-OX45 timeCell-OX45"><span>1/11/2022</span><span>3:02:01 PM</span></div>
    <div class="cell-OX45 buttonsCell-OX45">
      <div title="Edit" role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA"></div>
      <div title="Remove" role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA dangerous-165AA"></div>
    </div>
  </div>
</div>

I would convert the children list of the container into an array of [Date, Element] pairs, sort by the first column, then convert the sorted array of [Date, Element] pairs back into an array of Elements. Finally, you just have to loop through the resulting array to append the child elements into the container one by one.

var map = Array.prototype.map;
var mainEl = document.getElementById("main");
var childEls = map.call(mainEl.children, function (el) {
  var d = el.children[0].textContent;
  var t = el.children[1].textContent;
  return [Date.parse(d + " " + t), el];
}).sort(function (a, b) {
  return a[0] - b[0];
}).map(function (pair) {
  return pair[1];
});
for (let childEl of childEls) {
  mainEl.appendChild(childEl);
}
<div id="main">
  <div><span>1/11/2022</span> <span>1:59:08 PM</span>  David</div>
  <div><span>1/11/2022</span> <span>12:10:00 AM</span> Anna</div>
  <div><span>1/11/2022</span> <span>12:40:02 AM</span> John</div>
  <div><span>1/11/2022</span> <span>3:02:01 PM</span>  Vonn</div>
</div>

Just in case you don't know map or call:

> | [1, 2, 3].map(function (x) {
  |   return x + 1;
  | })
< | [2, 3, 4]
> | Array.prototype.map.call([1, 2, 3], function (x) {
  |   return x + 1;
  | })
< | [2, 3, 4]

The map.call pattern is required because mainEl.children has no map method (type document.children.map in the browser console and see what happens).

Side note

As suggested in the comments, in modern JS syntax you would write childEls = [...mainEl.children].map(...), which boils down to the same result. However, I did a perf test a couple of years ago to compare stuffs like map.call(mainEl.children, ...) and [...mainEl.children].map(...), and the modern syntax was far slower than the old one. Maybe things have changed since then, I let you check by yourself :-)

It's probably a good idea to write your own "parse" function, because you never know how the browser implementation of Date.parse(...) deals with non standard date formats. Just pick the various bits from d + " " + t, and make a Date object with new Date(year, monthIndex, day, hours, minutes, seconds, milliseconds).

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date

Another variant on the above. Query all elements to find the spans containing the dates and generate a timestamp to use in the comparison. An array sort function can compare the values to sort the results as desired before regenerating the HTML.

const d=document;
const q=(e,n=d)=>n.querySelector(e);
const qa=(e,n=d)=>n.querySelectorAll(e);

const parent=q('div.wrapper-3OdqYJdx');
const col=qa('div.timeCell-OX45');
const nodes=[];

col.forEach( div=>{
  let tmp={
    node:div.parentNode,
    time:new Date( [ ...qa('span', div ) ].map( span=>{
      return span.textContent;
    }).join(' ') ).getTime()
  };
  nodes.push( tmp )
});


nodes.sort( (a,b)=>{
  if( a.time > b.time )return 1;
  if( a.time < b.time )return -1
  if( a.time==b.time )return 0;
});

parent.innerHTML='';
nodes.forEach( obj=>parent.appendChild( obj.node ) );
span{padding:0.25rem}
<div class="wrapper-3OdqYJdx">
  <div class="bodyRow-OX45">
    <div class="cell-OX45 symbolCell-OX45">
      <div class="name-OX45">John</div>
    </div>
    <div class="cell-OX45 descriptionCell-OX45">paid</div>
    <div class="cell-OX45 timeCell-OX45"><span>1/11/2022</span><span>1:59:08 PM</span></div>
    <div class="cell-OX45 buttonsCell-OX45">
      <div role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA"></div>
      <div role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA dangerous-165AA"></div>
    </div>
  </div>
  
  <div class="bodyRow-OX45">
    <div class="cell-OX45 symbolCell-OX45">
      <div class="name-OX45">David</div>
    </div>
    <div class="cell-OX45 descriptionCell-OX45">paid</div>
    <div class="cell-OX45 timeCell-OX45"><span>1/11/2022</span><span>12:10:00 AM</span></div>
    <div class="cell-OX45 buttonsCell-OX45">
      <div role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA"></div>
      <div title="Remove" role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA dangerous-165AA"></div>
    </div>
  </div>
  
  <div class="bodyRow-OX45">
    <div class="cell-OX45 symbolCell-OX45">
      <div class="name-OX45">Vonn</div>
    </div>
    <div class="cell-OX45 descriptionCell-OX45">paid</div>
    <div class="cell-OX45 timeCell-OX45"><span>1/11/2022</span><span>12:40:02 AM</span></div>
    <div class="cell-OX45 buttonsCell-OX45">
      <div title="Edit" role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA"></div>
      <div role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA dangerous-165AA"></div>
    </div>
  </div>
  
  <div class="bodyRow-OX45">
    <div class="cell-OX45 symbolCell-OX45">
      <div class="name-OX45">Anna</div>
    </div>
    <div class="cell-OX45 descriptionCell-OX45">paid</div>
    <div class="cell-OX45 timeCell-OX45"><span>1/11/2022</span><span>3:02:01 PM</span></div>
    <div class="cell-OX45 buttonsCell-OX45">
      <div title="Edit" role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA"></div>
      <div title="Remove" role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA dangerous-165AA"></div>
    </div>
  </div>
</div>

Your classes in Dom may be generated dynamic, so this answer will help you:

const times = document.querySelectorAll('div[class*="timeCell"] span:first-child')

const data=[];

times.forEach( item => {
 data.push({
   time: new Date(item.innerText+" "+item.nextElementSibling.innerText ).getTime(),
   parent: item.parentElement.parentElement

 })
})


data.sort(function (a, b) {
  return a.time - b.time;
});

const newDom = document.querySelector('div[class*="wrapper"]');
data.forEach(item => newDom.append(item.parent));
div[class*="timeCell"] span:first-child{
color:red;
}
<div class="wrapper-3OdqYJdx">
  <div class="bodyRow-OX45">
    <div class="cell-OX45 symbolCell-OX45">
      <div class="name-OX45">John</div>
    </div>
    <div class="cell-OX45 descriptionCell-OX45">paid</div>
    <div class="cell-OX45 timeCell-OX45"><span>1/11/2022</span><span>1:59:08 PM</span></div>
    <div class="cell-OX45 buttonsCell-OX45">
      <div role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA"></div>
      <div role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA dangerous-165AA"></div>
    </div>
  </div>
  <div class="bodyRow-OX45">
    <div class="cell-OX45 symbolCell-OX45">
      <div class="name-OX45">David</div>
    </div>
    <div class="cell-OX45 descriptionCell-OX45">paid</div>
    <div class="cell-OX45 timeCell-OX45"><span>1/11/2022</span><span>12:10:00 AM</span></div>
    <div class="cell-OX45 buttonsCell-OX45">
      <div role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA"></div>
      <div title="Remove" role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA dangerous-165AA"></div>
    </div>
  </div>
  <div class="bodyRow-OX45">
    <div class="cell-OX45 symbolCell-OX45">
      <div class="name-OX45">Vonn</div>
    </div>
    <div class="cell-OX45 descriptionCell-OX45">paid</div>
    <div class="cell-OX45 timeCell-OX45"><span>1/11/2022</span><span>12:40:02 AM</span></div>
    <div class="cell-OX45 buttonsCell-OX45">
      <div title="Edit" role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA"></div>
      <div role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA dangerous-165AA"></div>
    </div>
  </div>
  <div class="bodyRow-OX45">
    <div class="cell-OX45 symbolCell-OX45">
      <div class="name-OX45">Anna</div>
    </div>
    <div class="cell-OX45 descriptionCell-OX45">paid</div>
    <div class="cell-OX45 timeCell-OX45"><span>1/11/2022</span><span>3:02:01 PM</span></div>
    <div class="cell-OX45 buttonsCell-OX45">
      <div title="Edit" role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA"></div>
      <div title="Remove" role="button" class="button-mpsUn-6R apply-common-tooltip button-165AA dangerous-165AA"></div>
    </div>
  </div>
</div>

Related