Cant work out out fetch api of met office to html page - javascript

Been tasked with displaying details from the met office data point api using javascript onto a html page and have only a brief knowledge of using the fetch api function.The met office uses users keys for their data point that needs inserted into the url in order to access the data. Im currently using the url that displays location information and would like to start with displaying the longitude and lattidide.
Ive wrote a html page and used an example I found of using fetch online but still no luck of displaying an data.
async function getLocations() {
let url = 'http://datapoint.metoffice.gov.uk/public/data/val/wxfcs/all/json/sitelist?key=231f9773-2c4f-4afd-beee-6878c1c63f0a';
try {
let res = await fetch(url);
return await res.json();
} catch (error) {
console.log(error);
}
}
async function renderLocations() {
let locations = await getLocations();
let html = '';
locations.forEach(Location => {
let htmlSegment = `<div class="Location">
<h2>${Location.longitude} ${Location.latitude}</h2>
</div>`;
html += htmlSegment;
});
let container = document.querySelector('.container');
container.innerHTML = html;
}
renderLocations();
<div class="container"></div>

By trying out the API endpoint by myself and logging out the result of getLocations(), I see that the structure of the Object looks like:
{
Locations: {
Location: [
...data
]
}
}
So to fix your code, change from
locations.forEach(Location => {
to
locations.Locations.Location.forEach(Location => {

Related

I have embedded visuals from a power bi report, is it possible to fetch the data inside these?

I have these visuals: that I want to fetch only the title "Førstehjelp" and the value "50" from, without the frame around etc. Is this possible with Javascript or do I have to edit the power bi report to make it look the way I want?
You can use visual.exportData to export data from a report visual.
Follow the below steps:
Get the Visual name using the getVisuals() API.
try {
// Retrieve the page collection.
const pages = await report.getPages();
// Retrieve the active page.
let activePage = pages.filter(function (page) {
return page.isActive;
})[0];
const visuals = await page.getVisuals();
console.log(
visuals.map(function (visual) {
return {
name: visual.name,
type: visual.type,
title: visual.title,
layout: visual.layout
};
})); catch (errors) {
console.log(errors); }
After you the get the Visual name, use the exportData API to export the data.
// Retrieve the target visual.
let visual = visuals.filter(function (visual) {
return visual.name === "VisualName";
})[0];
const result = await visual.exportData(models.ExportDataType.Summarized);
console.log(result.data); }
Reference:
https://learn.microsoft.com/javascript/api/overview/powerbi/export-data

Simplifying JS query from JSON API

I'm trying to display some data from a API, using similar to the below example.
I need to feed in data such as a Video ID from a CMS, which will then retrieve additional data from the API about the video.
The below example works, but I'm not sure I've written it in the best way - and I would like to be able to set a variable using a Video ID from the CMS's front end template string. Below I am having to repeat the Video ID in order to get it to work - and I'm struggling to simplify this.
Any help appreciated!
async function getSomething() {
let request = {
item: {
name: "example",
colour: "red"
},
video: ["12345"]
};
let url = new URL("https://example.com");
url.searchParams.append('data', JSON.stringify(request));
let response = await fetch(url);
let data = await response.json();
console.log(data.video);
return data;
}
getSomething().then(data =>
document.querySelector('[data-video-id]').innerHTML = data.video.12345.label
);

Office.js API for PowerPoint (Preview)

I am trying to use the new Office.js API for Powerpoint which is currently in preview. I am unable to get anything working with the PowerPoint.run() method call because it seems to behave differently that the ones in Excel and Word. Could anyone help me find a working way to call the SlideCollection.getCount() method referenced here?
https://learn.microsoft.com/en-us/javascript/api/powerpoint/powerpoint.slidecollection?view=powerpoint-js-preview
Sample code (assumed I needed to load items first before trying to get the count):
PowerPoint.run(function (context) {
var properties = context.presentation.slides.items;
context.load(properties);
return context.sync()
.then(function() {
console.log(properties);
})
.catch((error) => console.log(error));
})
Here is a call to slides.getCount() which should work
PowerPoint.run(async (context) => {
context.presentation.load("slides");
await context.sync();
var slides = context.presentation.slides;
var slideCount = slides.getCount();
await context.sync();
console.log("There are ", slideCount.value, " slides in this presentation");
}
PowerPoint.run(async function (context) {
context.presentation.load("slides");
await context.sync();
const slide = context.presentation.slides.getItemAt(0);
slide.load("id");//you just load any property from PPT object model and then sync
await context.sync();
console.log(slide.id);
});

Pulling Articles from Large JSON Response

I'm trying to code something which tracks the Ontario Immigrant Nominee Program Updates page for updates and then sends an email alert if there's a new article. I've done this in PHP but I wanted to try and recreate it in JS because I've been learning JS for the last few weeks.
The OINP has a public API, but the entire body of the webpage is stored in the JSON response (you can see this here: https://api.ontario.ca/api/drupal/page%2F2020-ontario-immigrant-nominee-program-updates?fields=body)
Looking through the safe_value - the common trend is that the Date / Title is always between <h3> tags. What I did with PHP was create a function that stored the text between <h3> into a variable called Date / Title. Then - to store the article body text I just grabbed all the text between </h3> and </p><h3> (basically everything after the title, until the beginning of the next title), stored it in a 'bodytext' variable and then iterated through all occurrences.
I'm stumped figuring out how to do this in JS.
So far - trying to keep it simple, I literally have:
const fetch = require("node-fetch");
fetch(
"https://api.ontario.ca/api/drupal/page%2F2020-ontario-immigrant-nominee-program-updates?fields=body"
)
.then((result) => {
return result.json();
})
.then((data) => {
let websiteData = data.body.und[0].safe_value;
console.log(websiteData);
});
This outputs all of the body. Can anyone point me in the direction of a library / some tips that can help me :
Read through the entire safe_value response and break down each article (Date / Title + Article body) into an array.
I'm probably then just going to upload each article into a MongoDB and then I'll have it checked twice daily -> if there's a new article I'll send an email notif.
Any advice is appreciated!!
Thanks,
You can use regex to get the content of Tags e.g.
/<h3>(.*?)<\/h3>/g.exec(data.body.und[0].safe_value)[1]
returns August 26, 2020
With the use of some regex you can get this done pretty easily.
I wasn't sure about what the "date / title / content" parts were but it shows how to parse some html.
I also changed the code to "async / await". This is more of a personal preference. The code should work the same with "then / catch".
(async () => {
try {
// Make request
const response = await fetch("https://api.ontario.ca/api/drupal/page%2F2020-ontario-immigrant-nominee-program-updates?fields=body");
// Parse response into json
const data = await response.json();
// Get the parsed data we need
const websiteData = data.body.und[0].safe_value;
// Split the html into seperate articles (every <h2> is the start of an new article)
const articles = websiteData.split(/(?=<h2)/g);
// Get the data for each article
const articleInfo = articles.map((article) => {
// Everything between the first h3 is the date
const date = /<h3>(.*)<\/h3>/m.exec(article)[0];
// Everything between the first h4 is the title
const title = /<h4>(.*)<\/h4>/m.exec(article)[0];
// Everything between the first <p> and last </p> is the content of the article
const content = /<p>(.*)<\/p>/m.exec(article)[0];
return {date, title, content};
});
// Show results
console.log(articleInfo);
} catch(error) {
// Show error if there are any
console.log(error);
}
})();
Without comments
(async () => {
try {
const response = await fetch("https://api.ontario.ca/api/drupal/page%2F2020-ontario-immigrant-nominee-program-updates?fields=body");
const data = await response.json();
const websiteData = data.body.und[0].safe_value;
const articles = websiteData.split(/(?=<h2)/g);
const articleInfo = articles.map((article) => {
const date = /<h3>(.*)<\/h3>/m.exec(article)[0];
const title = /<h4>(.*)<\/h4>/m.exec(article)[0];
const content = /<p>(.*)<\/p>/m.exec(article)[0];
return {date, title, content};
});
console.log(articleInfo);
} catch(error) {
console.log(error);
}
})();
I just completed creating .Net Core worker service for this.
The value you are looking for is "metatags.description.og:updated_time.#attached.drupal_add_html_head..#value"
The idea is if the last updated changes you send an email notification!
Try this in you javascript
fetch(`https://api.ontario.ca/api/drupal/page%2F2021-ontario-immigrant-nominee-program-updates`)
.then((result) => {
return result.json();
})
.then((data) => {
let lastUpdated = data.metatags["og:updated_time"]["#attached"].drupal_add_html_head[0][0]["#value"];
console.log(lastUpdated);
});
I will be happy to add you to the email list for the app I just created!

How can I update my dictionary with nested HTTP request?

I'm gonna try to explain this as clearly as I can, but it's very confusing to me so bear with me.
For this project, I'm using Node.js with the modules Axios and Cheerio.
I am trying to fetch HTML data from a webshop (similar to Amazon/eBay), and store the product information in a dictionary. I managed to store most things (title, price, image), but the product description is on a different page. To do a request to this page, I'm using the URL I got from the first request, so they are nested.
This first part is done with the following request:
let request = axios.get(url)
.then(res => {
// This gets the HTML for every product
getProducts(res.data);
console.log("Got products in HTML");
})
.then(res => {
// This parses the product HTML into a dictionary of product items
parseProducts(productsHTML);
console.log("Generated dictionary with all the products");
})
.then(res => {
// This loops through the products to fetch and add the description
updateProducts(products);
})
.catch(e => {
console.log(e);
})
I'll also provide the way I'm creating product objects, as it might clarify the function where I think the problem occurs.
function parseProducts(html) {
for (item in productsHTML) {
// Store the data from the first request
const $ = cheerio.load(productsHTML[item]);
let product = {};
let mpUrl = $("a").attr("href");
product["title"] = $("a").attr("title");
product["mpUrl"] = mpUrl;
product["imgUrl"] = $("img").attr("src");
let priceText = $("span.subtext").text().split("\xa0")[1].replace(",", ".");
product["price"] = parseFloat(priceText);
products.push(product);
}
}
The problem resides in the updateProducts function. If I console.log the dictionary afterwards, the description is not added. I think this is because the console will log before the description gets added. This is the update function:
function updateProducts(prodDict) {
for (i in prodDict) {
let request2 = axios.get(prodDict[i]["mpUrl"])
.then(res => {
const $ = cheerio.load(res.data);
description = $("div.description p").text();
prodDict[i]["descr"] = description;
// If I console.log the product here, the description is included
})
}
// If I console.log the product here, the description is NOT included
}
I don't know what to try anymore, I guess it can be solved with something like async/await or putting timeouts on the code. Can someone please help me with updating the products properly, and adding the product descriptions? Thank you SO much in advance.
To refactor this with async/await one would do:
async function fetchAndUpdateProducts() => {
try {
const response = await axios.get(url);
getProducts(response.data);
console.log("Got products in HTML");
parseProducts(productsHTML);
console.log("Generated dictionary with all the products");
await updateProducts(products);
} catch(e) {
console.log(e);
}
}
fetchAndUpdateProducts().then(() => console.log('Done'));
and
async function updateProducts(prodDict) {
for (i in prodDict) {
const response = await axios.get(prodDict[i]["mpUrl"]);
const $ = cheerio.load(response.data);
description = $("div.description p").text();
prodDict[i]["descr"] = description;
}
}
This will not proceed to conclude the call to fetchAndUpdateProducts unless the promise returned by updateProducts has been resolved.

Categories