I am trying to build a table, where first cell is an image , next cells have some values, for which header is defined in thead.
The issue is that, in javascript, for every iteration of loop, it adds a new row, though I have not used <tr>
fetch("./static/js/data.json")
.then(response => response.json())
.then(data => {
for (var j = 0; j < 10; j++) {
let imgsrc = data.data[j].image;
document.querySelector("#userdata").innerHTML +=
`<tr><td rowspan="8"><img src=${imgsrc} width="150" height="150"></td>`;
for (var i = 0; i < 5; i++) {
let vmovieID = data.data[j].ingredients[i].contents;
document.querySelector("#userdata").innerHTML += `<td>${vmovieID}</td>`;
}
}
document.querySelector("#userdata").innerHTML += '</tr>'
});
<div class="panel-body">
<table id="userdata">
<thead>
<th>Image</th>
<th>Dry Matter</th>
<th>CP</th>
<th>GE</th>
<th>Calcium</th>
</thead>
</table>
</div>
Results are:
It's recommended to use Javascript to create and append the elements as variables, rather than appending strings of HTML at various points.
Additionally, you should confirm the DOM is loaded before targeting elements to avoid any bugs.
Refactored code with the points from above:
<script>
const fetchedData = fetch("./static/js/data.json");
window.addEventListener("DOMContentLoaded", (event) => {
fetchedData
.then((response) => response.json())
.then((data) => {
const table = document.getElementById("userdata");
for (var j = 0; j < 10; j++) {
const imgsrc = data.data[j].image;
const row = document.createElement("tr");
row.innerHTML = `<td rowspan="8"><img src=${imgsrc} width="150" height="150"></td>`;
for (var i = 0; i < 5; i++) {
const vmovieID = data.data[j].ingredients[i].contents;
const textContent = document.createTextNode(vmovieID);
const cell = document.createElement("td");
cell.appendChild(textContent);
row.appendChild(cell);
}
table.appendChild(row);
}
})
.catch((error) => {
console.error(new Error(error));
});
});
</script>
<div class="panel-body">
<table id="userdata">
<thead>
<th>Image</th>
<th>Dry Matter</th>
<th>CP</th>
<th>GE</th>
<th>Calcium</th>
</thead>
</table>
</div>
Related
I am currently using the script below to display CSV data in a HTML table.
function createDataElement(htmlTag, innerText, idParent) {
let node = document.createElement(htmlTag);
let textnode = document.createTextNode(innerText);
node.appendChild(textnode);
document.getElementById(idParent).appendChild(node);
}
function createHeaderElement(columnText) {
createDataElement("th", columnText, "tableHeader");
}
function createCellData(rowIndex, dataIndex, cellText) {
if (dataIndex === 0) {
let node = document.createElement("tr");
node.setAttribute("id", "row" + rowIndex);
document.getElementById("tableBody").appendChild(node);
createDataElement("td", cellText, "row" + rowIndex);
} else {
createDataElement("td", cellText, "row" + rowIndex);
}
}
var csv_url = 'https://www.sample-videos.com/csv/Sample-Spreadsheet-10-rows.csv';
Papa.parse(csv_url, {
download: true,
complete: function(results) {
for (let i = 0; i < results.data.length; i++) {
if (i === 0) {
for (let j = 0; j < results.data[i].length; j++) {
createHeaderElement(results.data[i][j]);
}
}
if (i > 0) {
for (let j = 0; j < results.data[i].length; j++) {
createCellData(i, j, results.data[i][j]);
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.3.1/papaparse.min.js"
integrity="sha512-EbdJQSugx0nVWrtyK3JdQQ/03mS3Q1UiAhRtErbwl1YL/+e2hZdlIcSURxxh7WXHTzn83sjlh2rysACoJGfb6g=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<table style="width: 90vw; margin: auto;" class="table table-sm table-striped">
<thead>
<tr id="tableHeader">
</tr>
</thead>
<tbody id="tableBody">
</tbody>
</table>
However, this only works for one HTML table. I have tried adding unique classes to the table but it will still only show one.
How do I adapt this code to show multiple tables from seperate CSV files?
<thead> and <tbody> are required as I am styling with Bootstrap.
Cannot loop through the different CSV files as there is content between each table, so need to be able to position the HTML tables separately.
Need to be able to add a unique class to the <table> for additional styling.
I have a problem with coding the sorting code for my database. With few data there is no problem but at this time I have to sort about 4000 data and it lasts about 20s, too long time.
By my check, the operation which lasts too much is insertBefore(...,...) function.
Can you please help me?
function sorting(list) {
var list_data = [];
var list_id = [];
for (var i = 0; i < list.length; i++) {
list_data[i] = Date.parse(list[i].cells[1].innerHTML);
list_id[i] = parseInt(list[i].cells[12].innerHTML);
}
//ordino gli array
for (var i = 0; i < list.length; i++) {
for (var j = 0; j < list.length-1; j++) {
if (list_data[j] > list_data[j+1]) {
tmp = list_data[j];
list_data[j] = list_data[j+1];
list_data[j+1] = tmp;
tmp = list_id[j];
list_id[j] = list_id[j+1];
list_id[j+1] = tmp;
}
}
}
//ordinato lista_id
var j = 0;
for (var i = 0; i < list.length; i++) {
j=i;
while (list_id[i] != parseInt(list[j].cells[12].innerHTML)) {
j++;
}
var target = list[i];
var newElement = list[j];
target.parentNode.insertBefore(newElement, target);
}
}
I have my table with 13 columns 0-12. The thirteenth column contains hidden cells with id of the data. I started with a bubblesort and then changed in this because i thought it could work better, but it still lasts 20s to sort. How suggested in comments I'm starting to think that a sort by server is better, but I don't know how to implement
I don't think it's the sorting. Created a snippet with time-logging, so you can see that a 5000 items long list's sorting is not that much of a problem.
Try setting up your project so that you control the data & only output the results (the snippet is a very simple example of that).
const tbody = document.getElementById('tbody')
let sortDesc = false
const rowHtml = (rowData) => {
return `
<tr>
<td>
${ rowData.first }
</td>
<td>
${ rowData.second }
</td>
</tr>
`
}
const setTable = (data) => {
tbody.innerHTML = ''
tbody.innerHTML = data.map(rowData => {
return rowHtml(rowData)
}).join('')
}
const sortData = (data, desc) => {
return data.sort((a, b) => {
if (desc) {
return b.first - a.first
} else {
return a.first - b.first
}
})
}
renderTable = (data) => {
console.time('sort data')
const d = sortData(data, sortDesc)
console.timeEnd('sort data')
sortDesc = !sortDesc
console.time('set table')
setTable(d)
console.timeEnd('set table')
}
let data = [];
(function() {
console.time('create items')
for (let i = 0; i < 5000; i++) {
data.push({
first: i,
second: `${ i }-${ i }`,
})
}
console.timeEnd('create items')
renderTable(data)
})();
const btnSort = document.getElementById('btnSort')
btnSort.addEventListener('click', function() {
renderTable(data)
})
<button id="btnSort">SORT</button><br />
<table id="table">
<tbody id="tbody"></tbody>
</table>
You can see from the time-logs that the real "expensive" stuff is actually putting out the HTML ("set table" in this case takes ~100 times as much time as "sort data").
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>
do I have a question?
Can we connect two APIs on the same JavaScript page and retrieve the data from both APIs in the same table?
I want to connect two APIs and display the results of both APIs in the same table. The API is the same, only the Token changes.
Here is the code in JS
function csvJSON(csv) {
const lines = csv.split('\n');
const result = [];
const headers = lines[0].split(',');
for (let i = 1; i < lines.length; i++) {
if (!lines[i]) continue;
const obj = {};
const currentline = lines[i].split(',');
for (let j = 0; j < headers.length; j++) {
obj[headers[j]] = currentline[j];
}
result.push(obj);
}
return result;
}
function boutonSubmit(){
bounceType = document.getElementById('BouncesType').value;
datestart = document.getElementById('dateS').value;
dateend = document.getElementById('dateE').value;
//bounceCode = getElementById('#dateS').value;
// TOTAL BOUNCES
// Récupération des donnèes et convertion
fetch(`https://api7.esv2.com/v2/Api/Bounces?apiKey=867xxxxxxxGN&startDate=${this.datestart}&endDate=${this.dateend}&bounceType=${this.bounceType}`)
.then((response) => response.text())
.then((txtResponse) => {
const data = csvJSON(txtResponse);
const tbody = document.querySelector('#user-table tbody');
tbody.innerHTML = '';
data.forEach( (user) => {
const entry = document.createElement('tr')
entry.innerHTML = `
<tr>
<td class="column1">${user.Date}</td>
<td class="column2">${user.Email}</td>
<td class="column3">${user.BounceCode}</td>
<td class="column3">${user["BounceType "]}</td>
</tr>
`;
tbody.appendChild(entry);
});
})}
Thank you in advance.
I have dynamic table, it contains 5 textbox controls, i am trying to retrieve label text of all controls. How can i do this.
THanks.
What i had tried:
var table = document.getElementById("ControlTable_");
if (table != null) {
var trlength = table.rows.length;
for (var i = 0; i < trlength; i++) {
var tclenght = table.cells.length;
for (var j = 0; j < tclenght; j++) {
var check = table.rows[i].cells[j].innerText;
}
}
}
Here i am getting innertext undefined
You can have a 2d representation of your table by using something like the following function:
const mapTo = (element, selector, callback) => Array.from(
element.querySelectorAll(selector),
callback
);
const extractText = td => td.textContent;
const tableAsJson = mapTo(
document,
'#ControlTable_ tr',
(row) => mapTo(row, 'td', extractText),
);
console.log('table', tableAsJson);
<table id="ControlTable_">
<tr>
<td>hello</td>
<td>World</td>
</tr>
<table>
if your td elements also contain something like
<label for="something">
Label
</label>
<input />
then something like this may help
const extractText = td => td.querySelector('label').textContent;
Just a note,
please make sure you attach relevant part of your dom structure while asking similar questions in future :)
Here is what I've tried:
var table = document.getElementById("ControlTable_");
if (table != null) {
var trlength = table.rows.length;
for (var i = 0; i < trlength; i++) {
// use this instead of table.cells, because each cell must be specified by a row
// i.e: table.rows[i].cells
var td = table.rows[i].getElementsByTagName('td');
for (var j = 0; j < td.length; j++) {
var check = table.rows[i].cells[j].innerText;
console.log(check);
}
}
}
You need to find and get value from the label in the table cell.
var table_rows = $('#ControlTable_ tr');
for (var i = 0; i < table_rows.length; i++) {
var row = table_rows[i];
var columns = $(row).find('td');
for (var j = 0; j < columns.length; j++) {
var label = $(columns[j]).find('label');
if (label.length > 0) {
var check = label[0].innerText;
console.log(check);
}
}
}
Check below link for working example.
https://jsfiddle.net/rgehlot99/d5zntL6c/2/
(Values can be found in console)