cant pass data from textbox inside a loop - javascript

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)
}
})
}

Related

Foreach for array

I have an array which I populate like so
var list = [];
featureLayer.queryFeatures(querySnTR)
.then((result) => {
result.attachmentInfos.forEach((x) => {
list.push(uriString + "/" + x.id);
});
});
console.log("list", list);
I print out the list with console.log and it returns values inside.
Afterwards I do a foreach to go through all the elements inside and create a div for each of them. The thing is, it doesn't even go in the foreach function.
list.forEach((x) => {
console.log("CL", list);
console.log("x element", x);
var image = document.createElement("img");
image.src = x;
image.className = "queryImg";
document.getElementById("queryResults").appendChild(image);
});
It doesn't print out CL or x element for that matter.
Any ideas as to why?
The whole original code, for reference
startup: function () {
var _that = this;
_this = _that;
this.map.on("click", function (e) {
_this.map.graphics.clear();
identifyTask = new IdentifyTask("https://server/arcgis/rest/services/MUNICIPALITY_BUNDLE/ZK_KATASTAR_NA_ZELENILO/MapServer");
identifyParams = new IdentifyParameters();
identifyParams.tolerance = 10;
identifyParams.returnGeometry = true;
identifyParams.layerIds = [1];
identifyParams.layerOption = IdentifyParameters.LAYER_OPTION_ALL;
identifyParams.width = _this.map.width;
identifyParams.height = _this.map.height;
identifyParams.spatialReference = _this.map.spatialReference;
identifyParams.geometry = e.mapPoint;
identifyParams.mapExtent = _this.map.extent;
identifyTask.execute(identifyParams).then(function (data) {
objId = data[0].feature.attributes.objectid;
const querySnTR = {
where: "1 = 1",
outFields: ["*"]
};
var uriString = "https://server/arcgis/rest/services/MUNICIPALITY_BUNDLE/ZK_KATASTAR_NA_ZELENILO/MapServer/101/" + objId + "/attachments";
var featureLayer = new esri.layers.FeatureLayer(uriString);
featureLayer.queryFeatures(querySnTR)
.then((result) => {
result.attachmentInfos.forEach((x) => {
list.push(uriString + "/" + x.id);
});
});
const myFunction = async () => {
const { attachmentInfos } = await featureLayer.queryFeatures(querySnTR);
const list = attachmentInfos.map(({ id }) => `${uriString}/${id}`);
console.log("list", list);
list.forEach((x) => {
var image = document.createElement("img");
image.src = x;
image.className = "queryImg";
document.getElementById("queryResults").appendChild(image);
});
};
});
});
}
That's a trick on how the console works.
When you are executing the log the list is empty (100% sure) because you are populating it asynchronously. But the console has the reference to it and it will print it afterwards.
That's why your list is empty. You need to handle asynchrony here. You could work with an async/await approach or using promises, that will depend on the rest of your code, this is an example of how to do it with an async function (and rewritted it to modern javascript):
const myFunction = async () => {
const {attachmentInfos} = await featureLayer.queryFeatures(querySnTR);
const list = attachmentInfos.map(({id}) => `${uriString}/${id}`);
console.log("list", list);
list.forEach((x) => {
// put your code here
});
};
Edited:
Now that you share all your code you can simply do:
featureLayer.queryFeatures(querySnTR)
.then((result) => {
result.attachmentInfos.forEach((attachmentInfo) => {
var x = uriString + "/" + attachmentInfo.id
var image = document.createElement("img");
image.src = x;
image.className = "queryImg";
document.getElementById("queryResults").appendChild(image);
});
});
I would recommend you also to give vars meaningful names, not x but attachmentInfo, etc...

Uncaught TypeError: Cannot read properties of null (reading 'type')

I am trying to make an application that creates notifications once the user creates a new issue on a Gitlab repository it will display a new notification.
client.js
const socket = io()
socket.on('connect', function () {
console.log('Connected')
})
socket.on('disconnect', function () {
console.log('Disconnected')
})
socket.on('webhook-event', function (e) {
if (e.type === 'note') {
console.log('Type of webhook event: ' + e.type)
createNotification(e, 'New comment added to an issue')
updateAmountOfComments(e)
} else if (e.type === 'issue') {
if (e.state === 'closed') {
console.log('Type of webhook event: ' + e.type)
createNotification(e, 'Issue has been closed')
removeClosedIssue(e)
} else {
console.log('Type of webhook event: ' + e.type)
createNotification(e, 'New issue has been added')
newIssueEvent(e)
}
}
})
/** Function to create notifications
*/
const createNotification = (event, type) => {
const notification = document.getElementById('notificationList')
const notificationBox = document.createElement('div')
notificationBox.setAttribute('class', 'notificationBox')
// Header creation
const header = document.createElement('header')
header.setAttribute('class', 'notificationHeader')
header.innerHTML = `<h4>${type}</h4>`
notificationBox.append(header)
const content = document.createElement('div')
content.setAttribute('class', 'notificationContent')
const createdDate = document.createElement('p')
createdDate.innerText = 'Created date: ' + event.created_at
const link = document.createElement('a')
link.setAttribute('href', event.link)
link.innerText = 'Link to the issue'
const title = document.createElement('p')
title.innerText = 'Title: ' + event.title
const author = document.createElement('p')
author.innerText = 'Author: ' + event.author
if (event.type === 'note') {
const description = document.createElement('p')
description.innerText = 'Comment: ' + event.description
content.append(description)
const underIssue = document.createElement('p')
underIssue.innerText = 'Issue: ' + event.title
content.append(underIssue)
} else if (event.type === 'issue') {
content.append(title)
}
content.append(author)
content.append(createdDate)
content.append(link)
notificationBox.append(content)
notification.append(notificationBox)
}
/**
* Function for addressing new issues
*/
const newIssueEvent = (event) => {
const ul = document.getElementById('issues')
const li = document.createElement('li')
li.setAttribute('class', 'issues', 'id' + event.id)
const div = document.createElement('div')
div.setAttribute('id', 'ribbon')
const h4 = document.createElement('h4')
h4.setAttribute('id', 'title')
const text = document.createTextNode('Title: ' + event.title)
const spanBody = document.createElement('span')
spanBody.setAttribute('class', 'body')
const body = document.createTextNode('Description: ' + event.description)
const br = document.createElement('br')
const a = document.createElement('a')
a.setAttribute('href', event.link)
const links = document.createTextNode('Link to issue')
const pComment = document.createElement('p')
pComment.setAttribute('id', 'comments')
const comment = document.createTextNode('Comments: ' + 0)
const pAuthor = document.createElement('p')
pAuthor.setAttribute('id', 'author')
const author = document.createTextNode('Author: ' + event.author)
const pCreated = document.createElement('p')
pComment.setAttribute('id', 'createdAt')
const created = document.createTextNode('Created at: ' + event.created_at)
const pUpdated = document.createElement('p')
pComment.setAttribute('id', 'updatedAt')
const updated = document.createTextNode('Updated at: ' + event.created_at)
h4.appendChild(text)
spanBody.appendChild(body)
a.appendChild(links)
pComment.appendChild(comment)
pAuthor.appendChild(author)
pCreated.appendChild(created)
pUpdated.appendChild(updated)
div.appendChild(h4)
div.appendChild(spanBody)
div.appendChild(br)
div.appendChild(a)
div.appendChild(pComment)
div.appendChild(pAuthor)
div.appendChild(pCreated)
div.appendChild(pUpdated)
li.appendChild(div)
ul.insertBefore(li, ul.childNodes[0])
}
start.hbs
.
.
<div id="notificationList">
<h3>Notifications</h3>
<ul id="messages"></ul>
</div>
However, when I create a new issue it doesn't show any notification and in the console, it shows me this error
Error in the console

Airtable - How to change Api link Onclick JS?

I have this JS script, who call an Airtable API
var type = "Coupons"
var api_key = "?api_key=123456"
var maxRecords = "&maxRecords=10"
var filterByFormula = "&filterByFormula=%7Bvip_ou_50%7D%3D%2250%222"
var offset = "";
var url = "https://api.airtable.com/v0/app123456/" + type + api_key + maxRecords + "&offset=" + offset + "&sort%5B0%5D%5Bfield%5D=coupons_id";
async function catchJson() {
const response = await fetch(url);
const data = await response.json();....
as you see next, I created a function to change the value of the offset
var next_page = function () {
console.log(offset);
offset = data.offset;
console.log(offset);
}
page_suivante.onclick = next_page;
so I want to create a next page bouton Onclick that change the offset value
How can I do that !
Thanks for your help !
This is my result page for now : https://web.pinkmarket.co
Edit : this is my full JS with correction
var type = "Coupons"
var api_key = "?api_key=1234"
var maxRecords = "&maxRecords=10"
var filterByFormula = "&filterByFormula=%7Bvip_ou_50%7D%3D%2250%222"
var offset = "&offset"
var url = "https://api.airtable.com/v0/app1234/" + type + api_key + offset + "&sort%5B0%5D%5Bfield%5D=coupons_id";
const app = document.getElementById('root')
const card = document.createElement('div');
card.setAttribute('class', 'rightcontainer w-container')
app.appendChild(card)
async function catchJson() {
const response = await fetch(url);
const data = await response.json();
if (response.status >= 200 && response.status < 400) {
data.records.forEach(records => {
const records_length = document.getElementById('number')
records_length.innerHTML = 'Liste de coupons <br> <span class="text-span-2">Ouvrir la Map</span>'
const property_card = document.createElement('a')
property_card.setAttribute('class', 'property-card left w-inline-block w-clearfix')
property_card.style.background = "-webkit-gradient(linear, left top, left bottom, color-stop(29%, hsla(0, 0%, 100%, 0)), color-stop(68%, rgba(0, 0, 0, 0.5))), url('" + records.fields.image_url + "');";
property_card.style.background = "linear - gradient(180deg, hsla(0, 0 %, 100 %, 0) 29 %, rgba(0, 0, 0, 0.5) 68 %), url('" + records.fields.image_url + "');"
const image_quantity_div = document.createElement('div')
image_quantity_div.setAttribute('class', 'image-quantity-div')
const price_text = document.createElement('h1')
price_text.setAttribute('class', 'price-text')
price_text.innerText = records.fields.titre
const div_lower_info = document.createElement('div')
div_lower_info.setAttribute('class', 'div-lower-info w-clearfix')
const info_text = document.createElement('div')
info_text.setAttribute('class', 'info-text')
info_text.innerText = records.fields.compagny_name + ' - ' + records.fields.description_sub.substring(0, 100) + '...'
const view_button = document.createElement('div')
view_button.setAttribute('class', 'view-button')
view_button.textContent = 'Plus'
root.appendChild(card);
card.appendChild(property_card);
property_card.appendChild(image_quantity_div);
property_card.appendChild(price_text);
div_lower_info.appendChild(info_text);
div_lower_info.appendChild(view_button);
property_card.appendChild(div_lower_info);
})
const offset_page = document.createElement('a');
offset_page.setAttribute('class', 'button-2 left-aligned w-button')
offset_page.setAttribute('id', 'next')
offset_page.setAttribute('href', data.offset)
offset_page.innerHTML = "Page Suivante"
card.appendChild(offset_page);
});
}
else {
const errorMessage = document.createElement('a')
errorMessage.textContent = `Bah, ça ne marche pas !`
app.appendChild(errorMessage)
}
}
document.addEventListener('DOMContentLoaded', function () {
catchJson()
});
<div class="premium-properties-div" id="root">
</div>
If I got your question right you want to run the next_page() function on button click. If so this code does that:
EDIT: As discussed in the comments the below code will update your offset variable without restarting.
var type = "Coupons"
var api_key = "?api_key=123456"
var maxRecords = "&maxRecords=10"
var filterByFormula = "&filterByFormula=%7Bvip_ou_50%7D%3D%2250%222"
//I assume you set the ofset to "" because as discussed in the comments you get the offset value after calling the api the first time
var offset = "";
var url = "https://api.airtable.com/v0/app123456/" + type + api_key + maxRecords + "&offset=" + offset + "&sort%5B0%5D%5Bfield%5D=coupons_id";
var dynamicOffset = []
//your finalData
var finalData = []
//on click of button the api starts running.
document.getElementById("nextPageBtn").addEventListener('click', function() {
getNewOffset()
});
function getNewOffset() {
async function catchJson() {
const response = await fetch(url);
const data = await response.json();
//as disscussed in the comments ```data``` is the offset value you get back so now insert the offset value to the URL and run it again and again untill no ofset value is returned
//so first check if data is not empty then if not lets push every new offset data returned to an array called ```dynamic Offset``` but also empty the array before pushing then call the second fetch method.
if (data != "" && data != null) {
dynamicOffset = []
dynamicOffset.push(data)
secondFetch()
} else {
console.log('not more new offset')
//Log your final data
console.log(finalData)
}
}
}
function secondFetch() {
//insert the new Offset Value
const modifiedURL = "https://api.airtable.com/v0/app123456/" + type + api_key + maxRecords + "&offset=" + dynamicOffset[0] + "&sort%5B0%5D%5Bfield%5D=coupons_id";
//call fetch
async function catchJson() {
const response = await fetch(modifiedURL);
const data = await response.json();
//we didn't discuss how you want your final data to be saved but assuming your data are strings lets push them all to ```finalDataArray``` but you can save them in your desierd way. Note we are not clearing array here becuase we are appending not writing.
//just a precaution statment
if (data != "" && data != null) {
finalData.push(data)
//lets setTimeout of 1 second to avoid memory overload
setTimeout(() => {
//call getNewOffset() again
getNewOffset()
}, 1000)
}
}
}
<button id="nextPageBtn">Next Page</button>

How can I get the data from an api request from the then() method, so I can process the data outside of the function?

How can I get the data from an api request from the then() method, so I can process the data outside
of the function. Can I store the data in a state object for example and how to do that.
// openweathermap async await api request
async function getData(){
try{
const url = `http://api.openweathermap.org/data/2.5/forecast?
q=${city}&units=metric&appid=${key}`;
const data = await axios(url)
console.log(data)
return data;
}catch(error){
temperature.insertAdjacentHTML('afterend', '<div id="error">Oooops
something went wrong!</div>');
}
}
getData().then( data => {
const temp = data.data.list[0].main.temp;
temperature.textContent = temp.toFixed(1) + ' \xB0' + "C ";
const temp2 = data.data.list[1].main.temp;
temperature2.textContent = temp2.toFixed(1) + ' \xB0' + "C ";
const forecast = data.data.list[0].weather[0].description;
foreCast.textContent = forecast.toLowerCase();
const forecast2 = data.data.list[1].weather[0].description;
foreCast2.textContent = forecast2.toLowerCase();
const icon = data.data.list[0].weather[0].icon
weatherIcon.insertAdjacentHTML('afterbegin', `<img
src="http://openweathermap.org/img/w/${icon}.png">`)
const icon2 = data.data.list[1].weather[0].icon
weatherIcon2.insertAdjacentHTML('afterbegin', `<img
src="http://openweathermap.org/img/w/${icon2}.png">`)
day.textContent = newTime;
day2.textContent = newTime2;
})
Should axios(url) be axios.get(url)?
Then you can handle the data inside the callback function:
getData().then(data => console.log(data))
Get data is already an async function which means it returns a Promise. Just assign variable data by calling getData function. This should be done in an async function.
(async () => {
const data = await getData();
const temp = data.data.list[0].main.temp;
temperature.textContent = temp.toFixed(1) + ' \xB0' + "C ";
const temp2 = data.data.list[1].main.temp;
temperature2.textContent = temp2.toFixed(1) + ' \xB0' + "C ";
const forecast = data.data.list[0].weather[0].description;
foreCast.textContent = forecast.toLowerCase();
const forecast2 = data.data.list[1].weather[0].description;
foreCast2.textContent = forecast2.toLowerCase();
const icon = data.data.list[0].weather[0].icon
weatherIcon.insertAdjacentHTML('afterbegin', `<img src="http://openweathermap.org/img/w/${icon}.png">`)
const icon2 = data.data.list[1].weather[0].icon
weatherIcon2.insertAdjacentHTML('afterbegin', `<img src="http://openweathermap.org/img/w/${icon2}.png">`)
day.textContent = newTime;
day2.textContent = newTime2;
})();
Found a solution: Create a class with the getData() method, create a function to control the data and store it in the state object.
// Create class
class Weather {
constructor(){
}
async getData(){
try{
const url = `http://api.openweathermap.org/data/2.5/forecast?
q=${city}&units=metric&appid=${key}`;
const data = await axios(url)
this.data = data
}catch(error){
temperature.insertAdjacentHTML('afterend', '<div id="error">Oooops something
went wrong!</div>');
}
}
}
// Create state object, declare function to get data and store data in state object
const state = {}
const controlData = async () => {
state.data = new Weather()
await state.data.getData()
const temp = state.data.data.data.list[0].main.temp;
temperature.textContent = temp.toFixed(1) + ' \xB0' + "C ";
const temp2 = state.data.data.data.list[1].main.temp;
temperature2.textContent = temp2.toFixed(1) + ' \xB0' + "C ";
const forecast = state.data.data.data.list[0].weather[0].description;
foreCast.textContent = forecast.toLowerCase();
const forecast2 = state.data.data.data.list[1].weather[0].description;
foreCast2.textContent = forecast2.toLowerCase();
const icon = state.data.data.data.list[0].weather[0].icon
weatherIcon.insertAdjacentHTML('afterbegin', `<img
src="http://openweathermap.org/img/w/${icon}.png">`)
const icon2 = state.data.data.data.list[1].weather[0].icon
weatherIcon2.insertAdjacentHTML('afterbegin', `<img
src="http://openweathermap.org/img/w/${icon2}.png">`)
day.textContent = newTime;
day2.textContent = newTime2;
let sRise = convertTime(state.data.data.data.city.sunrise);
let sSet = convertTime(state.data.data.data.city.sunset);
sunRise.textContent = `Sunrise ${sRise}`;
sunSet.textContent = `Sunset ${sSet}`;
}
controlData()

Nodejs Scraper isn't moving to next page(s)

Hey guys this is a follow on from my other question, i have created a Nodejs Scraper that doesnt seem to want to go through the pages, it stays on the first. my source code is below
const rp = require('request-promise');
const request = require('request');
const otcsv = require('objects-to-csv');
const cheerio = require('cheerio');
//URL To scrape
const baseURL = 'xxx';
const searchURL = 'xxxx';
//scrape info
const getCompanies = async () => {
// Pagination test
for (let index = 1; index <= 20; index = index + 1) {
const html = await rp.get(baseURL + searchURL + index);
const $ = await cheerio.load(html);
console.log("Loading Pages....");
console.log("At page number " + index);
// end pagination test
//const htmls = await rp(baseURL + searchURL);
const businessMap = cheerio('a.business-name', html).map(async (i, e) => {
const link = baseURL + e.attribs.href;
const innerHtml = await rp(link);
const emailAddress = cheerio('a.email-business', innerHtml).prop('href');
const name = e.children[0].data || cheerio('h1', innerHtml).text();
const phone = cheerio('p.phone', innerHtml).text();
return {
// link,
name,
emailAddress: emailAddress ? emailAddress.replace('mailto:', '') : '',
phone,
}
}).get();
return Promise.all(businessMap);
}
};
console.log("Finished Scraping.... Now Saving!")
//save to CSV
getCompanies()
.then(result => {
const transformed = new otcsv(result);
return transformed.toDisk('./output.csv');
})
.then(() => console.log('Scrape Complete :D '));
As you can see I have tried a few different ways to make this happen so any help will be gratefully appreciated.

Categories

Resources