I have an image gallery on my website. It's powered by a script called gallery.js which runs on my page called gallery.html. It creates an html that contains the images I want to show.
However, I have to manually add the names of all the images to an array, which can be tedious. I need a way to scan the names of all the files in the /images/gallery directory, so that all I have to do is add images to the directory, and the script will detect them. How can I achieve this?
Here's the gallery.js code:
const table = document.getElementById("gallery");
/*
Filenames are added manually here
*/
const files = [ ... ];
const tableWidth = 4;
let htmlString = "";
for (let i = 0; i < files.length; i++) {
const filename = files[i]
// Start of row
if (i % tableWidth == 0) {
htmlString += "<tr>"
}
htmlString += `
<td>
<a href=\"images/gallery/${filename}.png\" target="_blank">
<img src=\"images/gallery/${filename}.png\">
</a>
</td>
`
// End of row
if (i % tableWidth == tableWidth - 1) {
htmlString += "</tr>"
}
}
table.innerHTML = htmlString
Related
I am working on a project where I call a certain API and in response I get back a json string with all the information. I need to find a way using javascript to display this json string into a table format. I got a very basic version of this running. However, the problem I am having is that I cannot find a way to display a image in this block of code.
results.html file:
<!DOCTYPE HTML>
<html>
<head>
<title>
How to convert JSON data to a
html table using JavaScript ?
</title>
<h1>Results: </h1>
<script src=
"https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js">
</script>
</head>
<body style = "text-align:center;" id = "body">
<h3>Showing resuls for: {{searchQuery}}</h3>
<p>{{responseText}}</p>
<br><br>
<table align = "center"
id="table" border="1">
</table>
<div id="header"></div>
<script>
var el_up = document.getElementById("GFG_UP");
var list = [];
list = "{{responseText|escapejs}}";
//console.log(list);
var titles = []
for (var i = 0; i < list.length-8; i++) {
if(list[i] == 't' && list[i+1] == 'i')
{
var title = '';
for(var j = (i+8); list[j] != ","; j++) {
title += list[j];
}
i = j;
console.log(title + ", ")
titles.push(title)
}
}
console.log(titles)
var images = []
for (var i = 0; i < list.length-8; i++) {
if(list[i] == 'h' && list[i+1] == 't')
{
var image = '';
for(var j = (i); list[j] != ","; j++) {
image += list[j];
}
i = j;
console.log(image + ", ");
var img = new Image();
img.src = image.slice(0, -1);
images.push(img);
}
}
console.log(images)
var restaurants = []
for (var i = 0; i < list.length-17; i++) {
if(list[i] == 'r' && list[i+1] == 'e' && list[i+2] == 's')
{
var restaurant = '';
for(var j = (i+17); list[j] != ","; j++) {
restaurant += list[j];
}
i = j;
console.log(restaurant + ", ")
restaurants.push(restaurant)
}
}
console.log(restaurants)
function createTable(tableData) {
var table = document.createElement('table');
var tableBody = document.createElement('tbody');
tableData.forEach(function(rowData) {
var row = document.createElement('tr');
console.log(typeof(cellData))
rowData.forEach(function(cellData) {
var cell = document.createElement('td');
cell.appendChild(document.createTextNode(cellData));
row.appendChild(cell);
});
tableBody.appendChild(row);
})
table.appendChild(tableBody);
document.body.appendChild(table);
};
var a = [titles, restaurants, images]
console.log(a)
createTable(a);
</script>
</body>
</html>
The function createTable is the one in question. It displays the text parts correctly. Im not sure how to get it to display images given the URLs of those images in a table.
output HTML file:
HTML output
You should show us the API response you are working with here.
Another thing is your createTable function expects to get table data. But onclick on your button pass there #table ID. Not sure if it should be like this.
Also you could run your JS script when all page is loaded:
window.onload = () => {
// Your JS script which should do something after page is loaded.
}
Finally it comes to the images. I think that you are not using img tag anywhere so your images simply won't be visible in the table. If you would like to see them just create img element and put it into td.
Few advices (not related with your question):
stop using console.log so much, place debugger statement in your code and debug it like a pro, if you don't know how just look for it in youtube,
please put your attention to a code style, it is a bit messy, if you have real trouble with it use ESlint to fix it for you.
EDIT
About images - if you want to create DOM element for img use code below instead of current one:
var img = document.createElement("IMG");
Than you can set src and other things like alt and so on:
img.src = imgUrlString;
How can I 'nest' innerHTML bindings? Is it a sanitation problem?
I am using angular to create a website to play chess. I am dynamically creating a table and putting it into the component with: <div [innerHTML]="board | safeHTML"> where board with a string with the HTML for the table in and safeHTML is a pipe that bypasses sanitisation so the HTML isn't just read as a string. The code to generate the table is at the bottom of the post.
I would like to then be able to change the contents of each cell in the table.
Here is an example cell:
<td id="n${uniqueNumber}" class="board" [innerHTML]="boardValues.${uniqueNumber}">{{boardValues.${uniqueNumber}}}</td>
boardValues is an object that contains all of the cell data.
The table correctly displays when bound with [innerHTML] however the cells don't and [innerHTML] is displayed as an attribute (e.g. this image). Similarly {{boardValues.value}} shows up as plain text rather than the value.
How can I 'nest' innerHTML bindings? Is it a sanitation problem?
My html:
Running that doesn't work but it shows my main loops (the important one is generateBoard)
Here is a stack blitz project that sort of works but doesn't have formatting for some reason. Still shows my issue
generateBoard(n, playColour) {
var tblBuild = ""
var tblFooter = "<tr><td id=\"blank\"></td>"
for (var i = 0; i < 8; i++) {
tblFooter += `<th class="coordinates letters">${String.fromCharCode(97+i)}</th>`
}
tblFooter += "</tr>"
for (var i = 0; i <= n; i++) {
tblBuild += `<tr class="n${n-i+1}">`
tblBuild += `<th class="coordinates numbers">${n-i+1}</th>`
for (var j = 0; j <= n; j++) {
var idValue = `n${8*(n-i)+j}`
//want to assign the innerHTML to an object
tblBuild += `<td id="n${idValue}" class="board" [innerHTML]="boardValues.${idValue}">{{boardValues.${idValue}}}</td>`
}
tblBuild += ("</tr>")
}
var tbl = "<table id=\"board\" class= \"board " + playColour + "\"" + "<tbody>" + tblBuild + "</tbody>" + tblFooter + "</table>"
console.log(tbl)
return tbl
}
generateBoardValues(n) {
interface LooseObject {
[key: string]: any
}
var boardValues: LooseObject = {}
console.log("running generateBoardvalues")
console.log("n", n)
for (var i = 0; i <= n; i++) {
for (var j = 0; j <= n; j++) {
boardValues[`n${8*(n-i)+j}`] = `n${8*(n-i)+j}`
console.log("generating boardValues", boardValues[`n${8*(n-i)+j}`])
}
}
boardValues.n15 = "maually set"
console.log("n15", boardValues.n15)
console.log(Object.keys(boardValues).sort((a, b) => Number(a.slice(1)) - Number(b.slice(1)))) //sorted values
return boardValues
}
n = 7
boardValues = generateBoardValues(n)
board = generateBoard(n, "white")
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<p [innerHTML]="boardValues.n12"></p> <!--Works-->
<div [innerHTML]="board | safeHTML"> <!-- displays table but not desired cell contents-->
This approche is very expensive. I wouldn't use innerHTML in your case. You should handle this in your template file and use *ngFor.
Trying to export a datatable HTML table to CSV which I have implemented some code using Javascript but this doesnt include my column headers which I want to add in. Also I want to exclude a particular column from the export but not sure how to tweak the current code I have working:
Created a JS FIDDLE with an example where the CSV is not including headers and want to hide the column 'Office' and 'Age' on export: https://jsfiddle.net/matp4bjn/
function download_csv_normal(csv, filename) {
var csvFile;
var downloadLink;
// CSV FILE
csvFile = new Blob([csv], { type: "text/csv" });
// Download link
downloadLink = document.createElement("a");
// File name
downloadLink.download = filename;
// We have to create a link to the file
downloadLink.href = window.URL.createObjectURL(csvFile);
// Make sure that the link is not displayed
downloadLink.style.display = "none";
// Add the link to your DOM
document.body.appendChild(downloadLink);
// Lanzamos
downloadLink.click();
}
function export_table_to_csv_normal(html, filename) {
var csv = [];
//var rows = document.querySelectorAll(".vs tr"); //gets paginated version
var rows = $("#tabledt").dataTable().fnGetNodes(); //gets all rows
//var rows = document.querySelectorAll("tabledt tr");
for (var i = 0; i < rows.length; i++) {
var row = [], cols = rows[i].querySelectorAll("td, th");
for (var j = 0; j < cols.length; j++)
row.push(cols[j].innerText);
csv.push(row.join(","));
}
// Download CSV
download_csv_normal(csv.join("\n"), filename);
}
function pad2(n) { return n < 10 ? '0' + n : n }
document.querySelector(".savebtn").addEventListener("click", function () {
var html = document.querySelector(".vs").outerHTML;
var date = new Date();
var file = "vstable_" + date.getFullYear().toString() + pad2(date.getMonth() + 1) + pad2(date.getDate()) + pad2(date.getHours()) + pad2(date.getMinutes()) + pad2(date.getSeconds()) + ".csv";
export_table_to_csv_normal(html, file);
});
HTML:
<button class="savebtn">
SAVE
</button>
Your code was working fine just needed to insert the header and implement condition for the columns to skip columns, you have made the columns to display none but that were still present in the code although not visible on the screen, that's why they were printing in the csv. In for loop you need to skip them.
Solution to your problem
for (var i = 0; i < rows.length; i++) {
//only run for the first iteration to set header row in the csv
if(i==0){
var row2 = [], cols2 = $('#tabledt thead tr')[0];
for(var i2 = 0; i2 < cols2['cells'].length; i2++){
//skip office and age columns
if(i2==2 || i2==3){continue;}
//add columns
row2.push(cols2['cells'][i2].innerText);
//console.log(cols2['cells'][i2].innerText);
}
//insert header
csv.push(row2.join(","));
}
var row = [], cols = rows[i].querySelectorAll("td");
for (var j = 0; j < cols.length; j++){
//skip office and age columns
if(j==2 || j==3){continue;}
//add columns
row.push(cols[j].innerText);
}
csv.push(row.join(","));
}
// Download CSV
download_csv_normal(csv.join("\n"), filename)
Below is the code for displaying webservices json response using li,ul tags dynamically it works fine but i need the same for table using tr,td the main thing to be noted is i need to save the onclick data here which is data(doc1) .help please thanks in advance
ul = $('#mydemo1');
ul.html(null);
for (var i = 0; i <= result.length; i++)
{
var doc1 = result[i];
li = $('<li/>').html(doc1.Name).data(doc1);
li.append($('<br/>'));
li.append($('<hr>'));
ul.append(li);
}
<ul id="mydemo1" style="text-align:left;"> </ul>
Try this...
var tableelement= $('#mydemo1'); //where mydemo1 is the id of some table in DOM
for (var i = 0; i < result.length; i++) {
tableelement.append(createRow(result[i]));
}
function createRow(rowObject) { //dynamically adding rows to the Table where each row contains the name
var trElement = "<tr>";
trElement += "<td>" + rowObject.Name + "</td>";
return trElement;
}
I've downloaded the following opennsf. I would like to add for each document uploaded the option to delete if you choosed wrong. I managed to add a button in the script but I don't know how to link it to the attachment.
Here is the edited code:
var files = document.getElementById('ynFileUploadMulti').files;
var html = '';
if (files && files.length > 0) {
if(dojo.byId("ynFileUploadInfo").innerHTML == "" ) {
html = '<table id="ynFileUpload" class="xspDataTableFileDownload" style="width:100%;margin-bottom:1em">';
html += '<thead style="color:#545454;"><tr><th style="font-weight:bold;width:46px">Size</th><th style="font-weight:bold">Files to Upload</th><th style="font-weight:bold">Delete</th></tr></thead><tbody style="color:#a0a0a0">';
}
else{
html += dojo.byId("ynFileUploadInfo").innerHTML;
html = html.replace("</tbody></table>", "");
}
for (var i = 0; i < files.length; i++) {
var file = files[i];
var fileSize = 0;
if (file.size > 1024 * 1024)
fileSize = (Math.round(file.size / (1024 * 1024))).toString() + ' MB';
else
fileSize = (Math.round(file.size / 1024)).toString() + ' KB';
html += '<tr><td>'+fileSize+'</td><td>'+file.name+'</td><td ><button onclick="myFunction()">x</button></td></tr>'
}
html += '</tbody></table>';
}
dojo.byId("ynFileUploadInfo").innerHTML = html;
} catch (e) {
console.log("ynUpload_onchange: "+e);
}
This code is in the ynUploader_onchange() function. But I guess I need to touch the other function too (the ynUploader_worker(.....) function)?? How can I achieve this?
You can use the property "Allow Delete" in the File Download control or you can place a button on the xpage/cc with the following code to get a handle on the uploaded files
var attList = document1.getAttachmentList("AttachmentRT");
for(var i=0; i<attList.size(); i++)
{
var att:String = attList[i];
// Here you can process every uploaded file
}
AttachmentRT ist the name of the notesrichtext field bound to the File Download