Can't retrieve data from the NY Times API - javascript

I'm trying to get the largest image, title, short description and url of top stories from the NY Times API. Before I get all the information that I need, I'm trying to just get the titles but I can't seem to get any information appearing. Is something wrong with my code?
UPDATE: I've added the element to the DOM (please see code below) however the title still hasn't been displayed. I also tried printing it in the console before but nothing printed there either.
var url = 'https://api.nytimes.com/svc/topstories/v2/science.json?api-key=MY_API_KEY'
function setup() {
noCanvas()
loadJSON(url, gotData)
}
function gotData(data) {
const articles = data.results
for (let i = 0; i < articles.length; i++) {
const title = document.createElement('h1')
title.innerText = articles[i].title
document.body.appendChild(title)
}
}

Well, you created your element, but you still need to add it to the DOM.
To create your element:
const title = document.createElement('h1')
And to add it to the DOM (to make it actually appear on your page):
document.body.appendChild(title)
But now you still need to add your actual title from the API to it:
title.innerText = articles[i].title
And all together:
const title = document.createElement('h1') // create the heading
title.innerText = articles[i].title // add the title from the API to your heading
document.body.appendChild(title) // add your heading to the DOM (this will make it appear)

Have a look at this. I answered in your dupe but here is better
let html = [];
fetch('https://api.nytimes.com/svc/topstories/v2/science.json?api-key=yourApiKey')
.then((resp) => resp.json())
.then(function(data) {
data.results.forEach(res => {
html.push(`<h1>${res.title}</h1>`);
})
document.getElementById("res").innerHTML = html.join("");
})
<div id="res"></div>

Related

JavaScript Object - Split() method + '\n'

I reached 'fetch' method...
A simple question (complicated for me) ...
How to use 'fetch()' method, 'split()' and '\ n' together?
I will show you an example (i am here to learn and master some skills and i am not ashamed to ask):
I need to read and print the following data using the 'fetch' method:
from the following link 'https://v-dresevic.github.io/Advanced-JavaScript-Programming/data/students.txt' - it is necessary to read the data and print them on the page.
And that is quite clear to me! I managed to do that!
code: enter image description here
my result (wrong result): enter image description here
correct result: enter image description here
My question is:
After reading the data from the file, I have to parse them and create Student objects based on them.
Parsing can be done using the split () method of the String object.
It is best to divide the read text by line breaks, specifying "\ n" for the split () method parameter.
thanks in advance :)
here is a fast example of parsing your data to an array of objects as i think this is the only thing you ask here, from there you can loop that array and display the object as you need.
const url =
"https://v-dresevic.github.io/Advanced-JavaScript-Programming/data/students.txt";
let result = fetch(url)
.then((r) => r.text())
.then(process);
function process(result) {
const linesDescription = ["Name", "Address", "Phone", "Course"];
const array = [];
let obj = {};
var lines = result.split("\n");
let x = 0;
for(var line = 0; line < lines.length; line++){
obj[linesDescription[x]] = lines[line].trim();
x++;
if (x >= linesDescription.length) {
array.push(obj);
x = 0;
obj = {};
}
};
console.log(array);
}

Change text Inside heading with info from Array

I'm making a fetch call to retrieve some data on player cards.
I'm trying to display said cards and running into issues accurately parsing JSON and showing info in HTML.
Here is an example HTML heading for a card:
<h3 class="card__title">Example Card</h3>
Here is some JavaScript code I used after the fetch call:
let cardList = json.results
let cardTitle0 = cardList[0].name.toString();
How do I change the text from Example Card -> cardTitle0 from my array? This question applies to other attributes from the array and HTML objects.
You'll need to use the h3 element to get the link:
const link = document.querySelector(".card__title a");
// These can be const.
const cardList = json.results
const cardTitle0 = cardList[0].name.toString();
link.innerHTML = cardTitle0;
For multiple cards, you'd have to loop through the cardList json result and also through the elements on the page.
This is just an idea off the top of my head so I can't verify this code works or is even the best option for addressing multiple cards but hopefully it'll get you going in the right direction.
const links = document.querySelectorAll(".card__title a");
const cardList = json.results;
// Loop through the links on the page.
for (let i = 0; i < links.length - 1; i++)
{
for (let j = 0; j < cardList.length - 1; j++)
{
const title = cardList[j].name.toString();
links[i].innerHTML = title;
}
}

Page refresh displays entire localstorage object

I have built a todo list using Vanilla Javascript and localstorage. The todo list has the following key, value:
key: todolist
value: [[\"id:0\",\"title:buy groceries\",\"done:false\"],
[\"id:1\",\"title:pick up dry cleaning\",\"done:false\"],
[\"id:2\",\"title:walk dog\",\"done:false\"]]
The values display just great on my website (only the title is displaying) but when I refresh the page, the whole object is displaying.
Before page refresh:
buy groceries
pick up dry cleaning
walk dog
After page refresh:
id:0,title:buy groceries,done:false
id:1,title:pick up dry cleaning,done:false
id:2,title:walk dog,done:false
Obviously, after a page refresh I only want the title to display on the list inside the li tag. It's a head scratcher because it only does this after a page refresh.
How do I get only the title to display after page refresh?
I'm somewhat of a newbie to Javascript and can't quite figure out how to make this happen. I've been Googling for almost two days and ready to tear my hair out!!
// set up some variables for elements on the page
const form = document.querySelector('form');
const ul = document.querySelector('ul');
const button = document.querySelector('button');
const input = document.getElementById('item');
// Fix empty array when script runs by making a conditional statement that
checks if localStorage already exists
//let itemsArray = localStorage.getItem('todolist') ?
JSON.parse(localStorage.getItem('todolist')) : [];
let todolist;
if (localStorage.getItem('todolist')) {
itemsArray = JSON.parse(localStorage.getItem('todolist'));
} else {
itemsArray = [];
}
localStorage.setItem('todolist', JSON.stringify(itemsArray));
const data = JSON.parse(localStorage.getItem('todolist'));
//alert(typeof(data));
// function that creates an li element, sets the text of the element to the
parameter, and appends the list item to the ul.
const liMaker = (text) => {
const li = document.createElement('li');
li.textContent = text;
ul.appendChild(li);
// Create a "close" button and append it to each list item
var span = document.createElement("SPAN");
var txt = document.createTextNode("🗑️");
span.className = "close";
span.appendChild(txt);
li.appendChild(span);
for (i = 0; i < close.length; i++) {
close[i].onclick = function() {
var div = this.parentElement;
div.style.display = "none";
}
}
}
// Event listener that submits the value of the input
form.addEventListener('submit', function (e) {
e.preventDefault();
var id = "id:" + itemsArray.length;
var title = "title:" + input.value;
var done = "done:" + "false";
itemsArray.push([id, title, done]);
//itemsArray.push(input.value);
localStorage.setItem('todolist', JSON.stringify(itemsArray));
liMaker(input.value);
input.value = "";
});
data.forEach(item => {
liMaker(item);
});
// clear items from todolist
button.addEventListener('click', function () {
localStorage.removeItem("todolist");
while (ul.firstChild) {
ul.removeChild(ul.firstChild);
}
itemsArray = [];
});
One thing I should note, the page refresh issue doesn't happen when I change the following:
itemsArray.push([id, title, done]);
to the following:
itemsArray.push(input.value);
The main reason you are having this problem is because your JSON is not formatted properly.
The reason you are only seeing the problem on page refresh is because at this point local storage contains the "todolist" key with your improperly formed JSON. This JSON value is then stored in your data variable and output to your list items in an undesired way (as you described).
Otherwise (without page refresh) the text of your list items is coming directly from the text in the input field.
If you make the following changes to your code it will work properly (I have tested it). Hope it helps.
JavaScript comments
Firstly i'm not sure if this just happened when you posted your code here but if your comments in JS extend across two lines or more then you need to put // on all lines.
For example in your code you have:
//function that creates an li element, sets the text of the element to the
parameter, and appends the list item to the ul.
and it should be:
//function that creates an li element, sets the text of the element to the
//parameter, and appends the list item to the ul.
The format of your JSON
Secondly I see a problem with the way the JSON is formatted.
It should look something like the following (before slashes are added).
[{"id":0,"title":"buy groceries","done":false},
{"id":1,"title":"pick up dry cleaning","done":false},
{"id":2,"title":"walk dog","done":false}]
Note each property name (i.e "id", "title" and "done") should have double quotes and each property value (e.g "buy groceries") should have double quotes (unless its an int or a boolean etc).
You can use a tool called JSLint to check your JSON is valid.
So in order to create your JSON in the right format (when the form is submitted)
change these lines of code:
var id = "id:" + itemsArray.length;
var title = "title:" + input.value;
var done = "done:" + "false";
itemsArray.push([id, title, done]);
to the following:
var idValue = itemsArray.length;
var titleValue = input.value;
var doneValue = false;
itemsArray.push({"id": idValue, "title": titleValue, "done" : doneValue});
Iterating through the array
Your data variable will contain the array of todolist objects (from local storage).
So therefore the item you have in the following code will contain the full object i.e {"id":0,"title":"buy groceries","done":false}.
So in order to get the title here you need to say item.title. (This will work now that the JSON will be properly formatted):
data.forEach(item => {
//log the item to check it.
console.log(item);
liMaker(item.title);
});

Assigning values received from asynchronous functions [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 4 years ago.
So I'm creating the a FB app that uses the FB SDK. In the code below, I am getting a list of movies I like and their FB page ids in 'data'. Then, I'm iterating through it to get the get the names of the movies and using the page ids, i get their page links and src of their page profile pictures. Then I use the details to create the following HTML block:
<article>
<figure>
<img src="source">
</figure>
<div>
<a href="link"/>
</div>
</article>
So, I dynamically create each article block and then append them to the below HTML code:
<body>
<header></header>
<section>
<article></article>
</section>
<footer></footer>
<script src = *source of my .js file*></script>
</body>
This is my js code:
// data has a list of FB movie pages, each containing the name of the movie and page id
function print(data)
{
//iterates through the object passed to print movie names in console.
var target = document.querySelector('article');
var docFrag = document.createDocumentFragment();
for (var i = 0; i < data.length; i++)
{
var temp = data[i];
var linkElement = document.createElement('a');
var linkText = document.createTextNode(temp["name"]);
linkElement.appendChild(linkText);
//getting the link to the movie's FB page
getLink(function(response){linkElement.href = response;},temp["id"]);
var imgElement = document.createElement('img');
//getting the src of the picture of the movie's page
getPic(function(response){imgElement.setAttribute("src", response);},temp["id"]);
imgElement.setAttribute("width", "304");
imgElement.setAttribute("height", "228");
imgElement.setAttribute("alt", temp["name"]);
var article = document.createElement("article"),
figure = document.createElement("figure"),
div = document.createElement("div");
div.appendChild(linkElement);
figure.appendChild(imgElement);
article.appendChild(figure);
article.appendChild(div);
console.log(article);
docFrag.appendChild(article);
}
target.appendChild(docFrag);
}
function getLink(callback,id)
{
FB.api('/'+id+'?fields=link', function(response)
{
callback(response.link);
});
}
function getPic(callback,id)
{
FB.api('/'+id+'?fields=cover{source}', function(response)
{
callback(response.cover.source);
});
}
My problem is that when I print the output, all the article blocks except the last one lose the href's and the src's for the 'img' blocks. When I print the articles in the console, the href and the src are empty except the last one. I think maybe it's got something to do with async calls to the FB SDK, but I'm not sure. Can anyone help?
var has function scope, not block scope, and is hoisted. Use const or let instead, especially in for loops, especially in asynchronous for loops:
for (let i = 0; i < data.length; i++) {
const temp = data[i];
const linkElement = document.createElement('a');
To the interpreter, what you're currently doing looks something like this:
function print(data) {
var target;
var docFrag;
var temp;
var linkElement;
// etc
for (i = 0; i < data.length; i++) {
temp = data[i];
linkElement = document.createElement('a');
// etc
So after the end of the loop, once the responses come back, each callback is referencing the same imgElement, the last one the for loop reassigned.
You can also use forEach, which is significantly better than for loops in most respects. (no manual iteration, automatic abstraction, accepts functions as arguments)
data.forEach((temp) => {
const linkElement = document.createElement('a');
// ...

retrieving specific data from json array using javascript

Hi guys need a little help here since I am a begiiner in javascript Please note that my question might be a duplicate to you all but I need a little enlightenment here, anyway I need to get to display the data I need from a JSON array lets say I have 3 array
var = countrysites[ "Denmark"],["United States"],["France"]
if I click the marker for Denmark using basic javascript Onclick it would display the data for Denmark only not calling all data of USA and France. Here is my javascript code
function displayData(){
for (var i = 0; i < countrysites.length; i++) {
if (countrysites[i].country_name === id) {
countrysites[i].country_name = country_name;
}
}
}
and my div has an id of 'sitemark' and has onclick of displayData
Thank you in advance
If you're going to be going through a multi-dimensional array you'd have to use two for loops like so
for(var i = 0; i < arr.length; i++) {
for(var j = 0; j < arr[i].length; j++) {
if(whatever you're looking for) {
}
}
}
I've taken some liberties in answering this because I'm still not sure what your data-structure looks like, but hopefully this will help.
Here's the data you're receiving as JSON which you then parse. It's array of objects each of which contains country_name and info properties.
const countryInfo = [
{ country_name: 'Denmark', info: 'This is Denmark' },
{ country_name: 'England', info: 'This is England' },
{ country_name: 'Japan', info: 'This is Japan' }
];
For the purposes of this DEMO we grab the body element, and then grab an array of just the country names from the data.
const body = document.querySelector('body');
const names = countryInfo.map(obj => obj.country_name);
We build some markers with that array data and add them to the body element. Note the data attribute data-name. We store a copy of the country name here.
names.forEach(name => {
const html = `<div class="sitemark" data-name="${name}">${name}</div>`;
body.insertAdjacentHTML('beforeend', html);
});
We grab the info element. This is where we add the country information.
const info = document.querySelector('#info');
We grab the markers and add event listeners to them. When one is clicked, call the displayData function.
const sitemarks = document.querySelectorAll('.sitemark');
sitemarks.forEach(marker => {
marker.addEventListener('click', displayData, false);
});
To get the countryinfo we perform a find operation on the countryInfo array that pulls out the first object instance where the country name is the same as the name in the data-name attribute on the element, and then take the info value from that object. Then we add that text to the info element.
function displayData() {
const text = countryInfo.find(obj => obj.country_name === this.dataset.name).info;
info.innerHTML = text;
}

Categories

Resources