I'm trying to display some data from google - the script below works for pulling the data - but I want to add a delay to it running so there's time for it to process the data when a change is made.
I've tried adding setTimeout() to the whole piece of code, but when I add it it turns back blank.
Any ideas?
https://codepen.io/jameswill77/pen/PoREWmK
const sheetId = '1Fa0SgniGrmW_0DCQriR6-XYj2eiRayTK_9HZG9BQYok';
const base = `https://docs.google.com/spreadsheets/d/${sheetId}/gviz/tq?`;
const sheetName = 'sheet 1';
const query = encodeURIComponent('Select *')
const url = `${base}&sheet=${sheetName}&tq=${query}`
const data = []
document.addEventListener('DOMContentLoaded', init)
const output = document.querySelector('.output')
function init() {
fetch(url)
.then(res => res.text())
.then(rep => {
//Remove additional text and extract only JSON:
const jsonData = JSON.parse(rep.substring(47).slice(0, -2));
console.log(rep)
const colz = [];
const tr = document.createElement('tr');
//Extract column labels
jsonData.table.cols.forEach((heading) => {
if (heading.label) {
let column = heading.label;
colz.push(column);
const th = document.createElement('th');
th.innerText = column;
tr.appendChild(th);
}
})
output.appendChild(tr);
//extract row data:
jsonData.table.rows.forEach((rowData) => {
const row = {};
colz.forEach((ele, ind) => {
row[ele] = (rowData.c[ind] != null) ? rowData.c[ind].v : '';
})
data.push(row);
})
processRows(data);
})
}
function processRows(json) {
json.forEach((row) => {
const tr = document.createElement('tr');
const keys = Object.keys(row);
keys.forEach((key) => {
const td = document.createElement('td');
td.textContent = row[key];
tr.appendChild(td);
})
output.appendChild(tr);
})
}
<div class="output"></div>
document.addEventListener('DOMContentLoaded', () => {
setTimeout(init, 3000);
});
Is this behaviour what you are looking for?
Related
I'm making a request to questions.json, but I'm unsure how to capture the data returned by the response call. The JSON file is just an object but when I try to call response.names to get it, it's telling me response is not defined? Didn't I define it when I called the json function on it?
I'm thinking maybe because it's a promise, it's not technically defined? Unsure.
Here's my code:
fetchQuestions();
function createCategory(category, questions) {
const categoryDiv = document.createElement('div');
div.classList.add('category');
const h2 = document.createElement('h2');
h2.textContent = category;
categoryDiv.append(h2);
questions.forEach(question => {
const questionDiv = document.createElement('div');
questionDiv.classList.add('question');
const statusDiv = document.createElement('div');
statusDiv.classList.add(questions.status);
questionDiv.append(statusDiv);
const h3 = document.createElement('h3');
h3.textContent = question.name;
questionDiv.append(h3);
categoryDiv.append(questionDiv);
});
return categoryDiv;
}
function fetchQuestions() {
const myRequest = new Request('questions.json');
fetch(myRequest)
.then(response => response.json())
.then(getQuestionsByCategory(response.names))
.catch(console.error);
}
function getQuestionsByCategory(questions) {
const questionsByCategory = {};
questions.forEach(question => {
if (questionsByCategory.hasOwnProperty(question.category)) {
questionsByCategory[question.category].push(question);
} else {
questionsByCategory[question.category] = [question];
}
});
return questionsByCategory;
}
It's my first to do app with filter method. All of these functions works fine, but I have problem when I'm try search something in second input, when I search for one element I lose the rest of the array. How Can I fix that xD ?
const input = document.querySelector('input')
const add = document.querySelector('.addNew')
const clear = document.querySelector('.clear')
const div = document.querySelector('.container')
const search = document.querySelector('.search')
let words = [];
const newTask = () => { // add new task
if(input.value === '') return;
const li = document.createElement('li')
const pe = document.createElement('p')
const btnsComplete = document.createElement('button')
const btnDelete = document.createElement('button')
div.appendChild(li)
li.appendChild(pe)
li.appendChild(btnsComplete)
li.appendChild(btnDelete)
pe.textContent = input.value
btnsComplete.textContent = 'Done'
btnDelete.textContent = 'Cancel'
input.value = '';
words.push(li)
btnsComplete.addEventListener('click',function(e){ // complete
pe.classList.toggle('line')
})
btnDelete.addEventListener('click',function(e){ //cancel
e.target.parentNode.remove()
words.pop(e.target)
document.querySelector('.info').textContent = `Twoja lista składa się z ${words.length} elementów`
})
document.querySelector('.info').textContent = `Twoja lista składa się z ${words.length} elementów`
}
const clearing =() => { //remove all todos
div.innerHTML = ''
words.length = 0
document.querySelector('.info').textContent = `Twoja lista składa się z ${words.length} elementów`
}
const searchTask = (e) => { //search task
const searchText = e.target.value.toLowerCase();
words = words.filter(li => li.textContent.toLowerCase().includes(searchText))
div.textContent =''
words.forEach(li => div.appendChild(li))
}
search.addEventListener('input', searchTask)
clear.addEventListener('click', clearing)
add.addEventListener('click', newTask)
so im getting my data from Darksky api, i have elements generated with loops, and i update the text content of those via loop of the api data array. whenever i search, everthing else static changes values, not the one inside the loop
function search(ele) {
if(event.key === 'Enter') {
var url3 = 'https://geocode.xyz/' + ele.value +'?json=1' //this is where i convert the long,lat to city name
fetch(url3)
.then(z => z.json())
.then(z => {
locres = (z.latt+','+z.longt)
render()
renderLoop()
})
}
}
function renderLoop(){
var proxyUrl = 'https://cors-anywhere.herokuapp.com/';
var url1 = 'https://api.darksky.net/forecast/c34e122a56ae30a3090687878bce72c3/' + locres + '?units=auto' //i have to use proxy because of CORS
fetch(proxyUrl + url1)
.then(x => x.json())
.then(x => {
var skycons = new Skycons({"color": "white"});
skycons.set("icon0", Skycons = x.currently.icon);
skycons.play();
console.log(x.daily.data)
for(i=0;i<8;i++){
console.log(x.daily.data[i].time)
console.log(x.daily.data[i].summary)
const divs = document.createElement('div')
divs.className = ('week-day-container')
const divsholdr = document.querySelector('.week-stage')
const canv = document.createElement('canvas')
canv.id = ('icons'+(i+1))
canv.height = 100
canv.width = 70
divs.appendChild(canv)
divsholdr.appendChild(divs)
const dates = document.createElement('p')
dates.textContent = x.daily.data[i].time
divs.appendChild(dates)
const temp = document.createElement('p')
temp.textContent = 'High: '+ x.daily.data[i].temperatureHigh + 'Low: ' + x.daily.data[i].temperatureLow
divs.appendChild(temp)
const summ = document.createElement('p')
summ.textContent = x.daily.data[i].summary
divs.appendChild(summ)
}
for(y=0;y<8;y++){
skycons.set('icons'+(y+1), Skycons = x.daily.data[y].icon)
}
})
}
Working on scraping TV episodes from IMDb (Breaking Bad in the example below). The problem is when implementing the for loop, only the first iteration of j is returned.
My assumption is the return statement is exiting the loop but I'm unsure how to fix the problem.
const fetch = require('node-fetch');
const cheerio = require('cheerio');
const searchUrl = 'https://www.imdb.com/find?s=tt&ttype=tv&ref_=fn_tv&q=';
const movieUrl = 'https://www.imdb.com/title/';
async function getEpisodes(searchTerm) {
//const imdbID = await getID(searchTerm);
//const numSeasons = await getSeasons(imdbID);
const imdbID = 'tt0903747';
const numSeasons = 5;
const episodes = [];
for (let j = 1; j <= numSeasons; j++) {
return fetch(`${movieUrl}${imdbID}/episodes?season=${j}`)
.then(response => response.text())
.then(body => {
const $ = cheerio.load(body);
$('div[itemProp="episodes"]').each(function (i, element) {
const airdate = $(element).find('.airdate').text().trim();
const episodeTitle = $(element).find('a[itemProp="name"]').text().trim();
const votes = $(element).find('.ipl-rating-star__total-votes').text().trim().match(/\(([^)]+)\)/)[1];
const rating = $(element).find('.ipl-rating-star ').find('.ipl-rating-star__rating').text().trim().slice(0, 3);
episode = {
season: j,
episodeTitle,
airdate,
votes,
rating
};
episodes.push(episode);
});
return episodes; //Only season 1 is returned.
});
}
}
Let's rewrite the function using async await style. This way we make sure we fire fetch numSeasons times, await all of them, and process them one by one.
async function processResponse(response, season) {
const body = await response.text();
const $ = cheerio.load(body);
let episodes = [];
$('div[itemProp="episodes"]').each(function (i, element) {
const airdate = $(element).find('.airdate').text().trim();
const episodeTitle = $(element).find('a[itemProp="name"]').text().trim();
const votes = $(element).find('.ipl-rating-star__total-votes').text().trim().match(/\(([^)]+)\)/)[1];
const rating = $(element).find('.ipl-rating-star ').find('.ipl-rating-star__rating').text().trim().slice(0, 3);
episode = {
season,
episodeTitle,
airdate,
votes,
rating
};
episodes.push(episode);
});
return episodes;
}
async function getEpisodes(searchTerm) {
//const imdbID = await getID(searchTerm);
//const numSeasons = await getSeasons(imdbID);
const imdbID = 'tt0903747';
const numSeasons = 5;
let promises = [];
for (let j = 1; j <= numSeasons; j++) {
promises.push(fetch(`${movieUrl}${imdbID}/episodes?season=${j}`));
}
const responses = await Promise.all(promises);
return responses.reduce((accumulator, response, index) => {
return accumulator.concat(await processResponse(response, index + 1));
}, []);
}
Is it possible / is there a convenience function to copy a range of cells and/or a whole worksheet from one Excel sheet to another using ExcelJS?
copying worksheets with Merged cells
var ws1 = workbook.getWorksheet('demo');
let copySheet = workbook.addWorksheet('newdemo');
copySheet.model = Object.assign(ws1.model, {
mergeCells: ws1.model.merges
});
copySheet.name = 'new demo';
var sourceWorkbook= new Excel.Workbook();
var sourceWorksheet;
sourceWorkbook.xlsx.readFile("template.xlsx").then(function(){
sourceWorksheet= sourceWorkbook.getWorksheet(1);
var targetWorkbook = new Excel.Workbook;
var targetSheet = targetWorkbook.addWorksheet();
sourceWorksheet.eachRow((row, rowNumber) => {
var newRow = targetSheet.getRow(rowNumber);
row.eachCell((cell, colNumber) => {
var newCell = newRow.getCell(colNumber)
for(var prop in cell)
{
newCell[prop] = cell[prop];
}
})
})
This is what I done with my project. It works well.
You can copy the whole worksheet from one Excel sheet to another using ExcelJS. Below code will work
const Excel = require('exceljs');
async function copyExcel() {
let targetWorkbook = new Excel.Workbook();
targetWorkbook = await targetWorkbook.xlsx.readFile('target.xlsx');
const targetWorksheet = targetWorkbook.getWorksheet('target'); // you can add new sheet as well.
let sourceWorkbook = new Excel.Workbook();
sourceWorkbook = await sourceWorkbook.xlsx.readFile('source.xlsx');
const sourceWorksheet = sourceWorkbook.getWorksheet('source');
sourceWorksheet.eachRow({ includeEmpty: false }, (row, rowNumber) => {
var targetRow = targetWorksheet.getRow(rowNumber);
row.eachCell({ includeEmpty: false }, (cell, cellNumber) => {
targetRow.getCell(cellNumber).value = cell.value;
});
row.commit();
});
await targetWorkbook.xlsx.writeFile('target.xlsx');
}
copyExcel();