Check JSON contents for specific string - javascript

I've been learning and I think I'm finally at the end of this little "project" I've been struggling with! I've seen a few similar topics but can't quite adapt the code for my needs!
I have a JSON output that displays correctly, and I'm looking to search through it for a specific value, and only paste those results in the table.
I have the following Javascript that takes XML data and pastes it into a table.
Javascript
var html = '<table id="myTable"><thead><tr><th>Entry</th>';
for ( row = 0; row < jsondata.rowCount; row++ )
{
html += "<tr><td>" + (row+1) + "</td>";
for ( column = 0; column < jsondata.columnCount; column++ )
{
if((jsondata.xmlData [ row ] [ column ]) == "Ninja")
{
html += "<td>" + jsondata.xmlData [ row ] [ column ] + "</td>"
}
alert(jsondata.xmlData [ row ] [ column ]); //Added in edit - "undefined"
}
html += "</tbody></table>";
$("#tablearea").html(html);
}
EDIT: JSON
"xmlData" : [ [ "Ninja", "Blue"], [ "Car", "Red"] ]
If I exclude the if statement it will paste it all, but the if (when tested with an alert) states undefined.

EDIT (MORE CONCISE):
I believe that your problem is that your rowCount member does not match your actual number of rows. You could use the .length property of an array, or (in your given object), you could do the following...
var jsondata = {
rowCount: 3,
columnCount: 2,
xmlData: [["Ninja", "Blue"], ["Car", "Red"]]
};
var html = '<table id="myTable">' +
'<thead>' +
'<tr><th>Entry</th><tr>';
html += "<tbody>";
for (row = 0; row < jsondata.rowCount; row++) {
var showRow = false;
var tempHtml = "<tr>";
for (column = 0; column < jsondata.columnCount; column++) {
if (jsondata.xmlData[row]) {
tempHtml += "<td>" + jsondata.xmlData[row][column] + "</td>";
showRow = (jsondata.xmlData[row][column] == "Ninja") || showRow;
}
}
tempHtml += "</tr>";
if (showRow) {
html += tempHtml;
}
}
html += "</tbody></table>";
$("#tablearea").html(html);

It seem you have rowCount and/or columCount not matching (maybe just switched) with the actual length of the arrays.
Anyway I'd suggest to retrieve the length of the arrays inspecting them directly
var html = '<table id="myTable"><thead><tr><th>Entry</th>';
for ( row = 0; row < jsondata.xmlData.length; row++ )
{
html += "<tr><td>" + (row+1) + "</td>";
for ( column = 0; column < jsondata.xmlData[row].length; column++ )
{
if((jsondata.xmlData [ row ] [ column ]) == "Ninja")
{
html += "<td>" + jsondata.xmlData [ row ] [ column ] + "</td>"
}
}
html += "</tbody></table>";
$("#tablearea").html(html);
}

Related

Populating HTML table with Google Sheet data (rows & columns)

Having issues with what it might be a rather easy fix.
Context: My code is currently pulling data from Google Sheets, crafting some sort of table and sending it back to HTML where it repopulates an already existing table.
Issue: I am unable to make it so that it builds columns as well as rows. It pastes the data back all in one go (see image for context).
Files: GS & HTML. I believe the issue is on how I'm crafting the table. I know the current disposition of '' doesn't make sense, bu
HTML table with Gsheet values:
Original Gsheet table:
Google Script
function populateStratTb2(){
var tablerows = SpreadsheetApp.getActive().getSheetByName('supp_str').getRange(1, 5, 1000).getValue();
var tablevalues = SpreadsheetApp.getActive().getSheetByName('supp_str').getRange(4, 1, tablerows).getValues();
var tvlen = tablevalues.length
var active = SpreadsheetApp.getActive();
var sheet = active.getSheetByName("supp_str");
var myRange = sheet.getRange("d3:m" + tvlen);
var data = myRange.getValues();
var optionsHTML = "";
for ( var r = 0; r < 10; r+=1) {
for (var i = 0; i < data.length; i+=1) {
optionsHTML += '<tr><td>' + data[i][r] + '</td></tr>';
}};
return optionsHTML;
}
HTML Script
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
$(function(){
google.script.run
.withSuccessHandler(displayData)
.populateStratTb2();
});
function displayData(hl){
document.getElementById('strattable').innerHTML=hl;
}
console.log('MyCode');
</script>
PS. I have spent a good couple hours scrolling though the forum picking bits and improving my original code. I am sure this question (or similar) has been answered already but I can't manage to find it.
In your script, how about the following modifications?
Modification 1:
If your for loop is used, how about the following modification?
function populateStratTb2() {
var sheet = SpreadsheetApp.getActive().getSheetByName('supp_str');
var tablerows = sheet.getRange(1, 5, 1000).getValue();
var tablevalues = sheet.getRange(4, 1, tablerows).getValues();
var tvlen = tablevalues.length
var myRange = sheet.getRange("d3:m" + tvlen);
var data = myRange.getValues();
var optionsHTML = "";
for (var r = 0; r < 10; r += 1) {
var row = "";
for (var i = 0; i < data.length; i += 1) {
row += '<td>' + data[i][r] + '</td>';
}
optionsHTML += '<tr>' + row + '</tr>';
}
optionsHTML = '<table border="1" style="border-collapse: collapse">' + optionsHTML + "</table>";
return optionsHTML;
}
I'm worried that your for loop might not be your expected result. So, I would like to proposed one more modified script as "Modification 2".
Modification 2:
If your data is converted to the HTML table, how about the following modification?
function populateStratTb2() {
var sheet = SpreadsheetApp.getActive().getSheetByName('supp_str');
var tablerows = sheet.getRange(1, 5, 1000).getValue();
var tablevalues = sheet.getRange(4, 1, tablerows).getValues();
var tvlen = tablevalues.length
var myRange = sheet.getRange("d3:m" + tvlen);
var data = myRange.getValues();
var optionsHTML = '<table border="1" style="border-collapse: collapse">' + data.reduce((s, r) => s += "<tr>" + r.map(c => `<td>${c}</td>`).join("") + "</tr>", "") + "</table>";
return optionsHTML;
}
Note:
If you don't want to add the border, please modify <table border="1" style="border-collapse: collapse"> to <table>.
From your reply, I added 2 sample scripts for the script for obtaining the same result from reduce and for loop as follows.
reduce
var optionsHTML = '<table border="1" style="border-collapse: collapse">' + data.reduce((s, r) => s += "<tr>" + r.map(c => `<td>${c}</td>`).join("") + "</tr>", "") + "</table>";
for loop
var optionsHTML = "";
for (var r = 0; r < data.length; r++) {
var row = "";
for (var c = 0; c < data[r].length; c++) {
row += '<td>' + data[r][c] + '</td>';
}
optionsHTML += '<tr>' + row + '</tr>';
}
optionsHTML = '<table border="1" style="border-collapse: collapse">' + optionsHTML + "</table>";
Reference:
reduce()

How to sort a multidimensional array using items in Javascript [duplicate]

This question already has answers here:
Sort array of objects by string property value
(57 answers)
Closed 7 years ago.
Basically all I want is to sort this array based on each item that is shown below, with the exception of the "Action' and 'Thumb Image' ones. So the way I have it set up is that the header for each of rows is a link, and when that link is clicked the list will be sorted based on what was clicked. So for example, if Title is clicked, then I want to have a "titleSort()" function that will sort based on title. I have no idea how to accomplish this, so any help is much appreciated. I was hoping that VideoList.sort(Title) would work, for example.
Thanks,
JS
for(var i = 0; i<VideoList.length; i++) {
content += "<tr>";
content += "<td width='20%'><a href='https://www.youtube.com/watch?v=" + VideoList[i].VideoID + "'onclick='playVideo("+i+")'>" + "<img src ='https://i.ytimg.com/vi/" + VideoList[i].VideoID + "/hqdefault.jpg' width=175 height=130></a></td>";
content += "<td>" + VideoList[i].Title + "</td>";
content += "<td>" + VideoList[i].VideoID + "</td>";
content += "<td>" + VideoList[i].DateUploaded + "</td>";
content += "<td>" + VideoList[i].Category+ "</td>";
content += "<td>" + VideoList[i].Time+ "</td>";
content += "<td width='20%'>" + VideoList[i].Action + "</td>";
content += "</tr>";
You can use sort to sort VideoList according to title this code may work for you
VideoList.sort(function(a,b){
return a.Title > b.Title;
});
I agree with #manishrw about lodash. AND any number of libraries would make this easier - like jQuery and Angular. There are a ton of table-specific libraries out there that have sort function built in. However, I built it to show how you could do it, including re-building the table once it's sorted. To do that I had to create the array with mock data. Here's a jsfiddle:
https://jsfiddle.net/mckinleymedia/c02nqdbz/
And here's the code:
<div id="target"></div>
<script>
var VideoList = [],
content,
fields = ["Title", "VideoID", "DateUploaded", "Category", "Time", "Action"],
num = 10,
sortField = "Title",
sortDirection = 1,
compare = function(a, b) {
if (a[sortField] < b[sortField]) return -1 * sortDirection;
if (a[sortField] > b[sortField]) return 1 * sortDirection;
return 0;
},
sortArray = function(field) {
if( sortField === field ) sortDirection = -1 * sortDirection;
sortField = field;
VideoList.sort(compare);
buildTable();
},
creatVideos = function() {
for (var x = 0; x < num; x++) {
var video = {},
z = Math.floor(Math.random() * 200);
for (var i in fields) {
if(fields[i]==='VideoID') {
video[fields[i]] = z;
} else {
video[fields[i]] = fields[i] + "-" + z;
}
}
VideoList.push(video);
}
},
buildTable = function() {
content = "<table>";
content += "<tr>";
content += "<th>image</th>";
for (var x in fields) {
content += "<th class='field field-" + fields[x] + "' onclick='sortArray(\"" + fields[x] + "\")'>" + fields[x] + "</th>";
}
content += "</tr>";
for (var i in VideoList) {
content += "<tr>";
content += "<td width='20%'><a href='https://www.youtube.com/watch?v=" + VideoList[i].VideoID + "'onclick='playVideo(" + i + ")'>" + "<img src ='https://i.ytimg.com/vi/" + VideoList[i].VideoID + "/hqdefault.jpg' width=175 height=130></a></td>";
for (var x in fields) {
content += "<td>" + VideoList[i][fields[x]] + "</td>";
}
content += "</tr>";
}
content += "</table>";
document.getElementById('target').innerHTML = content;
};
creatVideos();
buildTable();
</script>
Here's a generic function for you
function sortBy(list, field) {
return list.sort(function(a,b) {
return a[field] < b[field];
});
}
sortBy(VideoList, 'Title');
Warning: sortBy will mutate the list input
You could also make it take a comparator so you control the 'direction' of the sort
// you you need to return -1, 0, or 1 for the sort to work reliably
// thanks, #torazaburo
function compareAsc(a,b) {
if (a < b) return -1;
else if (a > b) return 1;
else return 0;
}
function compareDesc(a,b) {
return compareAsc(a,b) * -1;
}
function sortBy(list, field, comparator) {
return list.sort(function(a,b) {
if (comparator instanceof Function)
return comparator(a[field], b[field]);
else
return compareAsc(a[field], b[field]);
});
}
// default sort ascending
sortBy(VideoList, 'Title');
// sort descending
sortBy(VideoList, 'Title', compareDesc);
Use Lodash library. It's easy to use and efficient in run-time. It has a function sortBy, which can be used to sort a collection based on they key you provide.
P.S. Lodash is my goto Library for any operation to be performed on any collection.

Sorting &Pagination for html table

Am using this Json to Html table and am getting the values also. All I need to do is implement sorting for this. Can someone help me out?
where in the objArray am passing my Json data.
All I need to do is implement Sorting and pagination. Please help me out.
function CreateTableViewX(objArray, theme, enableHeader) {
// set optional theme parameter
if (theme === undefined) {
theme = 'mediumTable'; //default theme
}
if (enableHeader === undefined) {
enableHeader = true; //default enable headers
}
var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
var str = '<table class="' + theme + '">';
// table head
if (enableHeader) {
str += '<thead><tr>';
for (var index in array[0]) {
str += '<th scope="col">' + index + '</th>';
}
str += '</tr></thead>';
}
// table body
str += '<tbody>';
for (var i = 0; i < array.length; i++) {
str += (i % 2 == 0) ? '<tr class="alt">' : '<tr>';
for (var index in array[i]) {
str += '<td>' + array[i][index] + '</td>';
}
str += '</tr>';
}
str += '</tbody>'
str += '</table>';
return str;
}
Try Jquery datatable
All you need is to refer Jquery and datables Script files in your solution, select your html table using an Id or class name and Initialize it like this. Datatable will then take care of sorting and pagination for you.
$(document).ready(function(){
$('#tableID').dataTable();
});

Looping through json subobjects and doing something with each "element"

I am a newbie with json arrays/objects. I am trying to get to some subobjects within my .json file. I have tried the suggestions on here, but I keep getting "undefined" results. Here is the .json --
{
"DACcourses": [
{
"longTitle": "<a href='#'>Ammo-29 Electrical Explosives Safety for Naval Facilities</a>",
"longDescript": "ammo-29.html",
"atrrsLink": "Win 95+",
"delMeth": "standard",
"sked": [
{
"classNumb": "926",
"startDate": "4/16/2012",
"endDate": "4/20/2012",
"location": "NMC Fort Worth, TX",
"status": "scheduled",
"emptySeats": "Availability"
},
{
"classNumb": "001",
"startDate": "6/4/2012",
"endDate": "6/8/2012",
"location": "McAlester, OK",
"status": "scheduled",
"emptySeats": "Availability"
},
{
"classNumb": "920",
"startDate": "6/18/2012",
"endDate": "6/22/2012",
"location": "Belle Chasse, LA",
"status": "scheduled",
"emptySeats": "Class Full"
}
]}
]}
I must be doing something fundamentally wrong. so here is my code. In the end I am trying to build table rows out of each of the 'sked' objects. But I am having problems with getting individual data elements to show in the console. Here has been my attempts:
$('#content').on("click", "#catList tbody tr", function() {
var aData = oTable.fnGetData( this );
console.log( aData );
var scheduleData = aData.sked;
var catLink = 'catalog/' + aData.longDescript;
$('#fullDescript').load(catLink, function() {
if (!$('#fullDescript #offerings')) {
$('.enrollBTN').hide();
};
if ($(scheduleData).length > 0) {
$(scheduleData).each(function() {
for(var i = 0; i < scheduleData.length; i++) {
/*var startDate = aData.sked.startDate[2];
var endDate = aData.sked.endDate[3];
var location = aData.sked.location[4];
var classNumb = aData.sked.classNumb[1];
var status = aData.sked.status[5];
var emptySeats = aData.sked.emptySeats[6];*/
//var item = scheduleData[i];
console.log( aData.sked.startDate[2] );
var html = "<tr>";
html += "<td>" + item.classNumb + "<\/td>";
//console.log( aData.sked[1].classNumb );
/*html += "<td>" + scheduleData.endDate + "<\/td>";
html += "<td>" + scheduleData.location + "<\/td>";
html += "<td>" + scheduleData.classNumb + "<\/td>";
html += "<td>" + scheduleData.status + "<\/td>";
html += "<td>" + scheduleData.emptySeats + "<\/td>";*/
html += "<\/tr>";
//return scheduleData;
};
$('#schedule tbody').append($(html));
});
};
});
$('#content').hide();
$('#fullDescript').show();
});
Any help is appreciated.
It seems like you would only need the each or for loop, but not both. It also looks like there's some confusion in there on whether to use item = scheduleData[i] or not. Try this:
if ($(scheduleData).length > 0) {
for(var i = 0; i < scheduleData.length; i++) {
var item = scheduleData[i];
var html = "<tr>";
html += "<td>" + item.endDate + "</td>";
// ... etc
html += "</td>";
}
}
Just as a PS, I'd recommend looking into a JS templating tool like Mustache.js. This would allow you to separate data from display template, so you could eliminate the parsing code. It would look something like this:
var template = "{{#sked}}<tr><td>{{endDate}}</td><td>{{location}}</td></tr>{{/sked}}";
var html = "<table>" + Mustache.render(template, aData) + "</table>";
I must be doing something fundamentally wrong
Yes you are.
When you use .each loop, you refer to the current element by this keyword. So you do not need the for loop. Or, if you want the for loop, you do not need the .each loop. In my opinion, use the for loop. .each is just an overhead in this case.
UPDATE: #dbaseman gave you exactly what you need :)
UPDATE 2: Please try the following code. Basically its same as that of dbaseman, but dbaseman's snippet missed closing the <tr> element.
if ($(scheduleData).length > 0) {
for(var i = 0; i < scheduleData.length; i++) {
var item = scheduleData[i];
var html = "<tr>";
html += "<td>" + item.endDate + "</td>";
// ... etc
html += "</tr>"; // should close the <tr> here
}
}

Find the value of html table cell by passing column name for a particular row

I am dynamically creating a table using JSON so i dont know in advance how many column and/or rows will be generated.
I add a clicked event for the row that get selected.
Now my every table will have a column name ID
I want to find the value of ID for the selected row.
How can i achieve this?
I have googled a find a lot of sample which select the cell be index but not by column name.
My table is something like:
My table is generated like:
function CreateTableView(objArray, theme, enableHeader) {
// set optional theme parameter
if (theme === undefined) {
theme = 'mediumTable'; //default theme
}
if (enableHeader === undefined) {
enableHeader = true; //default enable headers
}
// If the returned data is an object do nothing, else try to parse
var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
var str = '<table class="' + theme + '">';
// table head
if (enableHeader) {
str += '<thead><tr>';
for (var index in array[0]) {
str += '<th scope="col">' + index + '</th>';
}
str += '</tr></thead>';
}
// table body
str += '<tbody>';
for (var i = 0; i < array.length; i++) {
str += (i % 2 == 0) ? '<tr class="alt">' : '<tr>';
for (var index in array[i]) {
str += '<td>' + val(array[i][index]) + '</td>';
}
str += '</tr>';
}
str += '</tbody>'
str += '</table>';
return str;
}
Any help is appreciated
I hope i understood you correctly but this should do it.
It alerts the content of the td with the name ID of the clicked tr.
$('tr').live('click',function(){
alert( $(this).find('td[name="ID"]').html() );
});
To find the td via the th with text ID you could do this:
var index = $('yourtable th:contains("ID")').index();
alert( $('.selectedRow td:eq('+index+')').html() );
What I would do though is to save the ID in the TR's data object so you won't have to pull it out the td but can access it directly, like this:
[...]
<tr data-id="26"><td>.....</td></tr>
[...]
then you can access it like that:
$('.selectedRow').data('id');

Categories