LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Javascript Sort HTML Table Columns - Asc/Desc Indicators (https://www.linuxquestions.org/questions/programming-9/javascript-sort-html-table-columns-asc-desc-indicators-4175677056/)

GPGAgent 06-14-2020 08:54 AM

Javascript Sort HTML Table Columns - Asc/Desc Indicators
 
I have two examples of Javascript that sorts a column of a table, one is
very concise but doesn't show the sort order, the other is very long but
does show the sort order. I thought it would be simple to lift the
arrowhead code and put it into the nice concise bit of code but it
defeats me, maybe someone can point me in the right direction - no pun
intended!

With Arrowheads - using ascii codes 25b2 and 25bc

Code:

<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>TestSortArrows - html</title>
   
  <script>
 function sortTable(Table, col, dir) {
    var sortClass, i;

    sortTable.sortCol = -1;
    sortClass = Table.className.match(/js-sort-\d+/);
    if (null != sortClass) {
        sortTable.sortCol = sortClass[0].replace(/js-sort-/, '');
        Table.className = Table.className.replace(new RegExp(' ?' + sortClass[0] + '\\b'), '');
    }
    if ('undefined' === typeof col) {
        col = sortTable.sortCol;
    }

    if ('undefined' !== typeof dir) {
        sortTable.sortDir = dir == -1 || dir == 'desc' ? -1 : 1;
    } else {
        sortClass = Table.className.match(/js-sort-(a|de)sc/);
        if (null != sortClass && sortTable.sortCol == col) {
            sortTable.sortDir = 'js-sort-asc' == sortClass[0] ? -1 : 1;
        } else {
            sortTable.sortDir = 1;
        }
    }
    Table.className = Table.className.replace(/ ?js-sort-(a|de)sc/g, '');

    Table.className += ' js-sort-' + col;
    sortTable.sortCol = col;

    Table.className += ' js-sort-' + (sortTable.sortDir == -1 ? 'desc' : 'asc');

    if (col < Table.tHead.rows[Table.tHead.rows.length - 1].cells.length) {
        sortClass = Table.tHead.rows[Table.tHead.rows.length - 1].cells[col].className.match(/js-sort-[-\w]+/);
    }
    for (i = 0; i < Table.tHead.rows[Table.tHead.rows.length - 1].cells.length; i++) {
        if (col == Table.tHead.rows[Table.tHead.rows.length - 1].cells[i].getAttribute('data-js-sort-colNum')) {
            sortClass = Table.tHead.rows[Table.tHead.rows.length - 1].cells[i].className.match(/js-sort-[-\w]+/);
        }
    }
    if (null != sortClass) {
        sortTable.sortFunc = sortClass[0].replace(/js-sort-/, '');
    } else {
        sortTable.sortFunc = 'string';
    }
    Table.querySelectorAll('.js-sort-active').forEach(function(Node) {
        Node.className = Node.className.replace(/ ?js-sort-active\b/, '');
    });
    Table.querySelectorAll('[data-js-sort-colNum="' + col + '"]:not(:empty)').forEach(function(Node) {
        Node.className += ' js-sort-active';
    });

    var rows = [],
        TBody = Table.tBodies[0];

    for (i = 0; i < TBody.rows.length; i++) {
        rows[i] = TBody.rows[i];
    }
    if ('none' != sortTable.sortFunc) {
        rows.sort(sortTable.compareRow);
    }

    while (TBody.firstChild) {
        TBody.removeChild(TBody.firstChild);
    }
    for (i = 0; i < rows.length; i++) {
        TBody.appendChild(rows[i]);
    }
}

sortTable.compareRow = function(RowA, RowB) {
    var valA, valB;
    if ('function' != typeof sortTable[sortTable.sortFunc]) {
        sortTable.sortFunc = 'string';
    }
    valA = sortTable[sortTable.sortFunc](RowA.cells[sortTable.sortCol]);
    valB = sortTable[sortTable.sortFunc](RowB.cells[sortTable.sortCol]);

    return valA == valB ? 0 : sortTable.sortDir * (valA > valB ? 1 : -1);
};

sortTable.stripTags = function(html) {
    return html.replace(/<\/?[a-z][a-z0-9]*\b[^>]*>/gi, '');
};

sortTable.date = function(Cell) {
    // If okDate library is available, Use it for advanced Date processing
    if (okDate) {
        var Date = okDate(sortTable.stripTags(Cell.innerHTML));
        return Date ? Date.getTime() : 0;
    } else {
        return (new Date(sortTable.stripTags(Cell.innerHTML))).getTime() || 0;
    }
};

sortTable.number = function(Cell) {
    return Number(sortTable.stripTags(Cell.innerHTML).replace(/[^-\d.]/g, ''));
};

sortTable.string = function(Cell) {
    return sortTable.stripTags(Cell.innerHTML).toLowerCase();
};

sortTable.raw = function(Cell) {
    return Cell.innerHTML;
};

sortTable.last = function(Cell) {
    return sortTable.stripTags(Cell.innerHTML).split(' ').pop().toLowerCase();
};

sortTable.input = function(Cell) {
    for (var i = 0; i < Cell.children.length; i++) {
        if ('object' == typeof Cell.children[i]
            && 'undefined' != typeof Cell.children[i].value
        ) {
            return Cell.children[i].value.toLowerCase();
        }
    }

    return sortTable.string(Cell);
};

sortTable.none = function(Cell) {
    return null;
};

sortTable.getClickHandler = function(Table, col) {
    return function() {
        sortTable(Table, col);
    };
};

sortTable.init = function() {
    var THead, Tables, Handler;
    if (document.querySelectorAll) {
        Tables = document.querySelectorAll('table.js-sort-table');
    } else {
        Tables = document.getElementsByTagName('table');
    }

    for (var i = 0; i < Tables.length; i++) {
        if (!document.querySelectorAll && null === Tables[i].className.match(/\bjs-sort-table\b/)) {
            continue;
        }

        if (Tables[i].attributes['data-js-sort-table']) {
            continue;
        }

        if (!Tables[i].tHead) {
            THead = document.createElement('thead');
            THead.appendChild(Tables[i].rows[0]);
            Tables[i].insertBefore(THead, Tables[i].children[0]);
        } else {
            THead = Tables[i].tHead;
        }

        for (var rowNum = 0; rowNum < THead.rows.length; rowNum++) {
            for (var cellNum = 0, colNum = 0; cellNum < THead.rows[rowNum].cells.length; cellNum++) {
                THead.rows[rowNum].cells[cellNum].setAttribute('data-js-sort-colNum', colNum);
                Handler = sortTable.getClickHandler(Tables[i], colNum);
                window.addEventListener
                    ? THead.rows[rowNum].cells[cellNum].addEventListener('click', Handler)
                    : window.attachEvent && THead.rows[rowNum].cells[cellNum].attachEvent('onclick', Handler);
                colNum += THead.rows[rowNum].cells[cellNum].colSpan;
            }
        }

        Tables[i].setAttribute('data-js-sort-table', 'true')
    }

    var element = document.createElement('style');
    document.head.insertBefore(element, document.head.childNodes[0]);
    var sheet = element.sheet;
//
// Set up and down arrows using ascii codes 25b2 and 25bc
//
    sheet.insertRule('table.js-sort-asc thead tr > .js-sort-active:not(.js-sort-none):after {content: "\\25b2";font-size: 0.7em;padding-left: 3px;line-height: 0.7em;}', 0);
    sheet.insertRule('table.js-sort-desc thead tr > .js-sort-active:not(.js-sort-none):after {content: "\\25bc";font-size: 0.7em;padding-left: 3px;line-height: 0.7em;}', 0);
};

// Run sortTable.init() when the page loads
window.addEventListener
    ? window.addEventListener('load', sortTable.init, false)
    : window.attachEvent && window.attachEvent('onload', sortTable.init)
    ;

if (typeof NodeList.prototype.forEach !== "function") {
    NodeList.prototype.forEach = Array.prototype.forEach;
}
  </script> 

  </head>
<body>

  <H3>Test Sorting table - TestSortArrows.html</h3>
<!---  <table border=1 cellspacing=0> --->
<table class="js-sort-table"  border=1 cellspacing=0> <!--- id="demo1" --->

  <thead>
    <tr>
      <th>Asset No</th>
      <th>Description</th>
      <th>Location</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>JKEL03001234</td><td>Emergency Light</td><td>Rm 35</td>
    </tr>
    <tr>
      <td>JKEL03001239</td><td>Emergency Light</td><td>Rm 36</td>
    </tr>
    <tr>
      <td>JKEP01001234</td><td>Emergency Power Off</td><td>Rm 37</td>
    </tr>
    <tr>
      <td>JKED03001234</td><td>Emergency Door</td><td>Rm 38</td>
    </tr>
  </tbody>
</table>
</body>
</html>

And the without arrowheads example - I know what to insert. But I don't know how or where exactly.

Code:

<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>TestNoSortArrows</title>
   
  <script>
  function sortTable(table, col, reverse) {
    var tb = table.tBodies[0], // use `<tbody>` to ignore `<thead>` and `<tfoot>` rows
        tr = Array.prototype.slice.call(tb.rows, 0), // put rows into array
        i;
    reverse = -((+reverse) || -1);
    tr = tr.sort(function (a, b) { // sort rows
        return reverse // `-1 *` if want opposite order
            * (a.cells[col].textContent.trim() // using `.textContent.trim()` for test
                .localeCompare(b.cells[col].textContent.trim())
              );
    });
    for(i = 0; i < tr.length; ++i) tb.appendChild(tr[i]); // append each row in order
}

function makeSortable(table) {
    var th = table.tHead, i;
    th && (th = th.rows[0]) && (th = th.cells);
    if (th) i = th.length;
    else return; // if no `<thead>` then do nothing
    while (--i >= 0) (function (i) {
        var dir = 1;
        th[i].addEventListener('click', function () {sortTable(table, i, (dir = 1 - dir))});
    }(i));
}

function makeAllSortable(parent) {
    parent = parent || document.body;
    var t = parent.getElementsByTagName('table'), i = t.length;
    while (--i >= 0) makeSortable(t[i]);
}

    window.onload = function () {makeAllSortable();};
  </script> 

  </head>
<body>

  <H3>Test Sorting table - TestNoSortArrows.html</h3>
<!---  <table border=1 cellspacing=0> --->
<table class="js-sort-table" id="demo1" border=1 cellspacing=0>

  <thead>
    <tr>
      <th>Asset No</th>
      <th>Description</th>
      <th>Location</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>JKEL03001234</td><td>Emergency Light</td><td>Rm 35</td>
    </tr>
    <tr>
      <td>JKEL03001239</td><td>Emergency Light</td><td>Rm 36</td>
    </tr>
    <tr>
      <td>JKEP01001234</td><td>Emergency Power Off</td><td>Rm 37</td>
    </tr>
    <tr>
      <td>JKED03001234</td><td>Emergency Door</td><td>Rm 38</td>
    </tr>
  </tbody>
</table>
</body>
</html>

Thanks folks

GPGAgent 06-15-2020 01:19 PM

I solved this - here is the full improved code, to be honest I did have help
Code:

<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>TestNoSortArrows</title>


<script>
    function sortTable(table, col, reverse) {
        var tb = table.tBodies[0], // use `<tbody>` to ignore `<thead>` and `<tfoot>` rows
            tr = Array.prototype.slice.call(tb.rows, 0), // put rows into array
            i;
        reverse = -((+reverse) || -1);
        var sortingClass = '';

        // define class for arrowheads
        if (reverse == 1) sortingClass = 'js-sort-desc';
        else sortingClass = 'js-sort-asc';
        var trHead = table.tHead.rows[0];
        // remove all classes for arrowheads
        for (i = 0; i < trHead.cells.length; i++) {
            trHead.cells[i].classList.remove('js-sort-asc');
            trHead.cells[i].classList.remove('js-sort-desc');
        }
        // set class for current arrowhead
        table.tHead.rows[0].cells[col].classList.add(sortingClass);

        tr = tr.sort(function (a, b) { // sort rows
            return reverse // `-1 *` if want opposite order
                * (a.cells[col].textContent.trim() // using `.textContent.trim()` for test
                    .localeCompare(b.cells[col].textContent.trim())
                );
        });
        for (i = 0; i < tr.length; ++i) tb.appendChild(tr[i]); // append each row in order
    }

    function makeSortable(table) {
        var th = table.tHead, i;
        th && (th = th.rows[0]) && (th = th.cells);
        if (th) i = th.length;
        else return; // if no `<thead>` then do nothing
        while (--i >= 0) (function (i) {
            var dir = 1;
            th[i].addEventListener('click', function () { sortTable(table, i, (dir = 1 - dir)) });
        }(i));

        //
        // Inserted from the Arrowhead script
        //
        var element = document.createElement('style');
        document.head.insertBefore(element, document.head.childNodes[0]);
        var sheet = element.sheet;
        //
        // Set up and down arrows using ascii codes 25b2 and 25bc - but it doesn't work
        //
        // sheet.insertRule('table.js-sort-asc thead tr > .js-sort-active:not(.js-sort-none):after {content: "\\25b2";font-size: 0.7em;padding-left: 3px;line-height: 0.7em;}', 0);
        // sheet.insertRule('table.js-sort-desc thead tr > .js-sort-active:not(.js-sort-none):after {content: "\\25bc";font-size: 0.7em;padding-left: 3px;line-height: 0.7em;}', 1);
        sheet.insertRule('table thead tr > th.js-sort-asc:after {content: "\\25b2";font-size: 0.7em;padding-left: 3px;line-height: 0.7em;}', 0);
        sheet.insertRule('table thead tr > th.js-sort-desc:after {content: "\\25bc";font-size: 0.7em;padding-left: 3px;line-height: 0.7em;}', 1);

        //
        // Inserted from the Arrowhead script
        //

    }

    function makeAllSortable(parent) {
        parent = parent || document.body;
        var t = parent.getElementsByTagName('table'), i = t.length;
        while (--i >= 0) makeSortable(t[i]);
    }
    window.onload = function () { makeAllSortable(); };
</script>

</head>

<body>
    <H3>Test Sorting table - TestNoSortArrows.html</h3>
    <!---  <table border=1 cellspacing=0> --->
    <table class="js-sort-table" border=1 cellspacing=0>
        <!--  id="demo1" -->

    <thead>
        <tr>
            <th>Asset No</th>
            <th>Description</th>
            <th>Location</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>JKEL03001234</td>
            <td>Emergency Light</td>
            <td>Rm 35</td>
        </tr>
        <tr>
            <td>JKEL03001239</td>
            <td>Emergency Light</td>
            <td>Rm 36</td>
        </tr>
        <tr>
            <td>JKEP01001234</td>
            <td>Emergency Power Off</td>
            <td>Rm 37</td>
        </tr>
        <tr>
            <td>JKED03001234</td>
            <td>Emergency Door</td>
            <td>Rm 38</td>
        </tr>
    </tbody>
</table>
</body>

Cheers folks

</html>



All times are GMT -5. The time now is 10:04 PM.