I'm learning javascript, hence my question might be a bit silly/simple.
Following a tutorial on Udemy, I was able to display a spreadsheet from Google Sheet in my website, using javascript to retrieve all rows contained in the document and pass them to a container in an HTML page.
This is great.
Now I would like to visualise only one row at a time, at a specific interval.
After some search I realised I can do this by using getElementById in conjunction with .innerHTML within a loop but I can't figure out what I am supposed to pass and where.
So, here is the HTML I'm using
<!DOCTYPE html>
<html><head><title>Testing Data from Sheets</title></head>
<body>
<div class="output"></div>
<script src="sheets.js"></script>
</body>
</html>
And here is the JS
const sheetID = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
const base = `https://docs.google.com/spreadsheets/d/${sheetID}/gviz/tq?`;
const sheetName = 'quotes';
let qu = 'Select D';
const query = encodeURIComponent(qu);
const url = `${base}&sheet=${sheetName}&tq=${query}`;
const data = [];
document.addEventListener('DOMContentLoaded', init);
const output = document.querySelector('.output');
function init() {
console.log('ready');
fetch(url)
.then(res => res.text())
.then(rep => {
//console.log(rep);
const jsData = JSON.parse(rep.substr(47).slice(0, -2));
console.log(jsData);
const colz = [];
jsData.table.cols.forEach((heading) => {
if (heading.label) {
colz.push(heading.label.toLowerCase().replace(/\s/g, ''));
}
})
jsData.table.rows.forEach((main) => {
//console.log(main);
const row = {};
colz.forEach((ele, ind) => {
//console.log(ele);
row[ele] = (main.c[ind] != null) ? main.c[ind].v : '';
})
data.push(row);
})
maker(data);
})
}
function maker(json) {
const div = document.createElement('div');
div.style.display = 'grid';
output.append(div);
let first = true;
json.forEach((el) => {
//console.log(ele);
const keys = Object.keys(el);
div.style.gridTemplateColumns = `repeat (${keys.length} ,'1fr')`;
if (first) {
first = false;
keys.forEach((heading) => {
const ele = document.createElement('div');
//ele.textContent = heading.toLocaleUpperCase();
ele.style.background = 'black';
ele.style.color = 'white';
ele.style.fontFamily = 'Helvetica';
div.append(ele);
})
}
keys.forEach((key) => {
const ele = document.createElement('div');
//ele.style.border = '1px solid #ddd';
ele.textContent = el[key];
ele.style.background = 'black';
ele.style.color = 'white';
ele.style.fontFamily = 'Helvetica';
div.append(ele);
})
console.log(keys);
})
}
Thanks heaps for helping!
I tried using the following from other messages I've found on the forum:
var i = 0; // the index of the current item to show
setInterval(function() { // setInterval makes it run repeatedly
document
.getElementById('output')
.innerHTML = jsData[i++];
if (i == jsData.length) i = 0;
}, 1000);
Related
The code currently takes from a .log I have, and grabs the username of players in my lobby and returns stats (# of wins, level, etc.) of the player onto an electron HTML page in a table.
Currently, it only shows one row, with only one players' stats included in the row. I am trying to make it so that each player will show up in stacking rows.
Picture of what the html electron window shows
I also want the rows to update every time "checkforupdates" is ran but I figured I should stick to one issue at a time.
const { app, BrowserWindow } = require('electron');
const fs = require('fs');
const prompt = require('prompt-sync')();
const Hypixel = require('hypixel-api-reborn');
const hypixel = new Hypixel.Client('77684239-5a07-4ea4-bc9c-2f07db9fddb7');
const filePath = 'C:/Users/****/AppData/Roaming/.minecraft/logs/blclient/minecraft/latest.log';
const keyword = 'ONLINE: ';
let lastTrimmed = '';
console.clear();
let win;
function createWindow() {
win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
});
win.loadFile('playerstats.html');
}
app.whenReady().then(createWindow);
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
app.on('ready', async () => {
const checkForUpdates = () => {
fs.promises.readFile(filePath, 'utf8')
.then(data => {
if (data.includes(keyword)) {
const index = data.lastIndexOf(keyword);
const line = data.substring(index);
const parts = line.split('\n');
const trimmed = parts[0].trim();
if (trimmed !== lastTrimmed) {
const names = trimmed.split(', ');
names.forEach(async name => {
const playerName = name.replace(keyword, '');
try {
const player = await hypixel.getPlayer(playerName);
const winstreak = player.stats.bedwars.winstreak || '?';
const finalKills = player.stats.bedwars.finalKills;
const fkdr = player.stats.bedwars.finalKDRatio;
const wins = player.stats.bedwars.wins;
const lvl = player.stats.bedwars.level;
win.webContents.executeJavaScript(`
document.getElementById("IGN").innerHTML = "${player}";
document.getElementById("wins").innerHTML = "${wins}";
document.getElementById("finalKills").innerHTML = "${finalKills}";
`);
console.log(`(${lvl})${playerName}: ws - ${winstreak} fkdr - ${fkdr} finals - ${finalKills} wins - ${wins}`);
} catch (err) {
console.error(`${playerName} Is Nicked`);
}
});
lastTrimmed = trimmed;
}
}
})
.catch(console.error);
};
setInterval(checkForUpdates, 1000);
});
<!DOCTYPE html>
<html>
<head>
<title>Player Stats</title>
</head>
<body>
<table>
<tr>
<th>IGN</th>
<th>Wins</th>
<th>Finals</th>
<th>FKDR</th>
</tr>
<tr>
<td id="IGN"></td>
<td id="wins"></td>
<td id="finalKills"></td>
<td id="fkdr"></td>
</tr>
</table>
<script>
const playerData = window.playerData;
document.querySelector("#IGN").textContent = playerData.player;
document.querySelector("#wins").textContent = playerData.wins;
document.querySelector("#final-kills").textContent = playerData.finalKills;
</script>
</body>
</html>
I tried looking at other forums regarding them, but every other user had more complex programs that integrated adding rows, and I couldn't figure out how to implement it into my code.
The forums i found on stackoverflow that were relevant to me only asked about a singular row.
I also thought about just adding 15 more table rows (I only need 16 rows max) but I couldn't figure out how to divert the "getElementById()" to fill out data in a different row.
I'm not sure I understood your problem, but, if you have an array of players, you could do something like:
<script>
for(let i = 0; i < players.lenght; i++) {
let table = document.getElementById("tableId")
let newTr = document.createElement("tr")
let td1 = document.createElement("td")
td1.innerText = players[i].player
let td2 = document.createElement("td")
td2.innerText = players[i].wins
let td3 = document.createElement("td")
td3.innerText = players[i].finalKills
tr.append(td1)
tr.append(td2)
tr.append(td3)
table.append(tr)
}
</script>
This script cycles trough an array of players and for each one of them creates a row in the table with the relative tds.
Notice that you need to give the table an id (tableId in my example) also notice that you could use thead and tbody tags.
i am trying to change dynamically background-image liner gradient.i am getting the liner gradient value in console but its not changing the display! if I put the value manually in CSS it works but does not work dynamically!! what is wrong I am doing?
let inputFirst = document.getElementById("input1");
let inputSecond = document.getElementById("input2");
let buttons = document.querySelectorAll("label");
let display = document.querySelector(".container");
let color1;
let color2;
let gradientPosition = "";
inputFirst.addEventListener("input", () => {
color1 = inputFirst.value;
});
inputSecond.addEventListener("input", () => {
color2 = inputSecond.value;
});
buttons.forEach((button) => {
button.addEventListener("click", () => {
gradientPosition = button.id;
display.style.backgorundImage = `linear-gradient(${gradientPosition}, ${color1},
${color2})`;
console.log(`linear-gradient(${gradientPosition}, ${color1}, ${color2})`)
;
});
});
//linear-gradient( to right, #671313, #af1d1d)
I have a Firebase Blog on my website. Now I want to post iframes on it.
My idea is to push them like the other p tags from JavaScript into the HTML and write the Link into the database without the frame tag...but it didnĀ“t work. Does anyone know why? Here is the Code without frame tag:
I have following JavaScript Code:
let postCollection = document.querySelector("#posts-collection");
const db = firebase.firestore();
function createPost(title, time, content) {
let div = document.createElement("div");
div.setAttribute("class", "col-md-4");
let h2 = document.createElement("h2");
let p = document.createElement("p");
let small = document.createElement("small");
h2.textContent = title;
small.textContent = time;
p.textContent = content;
div.appendChild(h2);
div.appendChild(small);
div.appendChild(p);
postCollection.appendChild(div);
}
// Get Posts
function getPosts() {
db.collection("posts")
.get()
.then(snapshot => {
snapshot.docs.forEach(docs => {
createPost(
docs.data().postName,
docs.data().createdAt,
docs.data().postContent
);
});
})
.catch(err => {
console.log(err);
});
}
getPosts();
And the following HTML for it:
<div class="blog" id="blog">
<h1>Blog</h1>
<!-- Example row of columns -->
<div class="row" id="posts-collection"></div>
</div>
Here is my idea to post iframes:
let postCollection = document.querySelector("#posts-collection");
const db = firebase.firestore();
function createPost(title, time, content, link) {
let div = document.createElement("div");
div.setAttribute("class", "col-md-4");
let h2 = document.createElement("h2");
let p = document.createElement("p");
let small = document.createElement("small");
let frame = document.createElement("iframe");
h2.textContent = title;
small.textContent = time;
p.textContent = content;
iframe.textContent = link
div.appendChild(h2);
div.appendChild(small);
div.appendChild(p);
div.appendChild(iframe)
postCollection.appendChild(div);
}
// Get Posts
function getPosts() {
db.collection("posts")
.get()
.then(snapshot => {
snapshot.docs.forEach(docs => {
createPost(
docs.data().postName,
docs.data().createdAt,
docs.data().postContent
);
});
})
.catch(err => {
console.log(err);
});
}
getPosts();
I'm trying to make a tic tac toe in javascript and i'm stuck at this problem. There's not a lot of code in my js file so here it is:
I have this function that makes my squares (bunch of divs in a container) have the same values that are stored in the array
const containercube = document.querySelector('.container');
const quadrados = containercube.children;
var gameboard= ["","","","x","","","","",""];
const update = () =>{
for (let i = 0; i < gameboard.length; i += 1) {
quadrados[i].innerHTML= gameboard[i];
}
}
So far so good, this is the part that works.
Now this is where I'm having trouble, I tried making a function that will add an "X" to the array position that corresponds to the square's index but for some reason it doesn't work:
const placeToken = (target, token) => {
gameboard[target] = token;
update();
};
containercube.addEventListener('click', function clickEvent(quadrados) {
const tokenze = "x";
placeToken(quadrados.target.dataset.index, tokenze);
update();
})
I think there is a better way to do this.
But here is a working code with minimum edits
const containercube = document.querySelector('.container');
const quadrados = containercube.children;
let gameboard= ["","","","x","","","","",""];
const update = () =>{
for (let i = 0; i < gameboard.length; i += 1) {
quadrados[i].innerHTML= gameboard[i];
}
}
update();
const placeToken = (target, token) => {
gameboard[target] = token;
update();
};
//Edited part
for (let i = 0; i < gameboard.length; i += 1) {
const tokenze = "x";
quadrados[i].addEventListener('click',()=>{
placeToken(i, tokenze);
//removed the update
});
}
Atm I am fetching data from an api and I need to compare the previous data values with the current every few seconds to indicate whether parking spots have come free, have been filled or stayed equal.
As mentioned before I am using the fetch function. Inside I create containers with createElement so each time the setInterval runs, it places the whole HTML again underneath the previous one. I'm looking for a way to be able to refresh the api data and overwrite that HTML.
Anyone know a solution for this problem?
My code looks like this
let url =
'https://datatank.stad.gent/4/mobiliteit/bezettingparkingsrealtime.json#';
let percent;
function fetchParkingData() {
fetch(url)
.then((resp) => resp.json())
.then(function(data) {
for(let i = 0; i < data.length; i++) {
let parkingData = {
name: data[i].name,
totalCapacity: data[i].parkingStatus.totalCapacity,
availableCapacity: data[i].parkingStatus.availableCapacity,
}
let mainDiv = document.getElementById('mainDiv');
let parkingDiv = document.createElement('div');
parkingDiv.className = 'parking-div';
let name = document.createElement('h2');
let totalCapacity = document.createElement('h3');
let availableCapacity = document.createElement('h4');
let indicator = document.createElement('p');
name.innerHTML = parkingData.name;
totalCapacity.innerHTML = 'Capaciteit: ' + parkingData.totalCapacity;
availableCapacity.innerHTML = 'Beschikbaar: ' + parkingData.availableCapacity;
mainDiv.appendChild(parkingDiv);
parkingDiv.appendChild(name);
parkingDiv.appendChild(totalCapacity);
parkingDiv.appendChild(availableCapacity);
percent = Math.floor(parkingData.availableCapacity / parkingData.totalCapacity * 100);
console.log(percent);
if(percent < 20) {
parkingDiv.style.backgroundColor = 'red';
} if(percent >= 20 && percent <= 50) {
parkingDiv.style.backgroundColor = 'orange';
} if(percent > 50) {
parkingDiv.style.backgroundColor = 'green';
}
};
})
.catch(function(error) {
// error handling
parkingDiv.innerHTML = 'Data could not be fetched';
});
}
setInterval(fetchParkingData , 2000);
Just clear the mainDiv before adding the data:
mainDiv.innerHTML = "";