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.
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
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));
};
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With