Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting JSON file to sortable table using pure JavaScript

I have a JSON file named cats.json.

[{
        "breed" : "Abyssinian",
        "country" : "Ethiopia",
        "coffeePreference" : "espresso",
        "picture" : "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9b/Gustav_chocolate.jpg/100px-Gustav_chocolate.jpg"
    }, {
        "breed" : "Aegean",
        "country" : "Greece",
        "coffeePreference" : "medium roast, cream and sugar",
        "picture" : "https://upload.wikimedia.org/wikipedia/commons/thumb/5/51/Aegean_cat.jpg/100px-Aegean_cat.jpg"
}]

The above is a brief snippet. I am trying to load this JSON file using getJson and format it into a sortable table. I can render the table to the screen, but can't quite get my sort function to work. I know the sort function works on a regular HTML table, and I think it has something to do with my overall approach as I am new to the front end side of things. The code is as follows:

<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html;charset=Windows-1252">
<style type="text/css">
    table {
        border-collapse: collapse;
        border: none;
    }
    th,
    td {
        border: 1px solid black;
        padding: 4px 16px;
        font-family: Times New Roman;
        font-size: 24px;
        text-align: left;
    }
    th {
        background-color: #C8C8C8;
        cursor: pointer;
    }
</style>
</head>
<body>
<div id="catTable"></div>
<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script>
var cats, asc1 = 1,
        asc2 = 1,
        asc3 = 1;
    window.onload = function () {
        cats = document.getElementById("cats");
    }

    function sort_table(tbody, col, asc) {
        var rows = tbody.rows,
            rlen = rows.length,
            arr = new Array(),
            i, j, cells, clen;
        // fill the array with values from the table
        for (i = 0; i < rlen; i++) {
            cells = rows[i].cells;
            clen = cells.length;
            arr[i] = new Array();
            for (j = 0; j < clen; j++) {
                arr[i][j] = cells[j].innerHTML;
            }
        }
        // sort the array by the specified column number (col) and order (asc)
        arr.sort(function (a, b) {
            return (a[col] == b[col]) ? 0 : ((a[col] > b[col]) ? asc : -1 *   asc);
        });
        // replace existing rows with new rows created from the sorted array
        for (i = 0; i < rlen; i++) {
            rows[i].innerHTML = "<td>" + arr[i].join("</td><td>") + "</td>";
        }
    }  
$.getJSON('cats.json', function(cats) {
    var output="<table>";
        output+="<thead>"
        output+="<tr>";
        output+="<th> HeadShot </th>";
        output+= '<th onclick="sort_table(cats, 0, asc1); asc1 *= -1; asc2 =   1; asc3 = 1;">Breed</th>';
        output+= '<th onclick="sort_table(cats, 1, asc2); asc2 *= -1; asc3 = 1; asc1 = 1;">Country</th>';
        output+= '<th onclick="sort_table(cats, 2, asc3); asc3 *= -1; asc1 = 1; asc2 = 1;">CoffeePreference</th>';
        output+="</tr>";
        output+="</thead>";

    for (var i in cats) {
        output+="<tbody id = 'cats'>"; 

        output+="<tr>";
        output+="<td><img src='" + cats[i].picture+"' alt='cat picture'>     </td>";
        output+="<td>" + cats[i].breed + "</td>";
        output+="<td>" + cats[i].country + "</td>";
        output+="<td>" + cats[i].coffeePreference + "</td>";
        output+="</tr>";
        output+="</tbody>"; 

    }
    output+="</table>";
    document.getElementById("catTable").innerHTML=output;



 });


</script>
</body>
</html>

Any help or direction. would be greatly appreciated.

like image 465
00robinette Avatar asked Aug 14 '15 19:08

00robinette


2 Answers

https://www.datatables.net/

This will generate the table for you automatically from a JSON and sort it in place. A good starting point for your specific setup is this:

https://www.datatables.net/examples/server_side/object_data.html

You can use it without "processing" and "serverSide" and replace the "ajax" part with your JSON file.

Edit

Here is a basic implementation with your dataset: http://jsbin.com/kajina/1/edit?html,js,output

Edit 2

In order to use a remote data source, you need to replace the {data: cats} property with {ajax: "cats.json"}. This will have DataTables run the $.getJSON() function for you and fetch the data from the server.

There are multiple types of data sources available here https://www.datatables.net/examples/data_sources/

Also, for a big JSON file I recommend taking into consideration pagination (the server filters the data and sends you only one page of items at a time). See documentation here: https://www.datatables.net/examples/server_side/simple.html

like image 77
NicolaeS Avatar answered Nov 13 '22 16:11

NicolaeS


May help get you started:

The idea is to create an array of row objects where each object has a property for each header of the table and that property has the associated data point for that row.

The array of row objects can then be sorted (using the sortByKey function) based on a particular header.

The resulting array of sorted row objects could then be rendered back into the existing table in sorted order.

If possible, it might be easier to keep an object representing the table to sort and render from rather than grabbing the data from the table.

Untested, but might get the ball rolling. Good luck!

    /**
    *Sort a table element based on a header value
    *@param {object} table The table containing data to be sorted
    *@param {string|number} The column used to sort the rows
    *@param {boolean|null} Determines if the sort should be in reverse order
    */
    var sortTable = function sortTable (table, sortColumn, reverse) {
        var tArr = [];
        var tHeaders = table.tHead.getElementsByTagName('th');
        var tRows = table.tBody.getElementsByTagName('tr');
        var sArr;

        //Create an array of header titles for the table
        //In the order they appear in the header row
        var headers = table.tHead.getElementsByTagName('th');

        //Convert to actual array
        headers = [].slice.call(headers);

        //Replace objects with text
        headers = headers.map(function getHeaderText(header) {
            return header.innerText || header.textContent;
        });

        //Create a row object for each row of data in the table
        //having a property for each column of the table and
        //a corresponding value for that column
        tRows.forEach(function applyRows(row) {
            var col_ct = headers.length - 1;
            var rowObj = {};

            //Create an array of data values in the order they appear
            //in the row
            var data = row.getElementsByTagName('td');
            data = [].slice.call(data);
            data = data.map(function getDataText(data) {
                return data.innerText || data.textContent;    
            });

            //The number of headers should match the number
            //of data points in the row
            if (headers.length !== data.length) {
                alert('Column mismatch');
            }

            //Set header property value to associated data for this row
            while (col_ct) {
                rowObj[headers[col_ct]] = data[col_ct];
                col_ct--;
            }

            //Add the row to the table array
            tArr.push(rowObj);
         });

         //Now tArr contains all rows of your table
         //use sortObjs to sort rows based on particular property
         sArr = tArr.sort(sortByKey(sortColumn, reverse));

         //Then unfold the sorted object to rebuild the table
         sArr.forEach(function buildTableRow(rowObj) {
           //Some function that builds table rows and renders them
           //Rows will then be rendered in sorted order
     });

     };

/**
*Sort an array of objects based on a key
*@param {string|number} field The property to sort by
*@param {boolean} reverse The direction of sort
*@return {object} Params for sort
*/
var sortByKey = function sortByKey(key, reverse) {

    /**
    *Return the value of a given key
    *@param {object} o The object to sort
    *@return {string|number|object} The value of the key
    */
    var value = function (o) {
        return o[key];
    };

    var reverse = (reverse) ? -1 : 1;
    return function (a, b) {
        return a = value(a), b = value(b), reverse * ((a > b) - (b > a));
    };

};
like image 22
Cmaddux Avatar answered Nov 13 '22 16:11

Cmaddux