Change text Inside heading with info from Array - javascript

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

Related

For loop repeats each loop onto the next

I am trying to dynamically adjust the document.getElementById(divID) by using a loop. This seems to work...sorta
It keeps looping as you will see in the screenshot below.
let searchresult = function(response) {
let output ="";
for (let j = 0; j < response.length; j++) {
let divID = response[j].resortcode + 'results';
let container = document.getElementById(divID);
output +=
`
<div class="${response[j].resortcode} ${response[j].roomcode}">
</div>
`;
console.log(container);
$(container).html(output);
}
};
I have my container div set to the response[j].resortcode but I thought by using document.getElementById(divID) that it would only allow that resort code inside of a div with a corresponding resortcode
Notice it is also looping the getElementByID more than once.
I would like the output going to a premade div id in my html file (which it does, it just keeps repeating). Then loop the results <div class=${response[j].resortcode}"></div> into the corresponding premade div. Here is a photoshopped version of the desired result:
EDIT: Adding console of original response.
Any help is greatly appreciated.
Your variable output is added upon every iteration and never reset, so when you set the html to output, it contains every previous iteration.
You can fix this by getting the innerHTML and adding onto instead of having an output variable.
You can also store the resortcode into a Set (a special kind of array that does not allow duplication of elements) and then console.log out those containers at the end.
let searchresult = function(response) {
let resortCodes = new Set();
for (let j = 0; j < response.length; j++) {
resortCodes.add(response[j].resortcode); // add only happens if the resortcode isn't already in resortCodes
let divID = response[j].resortcode + 'results';
let container = document.getElementById(divID);
container.innerHTML += `
<div class="${response[j].resortcode}">
<div class="roominfo"><p class="roomtitle"> ${response[j].roomname} - ${response[j].viewname}</p>
</div>
</div>
`;
}
resortCodes.forEach(function (resortCode) {
console.log(document.getElementById(resortCode + "results"));
};
};

Can't retrieve data from the NY Times API

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>

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');
// ...

Creating a leaderboard with Firebase

I'm trying to build a top 10 leaderboard using the Firebase Realtime DB - I am able to pull the top 10 ordered by score (last 10 due to the way firebase stores in ascending order) however when I attempt to place them in the page they all appear in key order.
If I was a betting man I'd guess it's to do with the for loop I have to create the elements - but I'm not good enough at Javascript to work out where the issue is I've spent the last 3 hours on MDN and W3Schools and I can't for the life of me work it out.
Either that or I need to run a For Each loop on the actual data query? but I feel like I could avoid that as I'm already collecting the score data so I could just arrange that somehow?
I was sort of expecting everything to appear in ascending order - meaning I would have to go back and prepend my JQuery but instead I've managed to accidentally create a new problem for myself.
Any suggestions will be GREATLY appreciated
Here is my current code:
var db = firebase.database()
var ref = db.ref('images')
ref.orderByChild('score').limitToLast(10).on('value', gotData, errData);
function gotData(data) {
var scores = data.val();
var keys = Object.keys(scores);
var currentRow;
for (var i = 0; i < keys.length; i++){
var currentObject = scores[keys[i]];
if(i % 1 == 0 ){
currentRow = document.createElement("div");
$(currentRow).addClass("pure-u-1-5")
$("#content").append(currentRow);
}
var col = document.createElement("div")
$(col).addClass("col-lg-5");
var image = document.createElement("img")
image.src=currentObject.url;
$(image).addClass("contentImage")
var p = document.createElement("P")
$(p).html(currentObject.score)
$(p).addClass("contentScore");
$(col).append(image);
$(col).append(p);
$(currentRow).append(col);
}
}
Use .sort() beforehand, then iterate over each score object to add it to the page:
function gotData(data) {
const scores = data.val();
const keys = Object.keys(scores);
const sortedKeys = keys.sort((keyA, keyB) => scores[keyB].score - scores[keyA].score);
const content = document.querySelector('#content');
sortedKeys.map(sortedKey => scores[sortedKey])
.forEach(scoreObj => {
const row = content.appendChild(document.createElement('div'));
row.classList.add('pure-u-1-5'); // better done in the CSS if possible
const col = row.appendChild(document.createElement('div'));
col.classList.add('col-lg-5');
const img = col.appendChild(document.createElement('img'));
img.src = scoreObj.url;
img.classList.add('contentScore');
col.appendChild(document.createElement('p')).textContent = scoreObj.score;
});
}
For loops have worse abstraction, require manual iteration, and have hoisting problems when you use var - use the array methods instead when you can.

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