Before you read ahead: ES6 may not be used.Consider a web-page showing a report of some data that is structured as follows:<button id='sort-by-category'>Category</button><button id='sort-by-timestamp'>Timestamp</button><section id='report-body'>    <section class='report-section' data-category-name='fruit' data-item-id='1' data-timestamp='2016-09-12T15:47:45.000Z'>        ...    </section>    <section class='report-section' data-category-name='fruit' data-item-id='2' data-timestamp='2016-06-11T15:47:45.000Z'>        ...    </section>    <section class='report-section' data-category-name='vegetable' data-item-id='1' data-timestamp='2016-09-10T15:47:45.000Z'>        ...    </section></section>Such that each section in the report body needs to be sorted according to the custom data- attributes. The catch is that not all attributes are created equal; for example: sorting by timestamp is straightforward, but sorting by item-id isn't because we also want to group items of the same category together.Here's the implementation of that in JS:(function () {    use strict;    var categoryOrder = {        fruit : 0,        vegetable : 1    };    function compareStrings(string1, string2) {        if (string1 < string2) {            return -1;        } else if (string1 > string2) {            return 1;        }        return 0;    }    function compareCategories(element1, element2) {        var category1 = element1.getAttribute(data-category-name);        var category2 = element2.getAttribute(data-category-name);        if (category1 !== category2) {            return categoryOrder[category1] - categoryOrder[category2];        }        category1 = +element1.getAttribute(data-item-id);        category2 = +element2.getAttribute(data-item-id);        return category1 - category2;    }    // dates are ISO-8601    function compareTimestamps(element1, element2) {        var timeStamp1 = element1.getAttribute(data-timestamp);        var timeStamp2 = element2.getAttribute(data-timestamp);        return compareStrings(timeStamp1, timeStamp2);    }    function getElementsByClassName(className) {        var result = document.getElementsByClassName(className);        return Array.prototype.slice.call(result);    }    function makeRearrangeCallback(comparator, reportBody) {        return function() {            var reportBlocks = getElementsByClassName(report-section);            reportBlocks.sort(comparator);            for (var i = 0; i < reportBlocks.length; ++i) {                reportBody.appendChild(reportBlocks[i]);            }        };    }    function addRearrangeCallbackToElement(elementId, comparator, reportBody) {        var element = document.getElementById(elementId);        element.addEventListener(            click,            makeRearrangeCallback(comparator, reportBody),            false);    }    function main() {        var reportBody = document.getElementById(report-body);        addRearrangeCallbackToElement(sort-by-category, compareCategories, reportBody);        addRearrangeCallbackToElement(sort-by-timestamp, compareTimestamps, reportBody);    }    window.addEventListener(load, main, false);}());Note that I'm not looking just for commentary on the JS part. If you believe that there could be a better way to store the information in the markup, feel free to mention it.
Rearranging DOM elements using inconsistent criteria
javascript;html;dom
If I were to make any changes then this would be the code, using ES5, and reduce the number of functions a little, and variable assignments.(function() {  'use strict';  var slice = Function.prototype.call.bind(Array.prototype.slice);  var categoryOrder = {    fruit: 0,    vegetable: 1  };  function compareCategories(element1, element2) {    var category1 = element1.getAttribute('data-category-name');    var category2 = element2.getAttribute('data-category-name');    if (category1 !== category2) {      return categoryOrder[category1] - categoryOrder[category2];    }    return element1.getAttribute('data-item-id') - element2.getAttribute('data-item-id');  }  // dates are ISO-8601  function compareTimestamps(element1, element2) {    return element1.getAttribute('data-timestamp')      .localeCompare(element2.getAttribute('data-timestamp'));  }  function makeRearrangeCallback(comparator, reportBody) {    return function() {      slice(document.getElementsByClassName('report-section'))        .sort(comparator)        .forEach(function(reportBlock) {          reportBody.appendChild(reportBlock);        });    };  }  function addRearrangeCallbackToElement(elementId, comparator, reportBody) {    document.getElementById(elementId)      .addEventListener('click', makeRearrangeCallback(comparator, reportBody), false);  }  function main() {    var reportBody = document.getElementById('report-body');    addRearrangeCallbackToElement('sort-by-category', compareCategories, reportBody);    addRearrangeCallbackToElement('sort-by-timestamp', compareTimestamps, reportBody);  }  window.addEventListener('load', main, false);}());<button id='sort-by-category'>Category</button><button id='sort-by-timestamp'>Timestamp</button><section id='report-body'>  <section class='report-section' data-category-name='fruit' data-item-id='1' data-timestamp='2016-09-12T15:47:45.000Z'>    ..a  </section>  <section class='report-section' data-category-name='fruit' data-item-id='2' data-timestamp='2016-06-11T15:47:45.000Z'>    ..b  </section>  <section class='report-section' data-category-name='vegetable' data-item-id='1' data-timestamp='2016-09-10T15:47:45.000Z'>    ..c  </section></section>