Home > Net >  Why is my javascript sort function not producing the correct order?
Why is my javascript sort function not producing the correct order?

Time:02-27

I have a function that sorts courses (divs) based on an end date that is declared in a data attribute. The entire list of classes is sorting correct except one. I cannot figure out why it is not sorting it correctly. The March 24th is the first one in the sorted list.

I am guessing it is only looking at the "2" in "24" but I am not sure how to get around this, if it is the case.

HTML

 <button onClick="courseSort()">SORT</button>

    <div id="course-container" >
        <div  data-class-start="1/1/2022" data-class-end="5/28/2022">
            <h5>May 28</h5>
        </div>
        <div  data-class-start="2/8/2022" data-class-end="3/9/2022">
            <h5>Mar 9</h5>
        </div>
        <div  data-class-start="1/1/2022" data-class-end="3/5/2022">
            <h5>Mar 5</h5>
        </div>
        <div  data-class-start="1/1/2022" data-class-end="4/1/2022">
            <h5>Apr 1</h5>
        </div>
        <div  data-class-start="2/19/2022" data-class-end="3/8/2022">
            <h5>Mar 8</h5>
        </div>
        <div  data-class-start="2/19/2022" data-class-end="3/24/2022">
            <h5>Mar 24</h5>
        </div>
        <div  data-class-start="1/1/2022" data-class-end="4/23/2022">
            <h5>Apr 23</h5> 
        </div>
        <div  data-class-start="1/1/2022" data-class-end="4/30/2022">
            <h5>Apr 30</h5>
        </div>
    </div>

JS

function sorter(a, b) {
    if (a.dataset.classEnd < b.dataset.classEnd)
        return -1;
    if (a.dataset.classEnd > b.dataset.classEnd)
        return 1;
    return 0;
}
  
// Function to sort Data
function courseSort() {
    var course = document.querySelectorAll("[data-class-end]");
    var courseArray = Array.from(course);
    let sorted = courseArray.sort(sorter);
    sorted.forEach(e =>
        document.querySelector("#course-container").appendChild(e));
}

Thanks

CodePudding user response:

Check function sorter(a, b). When you're accessing for example a.dataset.classEnd, it's a string, not a date. You may want to do something like:

function sorter(a, b) {
  const [aDate, bDate] = [new Date(a.dataset.classEnd), new Date(b.dataset.classEnd)];
  if (aDate < bDate) return -1;
  if (aDate > bDate) return 1;
  return 0;
}

Also, you could simply do this like a one-liner instead of a separated function:

let sorted = courseArray.sort((a, b) => new Date(a.dataset.classEnd) - new Date(b.dataset.classEnd));

I am guessing it is only looking at the "2" in "24" but I am not sure how to get around this, if it is the case.

Yes, that's exactly what was happening as you were comparing strings.

EDIT: As Sebastian Simon suggested in comments, you may like to change the format of your dates to allow sorting without really needing to convert the variables to date.

CodePudding user response:

As already mentioned in comments, the true value of a date can be derived from the Date object. In the example below, the function courseArray(nodeList) will:

  • convert the NodeList into an array run it through .map()
    [...nodeList].map(d => {...
    // [...nodeList] is the same as Array.from(nodeList)
    
  • extract the value from data-class-end and convert it to ISO format
    let mmddyyyy = d.dataset.classEnd;
    let yyyymmdd = mmddyyyy.split('/');
    let yyyy = yyyymmdd.pop();
    yyyymmdd.unshift(yyyy);
    let ISO = yyyymmdd.join('-');
    // from mm/dd/yyyy to yyyy-mm-dd
    
  • then it is converted to the number of milli-seconds since 1-1-1970 to the ISO date -- then it's added as data-order to the div and then the divs are reordered according to data-order value.
      let ms = Date.parse(ISO);
      d.dataset.order = ms;
      return d;
    }).sort((a, b) => a.dataset.order - b.dataset.order);
    

Also, the inline event handler was removed and a onevent property event handler was added. See why inline event handlers are garbage.

const courseArray = nodeList => {
  return [...nodeList].map(d => {
    let mmddyyyy = d.dataset.classEnd;
    let yyyymmdd = mmddyyyy.split('/');
    let yyyy = yyyymmdd.pop();
    yyyymmdd.unshift(yyyy);
    let ISO = yyyymmdd.join('-');
    let ms = Date.parse(ISO);
    d.dataset.order = ms;
    return d;
  }).sort((a, b) => a.dataset.order - b.dataset.order);
};

function courseSort() {
  const course = document.querySelectorAll(".class-item");

  let sorted = courseArray(course);
  sorted.forEach(e =>
    document.querySelector("#course-container").appendChild(e));
};

document.querySelector('button').onclick = courseSort;
<button>SORT</button>

<div id="course-container" >
  <div  data-class-start="1/1/2022" data-class-end="5/28/2022">
    <h5>May 28</h5>
  </div>
  <div  data-class-start="2/8/2022" data-class-end="3/9/2022">
    <h5>Mar 9</h5>
  </div>
  <div  data-class-start="1/1/2022" data-class-end="3/5/2022">
    <h5>Mar 5</h5>
  </div>
  <div  data-class-start="1/1/2022" data-class-end="4/1/2022">
    <h5>Apr 1</h5>
  </div>
  <div  data-class-start="2/19/2022" data-class-end="3/8/2022">
    <h5>Mar 8</h5>
  </div>
  <div  data-class-start="2/19/2022" data-class-end="3/24/2022">
    <h5>Mar 24</h5>
  </div>
  <div  data-class-start="1/1/2022" data-class-end="4/23/2022">
    <h5>Apr 23</h5>
  </div>
  <div  data-class-start="1/1/2022" data-class-end="4/30/2022">
    <h5>Apr 30</h5>
  </div>
</div>

  • Related