How do I use the below code to pull certain details like country name and capital only into a table with drop down headers? Or can you suggest any plain English Youtube videos where I can learn how to do this or example courses where I can teach myself.
<script>
$(document).ready(function () {
//for example details in url below
var url = 'https://restcountries.eu/rest/v1/all';
$.getJSON(url, function (data) {
console.log(data)
// var arrItems = []; // THE ARRAY TO STORE JSON ITEMS.
// $.each(data, function (index, value) {
// arrItems.push(value); // PUSH THE VALUES INSIDE THE ARRAY.
// });
console.log(arrItems)
// EXTRACT VALUE FOR TABLE HEADER.
var col = [];
var arrItems = data.countries;
console.log(arrItems)
var firstCountry = arrItems[0]
console.log(firstCountry)
for (var i = 0; i < arrItems.length; i++) {
for (var key in arrItems[i]) {
if (col.indexOf(key) === -1) {
col.push(key);
}
}
}
// CREATE DYNAMIC TABLE.
var table = document.createElement("table");
// CREATE HTML TABLE HEADER ROW USING THE EXTRACTED HEADERS ABOVE.
var tr = table.insertRow(-1); // TABLE ROW.
for (var i = 0; i < col.length; i++) {
var th = document.createElement("th"); // TABLE HEADER.
th.innerHTML = col[i];
tr.appendChild(th);
}
// ADD JSON DATA TO THE TABLE AS ROWS.
for (var i = 0; i < arrItems.length; i++) {
tr = table.insertRow(-1);
for (var j = 0; j < col.length; j++) {
var tabCell = tr.insertCell(-1);
tabCell.innerHTML = arrItems[i][col[j]];
}
}
// FINALLY ADD THE NEWLY CREATED TABLE WITH JSON DATA TO A CONTAINER.
var divContainer = document.getElementById("showData");
divContainer.innerHTML = "";
divContainer.appendChild(table);
});
});
There's a lot of looping inside of looping, which can increase the time and space complexity - meaning, the more data, the slower this solution will become as well as in general this looks like it will be difficult to maintain.
I would first put as much of the html that you can in the static html and just append the dynamic html to the <tbody>.
You can use the Array.reduce static method to generate a string from your data. One thing you can do to make this easier to understand is stick with either mostly appending DOM nodes or using innerHTML. If you stick with innerHTML, you can create template strings for the cells and the rows.
This will make the code more declarative in nature and functional as well as composeable.
$(document).ready(function() {
//for example details in url below
var url = 'https://restcountries.eu/rest/v1/all';
$.getJSON(url, function(data) {
const html = buildHTML(data);
const tbody = document.querySelector('#showData tbody');
tbody.innerHTML = html;
});
});
const tableCellTemplate = (val) => {
return `<td>${val}</td>`;
};
const tableRowTemplate = (val) => {
return `<tr>${val}</tr>`;
};
function buildHTML(data) {
return data.reduce((prev, next) => {
const nameCell = tableCellTemplate(next.name);
const codeCell = tableCellTemplate(next.alpha2Code);
return prev + tableRowTemplate(nameCell + codeCell);
}, '');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="showData">
<table>
<thead>
<tr>
<th>Name</th>
<th>alpha2Code</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
Related
I'm trying to have a bunch of memes show up on my HTML page. I'm using this URL https://api.memegen.link/images. I'm having lots of trouble trying to display images. I cannot figure out how to use this link. The link has what looks like a bunch of JSON code and the actual website has very little documentation on how to use it.
Here's the Javascript code. The HTML is just 2 divs and an input that has an onClick that call the function
$(document).ready(function imagesFromJSON() {
$.getJSON("https://api.memegen.link/images", function (data) {
var arrItems = []; // The array to store JSON items.
$.each(data, function (index, value) {
arrItems.push(value); // Push values in the array.
});
// Extract values for the table header.
var col = [];
for (var i = 0; i < arrItems.length; i++) {
for (var key in arrItems[i]) {
if (col.indexOf(key) === -1) {
col.push(key);
}
}
}
var table = document.createElement("table");
var tr = table.insertRow(-1); // Table row.
for (var i = 0; i < col.length; i++) {
var th = document.createElement("th"); // Table header.
th.innerHTML = col[i];
tr.appendChild(th);
}
// Add JSON data to the table as rows.
for (var i = 0; i < arrItems.length; i++) {
tr = table.insertRow(-1);
for (var j = 0; j < col.length; j++) {
var tabCell = tr.insertCell(-1);
if (j === 2) { // The last JSON column has image urls.
// Create an <img> element to show the images.
var img = document.createElement('img');
img.src = arrItems[i].Image; // The image source from JSON array.
tabCell.appendChild(img);
}
else
tabCell.innerHTML = arrItems[i][col[j]];
}
}
// Finally, add the newly created <table> with data to a container.
var divContainer = document.getElementById("showData");
divContainer.innerHTML = "";
divContainer.appendChild(table);
});
});
You can use fetch API in JavaScript directly to call the memeAPI.
For generating the table inside your JavaScript, you can use Template literals which will make it easy for you to construct the tables.
const getMemeBtn = document.querySelector("#get-meme");
getMemeBtn.addEventListener("click", getMeme);
function getMeme(){
fetch("https://api.memegen.link/images")
.then(res => res.json())
.then(data => {
let HTMLContent = `<table>
<tr>
<th>Meme Template</th>
<th>Meme Image</th>
</tr>
`;
for(let i = 0; i < 5; i++){
let memeImgURL = data[i].url;
let memeName = data[i].template;
HTMLContent += `
<tr>
<td>${memeName}</td>
<td><img width="100" height="100" src="${memeImgURL}"></td>
</tr>
`;
}
HTMLContent += `</table>`;
document.getElementById("memes").innerHTML = HTMLContent;
})
.catch(err => console.log(err));
}
<button type="button" id="get-meme">Get Meme</button>
<br><br><br><br>
<div id="memes"></div>
I'm currently using the following code to create a table based on a JSON API. I want to change the title of the table columns to be Name and Score instead of userName and userScore...
I have tried adjusting the forEach statement that creates the table columns, but that didn't work...
axios
.get("[ip censored]/scores")
.then(function(response) {
let sortedList = response.data.sort((a, b) => b.userScore - a.userScore);
console.warn(sortedList);
// EXTRACT VALUE FOR HTML HEADER.
var col = [];
for (var i = 0; i < sortedList.length; i++) {
for (var key in sortedList[i]) {
if (
col.indexOf(key) === -1 &&
(key === "userName" || key === "userScore")
) {
col.push(key);
}
}
}
// CREATE DYNAMIC TABLE.
var table = document.createElement("table");
// CREATE HTML TABLE HEADER ROW USING THE EXTRACTED HEADERS ABOVE.
var tr = table.insertRow(-1); // TABLE ROW.
for (var i = 0; i < col.length; i++) {
var th = document.createElement("th"); // TABLE HEADER.
th.innerHTML = col[i];
tr.appendChild(th);
}
// ADD JSON DATA TO THE TABLE AS ROWS.
for (var i = 0; i < sortedList.length; i++) {
tr = table.insertRow(-1);
for (var j = 0; j < col.length; j++) {
var tabCell = tr.insertCell(-1);
tabCell.innerHTML = sortedList[i][col[j]];
}
}
// FINALLY ADD THE NEWLY CREATED TABLE WITH JSON DATA TO A CONTAINER.
var divContainer = document.getElementById("leaderboard");
divContainer.innerHTML = "";
divContainer.appendChild(table);
})
.catch(function(error) {
console.error(error);
});
I also tried using CSS to make the tables look prettier, but it still didn't work.
Given you know the incoming key names and that they're consistent a simple inline if/else in your JavaScript should be all you need.
Try this:
for (var i = 0; i < col.length; i++) {
var th = document.createElement("th"); // TABLE HEADER
// This inline if says if col[i] is userName then set innerHTML to Name, else Score
th.innerHTML = col[i]==='userName' ? 'Name' : 'Score';
tr.appendChild(th);
}
Never mind, I figured it out. I used an if statement, and if col[i] equaled the value I wanted, I changed the value before I pushed the table.
You can use an if statement.
for (var i = 0; i < col.length; i++) {
var th = document.createElement("th"); // TABLE HEADER.
var heading = "";
if(col[i] == "userName"){
th.innerHTML = "Name";
}
else if(col[i] == "userScore"){
th.innerHTML = "Score";
}
tr.appendChild(th);
}
I am doing an exercise (from Beginning Javascript) to better understand DOM manipulation. Attempting to recreate the following table in a DRY method using only JS (the textbook solution is here):
<table>
<tr>
<td>Car</td>
<td>Top Speed</td>
<td>Price</td>
</tr>
<tr>
<td>Chevrolet</td>
<td>120mph</td>
<td>$10,000</td>
</tr>
<tr>
<td>Pontiac</td>
<td>140mph</td>
<td>$20,000</td>
</tr>
</table>
I tried this but unsure how you can loop variable creation without throwing an error:
var array = [['Car', 'Top Speed', 'Price'],['Chevrolet', '120mph', '$10,000'], ['Pontiac', '140pmh', '$20,000']] // Creating a data array which a loop will source from
var table = document.createElement('table');
document.body.appendChild(table); // Drew the main table node on the document
for (var i = 0; i<3; i++) {
var tr[i] = document.createElement('tr'); //Create 3 <tr> elements assigned to a unique variable BUT need a working alternative for 'tr[i]'
table.appendChild(tr[i]); // Append to <table> node
for (var j = 0; j<3; j++) {
var tdText = document.createTextNode(array[i][j]); // Extract data from array to a placeholder variable
tr[i].appendChild(tdText); // Take string from placeholder variable and append it to <tr> node
}
}
As already said the problem is the syntax error in declaring the tr[i] variable.
A more cleaner way will be is to use the table api methods like
var array = [
['Car', 'Top Speed', 'Price'],
['Chevrolet', '120mph', '$10,000'],
['Pontiac', '140pmh', '$20,000']
] // Creating a data array which a loop will source from
var table = document.createElement('table');
document.body.appendChild(table); // Drew the main table node on the document
array.forEach(function(row) {
var tr = table.insertRow(); //Create a new row
row.forEach(function(column) {
var td = tr.insertCell();
td.innerText = column; // Take string from placeholder variable and append it to <tr> node
});
});
HTMLTableElement
insertRow()
insertCell
Please use tr instead of tr[i]. It will work
var array = [['Car', 'Top Speed', 'Price'],['Chevrolet', '120mph', '$10,000'], ['Pontiac', '140pmh', '$20,000']] // Creating a data array which a loop will source from
var table = document.createElement('table');
document.body.appendChild(table); // Drew the main table node on the document
for (var i = 0; i<3; i++) {
var tr = document.createElement('tr'); //Create 3 <tr> elements assigned to a unique variable BUT need a working alternative for 'tr[i]'
table.appendChild(tr); // Append to <table> node
for (var j = 0; j<3; j++) {
var tdElement = document.createElement('td');
tdElement.innerHTML = array[i][j];
tr.appendChild(tdElement); // Take string from placeholder variable and append it to <tr> node
}
}
My version with the use of THead and TBody as well as th and td.
// input as an array
const array = [
['Car', 'Top Speed', 'Price'],
['Chevrolet', '120mph', '$10,000'],
['Pontiac', '140pmh', '$20,000']
]
const table = document.createElement('table');
// Generate Header
const head = table.createTHead();
const tr = head.insertRow();
array[0].forEach(function(item) {
const th = document.createElement('th')
th.appendChild(document.createTextNode(item));
tr.appendChild(th);
});
// Generate Body
const body = table.createTBody();
array.slice(1).forEach(function(row) {
const tr = body.insertRow();
row.forEach(function(item, index) {
if (index === 0) {
const th = document.createElement('th')
th.appendChild(document.createTextNode(item));
tr.appendChild(th);
} else {
const td = tr.insertCell(); // create td only
td.appendChild(document.createTextNode(item));
}
});
});
document.body.appendChild(table);
ref:
<thead>: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/thead
<tbody>: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tbody
<th>: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th
I'm developing an android app with phonegap. I'm making an HTML table with some that with a for loop from localStorage. I need, for each row, to store the index i of the for to use it for retrieving an item from localStorage that has the name like the index. I have some code but the variable that i defined for that effect gets overwritten by the loop (of course). Here's the code:
<script language="javascript">
if(len != 0) {
var table = document.getElementById('hor-minimalist-b'); // get the table element
var tableBody = table.childNodes[1]; // get the table body
var tableHead = table.childNodes[0]; // get the table head
var thead = document.createElement('th');
var row2 = document.createElement('tr'); // create a new row
var headText = document.createTextNode('Dados');
thead.scope = "col";
thead.appendChild(headText);
row2.appendChild(thead);
tableHead.appendChild(row2);
for (var i=0; i<len; i++) {
var row = document.createElement('tr'); // create a new row
var cell = document.createElement('td'); // create a new cell
var a = document.createElement('a');
var cellText = document.createTextNode(localStorage.getItem('key' + i));
var xyz = "key" + i;
a.href = "alterar.html";
a.onclick = function() { doLocalStorage(xyz) };
a.appendChild(cellText);
cell.appendChild(a); // append input to the new cell
row.appendChild(cell); // append the new cell to the new row
tableBody.appendChild(row); // append the row to table body
}}
</script>
</table>
Maybe i'm not explaining myself too well. If you need any more info please ask. Thanks in advance. Eva
try to put the key name in to a closure:
function wrapper(i) {
return function() {
doLocalStorage("key" + i)
}}
a.onclick = wrapper(i);
Not sure if I got your question right, but if you want to bind usage of a variable asynchronously when doing for loop then you should wrap it in a closure:
for(i = 1, c = arr.length; i < c; i++){
(function(i){
// i wont change inside this closure so bound events will retain i
$('#id'+i).click(function(){
alert(i); // Will alert the corresponding i
})
})(i);
}
I am using the following method to read header names in a table and put in excel. Could anyone let me know how to modify this to support multiple tables with header info and data.
i.e. how to modify to pass table id. "headers" is the id for "th" tag in code.
function write_headers_to_excel()
{
str="";
var myTableHead = document.getElementById('headers');
var rowCount = myTableHead.rows.length;
var colCount = myTableHead.getElementsByTagName("tr")[0].getElementsByTagName("th").length;
var ExcelApp = new ActiveXObject("Excel.Application");
var ExcelSheet = new ActiveXObject("Excel.Sheet");
ExcelSheet.Application.Visible = true;
for(var i=0; i<rowCount; i++)
{
for(var j=0; j<colCount; j++)
{
str= myTableHead.getElementsByTagName("tr")[i].getElementsByTagName("th") [j].innerHTML;
ExcelSheet.ActiveSheet.Cells(i+1,j+1).Value = str;
}
}
Your question is a bit vague, so I'm guessing at what you want. Assuming your current function works as is, you can just take out the hard-coding of the table's ID and pass it in as a parameter:
function write_headers_to_excel(tableID) {
var myTableHead = document.getElementById(tableID);
// rest of your function as is
}
Then call it once for each table, though that will create a new ExcelSheet for each table.
If the idea is for all of the tables to be added to the same ExcelSheet you can pass an array of table IDs to the function something like the following. I've kept the basic structure of your function but moved the variable declarations out of the loops (since that what JavaScript does behind the scenes anyway), deleted your ExcellApp variable since it wasn't used, and moved the getElementsByTagName call out of the inner loop.
write_headers_to_excel(["headers1","headers3","headers7","etc"]);
function write_headers_to_excel(tableIDs) {
var myTableHead,
rowCount,
cols,
t,
i,
j,
rowOffset = 1,
ExcelSheet = new ActiveXObject("Excel.Sheet");
ExcelSheet.Application.Visible = true;
for (t=0; t < tableIDs.length; t++) {
myTableHead = document.getElementById(tableIDs[t]);
rowCount = myTableHead.rows.length;
for(i=0; i<rowCount; i++) {
cols = myTableHead.rows[i].getElementsByTagName("th");
for(j=0; j < cols.length; j++) {
ExcelSheet.ActiveSheet.Cells(i+rowOffset,j+1).Value = cols[j].innerHTML;
}
}
rowOffset += rowCount;
}
}
(No, I haven't tested it.)
You can get all tr elements by tag name
var rows = document.getElementsByTagName('tr');// get all rows of all tables
var table=0, TableRow=0;
for (i = 0; i < rows.length; i++) {
row = rows[i];
if (row.parentNode.tagName != 'THEAD' && row.parentNode.tagName != 'thead') {
table=table+1;
// do something here for headers
} else if (row.parentNode.tagName != 'TBODY' && row.parentNode.tagName != 'tbody')
{
TableRow=TableRow+1;
//do something here for rows
}
}