Assign looped img url to div - javascript

Attempting to recreate a Netflix app in HTML, CSS and JS to support my learning and become more proficient at JS. I want to give each div a background image from an object. The object contains 20 or so images of which I have looped through to get each respective url.
const getMovies = () => {
const movieEndpoint = '/discover/movie';
const requestParams = `?api_key=${tmdbKey}`;
const urlToFetch = `${tmdbBaseUrl}${movieEndpoint}${requestParams}`;
fetch(urlToFetch)
.then(response => {
return response.json();
})
.catch(error => {
console.log(error)
})
.then(data => {
const jsonResponse = data;
movies = jsonResponse.results;
console.log(movies);
for (const movie of movies) {
const fullSource = `https://image.tmdb.org/t/p/original/${movie.backdrop_path}`;
console.log(fullSource);
}
})
};
This successfully logs each url to the console, the trouble I have now is assigning them as backgrounds to existing div elements I have in a similar fashion. I have attempted to write a for loop to go through the divs and then change the background using style.backgroundImage = url(${fullSource}) but this doesn't work for me.
HTML looks like this:
<div id="category">
<div class="film"></div>
<div class="film"></div>
<div class="film"></div>
<div class="film"></div>
<div class="film"></div>
<div class="film"></div>
<div class="film"></div>
<div class="film"></div>
<div class="film"></div>
<div class="film"></div>
<div class="film"></div>
<div class="film"></div>
</div>
I have styled the divs in css haven't been able to find a successful method to assign the backgrounds.
To be clear, I would like to populate the divs with a random image from the object using the urls that have been populated.
Any help is appreciated!

const data = [
{
image: 'https://i.picsum.photos/id/1036/200/300.jpg?hmac=VF4u-vITiP0ezQiSbE3UBvxHDFf8ZqJDycaAIoffsCg'
},
{
image: 'https://i.picsum.photos/id/106/200/300.jpg?hmac=qnjqfh7hXrQF9MAA1T3JOgK3dhnLfxOo-HkzhyZoB2g'
},
{
image: 'https://i.picsum.photos/id/1036/200/300.jpg?hmac=VF4u-vITiP0ezQiSbE3UBvxHDFf8ZqJDycaAIoffsCg'
}
]
for (let index = 0; index < data.length; index++) {
const element = document.getElementById(`category-${index}`);
element.style.backgroundImage = `url(${data[index].image})`;
element.style.backgroundRepeat = 'no-repeat';
element.style.backgroundColor = "#f3f3f3";
element.style.backgroundSize = 'auto';
// element.style.backgroundPosition = '100vh 100vh';
element.style.width= '100%';
element.style.height = '100vh'
}
<div style="display: flex;">
<div id="category-0">Background Image 1</div>
<div id="category-1">Background Image 2</div>
<div id="category-2">Background Image 3</div>
</div>

Related

How can I interpret my JSON via Google Books API URL and display it on my HTML page using JS?

So, I am trying to pull the volume info from the JSON array from the URL provided: https://www.googleapis.com/books/v1/volumes?q=HTML5
Trying to pull author, title, images, page numbers and description.
This specific class of my HTML code I want to put the JSON data that I have mentioned above in is the 'b-card' class:
<div class="booklist">
<div class="booklist-cards">
<div class="b-card">
</div>
<div class="b-card">
</div>
<div class="b-card">
</div>
<div class="b-card">
</div>
<div class="b-card">
</div>
<div class="b-card">
</div>
<div class="b-card">
</div>
<div class="b-card">
</div>
</div>
</div>
<script src="https://www.googleapis.com/books/v1/volumes?q=HTML5"></script>
<script src="assets/js/script.js"></script>
The script.js file I have tried is below:
function handleResponse(obj) {
const book = Objects.keys(obj).map(item => obj['items']).reduce(
(acc, rec, id, array) => {
let singleBookCover = rec[id].volumeInfo.imageLinks.thumbnail;
let singleBookTitle = rec[id].volumeInfo.title;
let singleBookAuthor = rec[id].volumeInfo.authors[0];
return [...acc, {singleBookCover, singleBookTitle, singleBookAuthor}]
},
[]
).forEach( item => {
let title = document.createElement('h1');
title.textContent = `${item.singleBookTitle}`;
let author = document.createElement('strong');
author.textContent = `${item.singleBookAuthor}`;
let img = document.createElement('img');
img.src = item.singleBookCover;
img.alt = `${item.singleTitle} by ${item.singleBookAuthor}`;
let container = document.getElementsByClassName('b-card');
container.appendChild(title).appendChild(author).appendChild(img);
})
return book
}
The above code only adds the title image and author, but I cant get them to load into my HTML.
What are ways to resolve this? Am i calling the URL correctly in the HTML script tag?
Forgot to mention - would like to achieve this without using JQuery & AJAX. I have also tried inputting the callback to handleResponse in the script tag url but it doesnt work.
you can't append to the HTML because container is array so it need index of the element
container[index].appendChild(title).appendChild(author).appendChild(img);
but here simple version, and don't forget to add &callback=handleRespons to the API URL
function handleResponse(obj) {
obj.items.forEach((item, index) => {
if(index > 7) return; // limit 8 result
let div = document.createElement('div');
div.className = 'b-card';
div.innerHTML = `<h1>${item.volumeInfo.title}</h1>
<p><strong>${item.volumeInfo.authors[0]}</strong></p>
<img src="${item.volumeInfo.imageLinks.thumbnail}" alt="${item.singleTitle} by ${item.volumeInfo.authors[0]}" />`
let container = document.querySelector('.booklist-cards');
container.append(div);
})
}
<div class="booklist">
<div class="booklist-cards">
</div>
</div>
<script src="//www.googleapis.com/books/v1/volumes?q=HTML5&callback=handleResponse" async></script>

get a object value from a json API by Index in a forEach loop in JavaScript?

I am trying to learn how to use fetch() APIs this weekend...
and I saw this interesting API service, and I tried to learn how to use this
and I get a little problem, with javascript
the problem
I want to get the data from a .Json (and this works fine),
but when I want to put the values in the <div> and getting by object[index] is not showing anything
from what I know it seems possible,
but in this case, is not (...I search everywhere on the internet, no result)
basically...
this don't work object[index]; //index variable, is a number
this works object.object1; //normal method
what I tried
yes, I tried the traditional method using obj1.obj2 and is working fine, with the result I want!
but is not efficient, like I want.
because I want to get the values by index
and put the value in the <div>
with the index of the NodeListOf<element>
complete code, I wrote
open the snippet to see the code
let orarioText = document.querySelectorAll('.orario');
const fetchPreghieraTime = async() => {
const data = await fetch('http://api.aladhan.com/v1/timingsByCity?city=Milano&country=Italy&method=8');
const orarioJson = await data.json();
const orario = orarioJson.data.timings;
orarioText.forEach((item, index) => {
item.textContent = orario[index];
console.log(item.textContent + "" + index);
});
}
fetchPreghieraTime();
<div class="container">
<div class="tempo-preghiera-container">
<!-- 1 -->
<div class="tempo-fajr">
<div class="nome-preghiera">fajr</div>
<div class="orario">error</div>
<!-- this error text, It will change dinamically with JS -->
</div>
<!-- 2 -->
<div class="tempo-duhr">
<div class="nome-preghiera">duhr</div>
<div class="orario">error</div>
<!-- this error text, It will change dinamically with JS -->
</div>
<!-- 3 -->
<div class="tempo-asr">
<div class="nome-preghiera">asr</div>
<div class="orario">error</div>
<!-- this error text, It will change dinamically with JS -->
</div>
<!-- 4 -->
<div class="tempo-maghrib">
<div class="nome-preghiera">maghrib</div>
<div class="orario">error</div>
<!-- this error text, It will change dinamically with JS -->
</div>
<!-- 5 -->
<div class="tempo-isha">
<div class="nome-preghiera">isha</div>
<div class="orario">error</div>
<!-- this error text, It will change dinamically with JS -->
</div>
</div>
</div>
<script src="./script.js"></script>
What do I mean by efficient?
this is the idea to write less, simpler code:
elementClass.forEach((item, index) => {
item.textContent = object[index];
});
you can see how inefficient method below, that is working
elementClass[0].textContent = object.Fajr;
elementClass[1].textContent = object.Dhuhr;
elementClass[2].textContent = object.Asr;
elementClass[3].textContent = object.Maghrib;
elementClass[4].textContent = object.Isha;
if you can I want the less code, or the simpler solution
( I don't want you to give a faster program possible, no no, for me if is simple logic that is enough for me )
(think if I need to write all the name of the object if there is like 50 items, etc..., that is why)
the first Idea is coming to my mind because of arrays...
and in arrays, you can use brackets with a number, that start with 0, and that is (is not working)
the problem
code doesn't work
let orarioText = document.querySelectorAll('.orario');
//there are 5 elements with the same class
orarioText.forEach((item, index) => {
item.textContent = orarioJson.data.timings[index];
});
this is WORKING fine
let orarioText = document.querySelectorAll('.orario');
//there are 5 elements with the same class
orarioText.forEach((item, index) => {
item.textContent = orarioJson.data.timings.Fajr; //here you see the [index] is replaced by the actual name
});
if you want to try also, here is the API I used
here is the API service link, I usedhttp://api.aladhan.com/v1/timingsByCity?city=Milano&country=Italy&method=8
and this is how it looks:
{"code":200,"status":"OK","data":{"timings":{"Fajr":"05:31","Sunrise":"07:19","Dhuhr":"12:37","Asr":"15:26","Sunset":"17:56","Maghrib":"17:56","Isha":"19:26","Imsak":"05:21","Midnight":"00:37"}
in case, is not clear the problem to you:
you can write a comment, asking for more info, I will answer it :)
short summary of what I asked
I want that this HTML
<!-- 0 -->
<div class="myClass"></div>
<!-- 1 -->
<div class="myClass"></div>
<!-- 2 -->
<div class="myClass"></div>
<!-- 3 -->
<div class="myClass"></div>
<!-- 4 -->
<div class="myClass"></div>
to become like this HTML after JS
<!-- 0 -->
<div class="myClass">obj1 value</div>
<!-- 1 -->
<div class="myClass">obj2 value</div>
<!-- 2 -->
<div class="myClass">obj3 value</div>
<!-- 3 -->
<div class="myClass">obj4 value</div>
<!-- 4 -->
<div class="myClass">obj5 value</div>
I hope there is someone amazing helpful developer,
who have more experience,
that can help me
(and help also the future developers who see this question)
and thank you all the community!
You can get the property name that you need from the parent element. It has it in its class name "tempo-....". It just needs one change in the HTML, as you used a different spelling for dhurh. So align that with the spelling in the JSON response.
Here is how you can extract that name from that "tempo" class and then use it to access the timing from the response object:
Find the parent element with .parentNode
Get the class attribute value with .className
Extract the part after "tempo-" using .match and the first entry in the returned array
Convert the first letter to a capital and the rest to lowercase.
Use it as a dynamic property
let orarioText = document.querySelectorAll('.orario');
const fetchPreghieraTime = async() => {
const data = await fetch('http://api.aladhan.com/v1/timingsByCity?city=Milano&country=Italy&method=8');
const orarioJson = await data.json();
const orario = orarioJson.data.timings;
orarioText.forEach((item, index) => {
let name = item.parentNode.className.match(/(?<=\btempo-)\w+/)[0];
item.textContent = orario[name[0].toUpperCase() + name.slice(1).toLowerCase()];
});
}
fetchPreghieraTime();
<div class="container">
<div class="tempo-preghiera-container">
<!-- 1 -->
<div class="tempo-fajr">
<div class="nome-preghiera">fajr</div>
<div class="orario">error</div>
<!-- this error text, It will change dinamically with JS -->
</div>
<!-- 2 -->
<div class="tempo-dhuhr">
<div class="nome-preghiera">duhr</div>
<div class="orario">error</div>
<!-- this error text, It will change dinamically with JS -->
</div>
<!-- 3 -->
<div class="tempo-asr">
<div class="nome-preghiera">asr</div>
<div class="orario ">error</div>
<!-- this error text, It will change dinamically with JS -->
</div>
<!-- 4 -->
<div class="tempo-maghrib">
<div class="nome-preghiera">maghrib</div>
<div class="orario">error</div>
<!-- this error text, It will change dinamically with JS -->
</div>
<!-- 5 -->
<div class="tempo-isha">
<div class="nome-preghiera">isha</div>
<div class="orario">error</div>
<!-- this error text, It will change dinamically with JS -->
</div>
</div>
</div>
<script src="./script.js"></script>
I will answer the same question, so I will help someone in the future :)
short answer
with .JSON format,
❌ you can't use the bracket with a number variable
orario[index]
✅ inside the brackets, you need to put a string (for example ["Fajr"], and is like writing .Fajr)
and so there isn't any method to access this by JSON!
but... I found a solution for you!
like you said also in the question, this method works very well in arrays
so we need to do something like this pseudocode:
FETCH -> JSON -> ARRAY -> ARRAY[index]
I saw on the internet that javascript, has this functionality, so you can use it too!
Object.values(orario);
more details about: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values
so...
I put this in variable called orarioArray, so is simple for you!
const orarioArray = Object.values(orario);
now what you need is only add this to your forEach loop
orarioText.forEach((item, index) => {
item.textContent = orarioArray[index];
});
edited complete code:
let allTempoContainer = document.querySelector('.all-tempo-container');
let orarioArrayValue;
let orarioArrayName;
const fetchPreghieraTime = async() => {
const data = await fetch('http://api.aladhan.com/v1/timingsByCity?city=Milano&country=Italy&method=8');
const orarioJson = await data.json();
const orario = orarioJson.data.timings;
orarioArrayValue = Object.values(orario);
orarioArrayName = Object.keys(orario);
for (let index = 0; index < orarioArrayName.length; index++) {
createOrarioCard(index);
}
}
function createOrarioCard(index) {
var OrarioCardTemplate = document.querySelectorAll("template")[0];
var OrarioCardClone = OrarioCardTemplate.content.cloneNode(true);
allTempoContainer.appendChild(OrarioCardClone);
let orarioText = document.querySelectorAll('.orario');
let preghieraText = document.querySelectorAll('.nome-preghiera');
preghieraText[index].textContent = orarioArrayName[index];
orarioText[index].textContent = orarioArrayValue[index];
}
fetchPreghieraTime();
<div class="container">
<div class="all-tempo-container">
<!-- here it will generate the code -->
</div>
</div>
<template>
<div class="orario-container" style="display: flex; justify-content: space-between;">
<div class="nome-preghiera">loading...</div>
<div class="orario">loading...</div>
</div>
</template>
<script src="./script.js"></script>
previus code:
let orarioText = document.querySelectorAll('.orario');
const fetchPreghieraTime = async() => {
const data = await fetch('http://api.aladhan.com/v1/timingsByCity?city=Milano&country=Italy&method=8');
const orarioJson = await data.json();
const orario = orarioJson.data.timings;
// JSON to Array
const orarioArray = Object.values(orario);
orarioText.forEach((item, index) => {
item.textContent = orarioArray[index];
});
}
fetchPreghieraTime();
<!-- 0 -->
<div class="orario"></div>
<!-- 1 -->
<div class="orario"></div>
<!-- 2 -->
<div class="orario"></div>
<!-- 3 -->
<div class="orario"></div>
<!-- 4 -->
<div class="orario"></div>
try this
<div class="container">
<div class="tempo-preghiera-container">
</div>
</div>
const fetchPreghieraTime = async () => {
const data = await fetch(
"http://api.aladhan.com/v1/timingsByCity?city=Milano&country=Italy&method=8"
);
const orarioJson = await data.json();
const orario = orarioJson.data.timings;
let orarioText = document.querySelector(".tempo-preghiera-container");
for (const property in orario) {
if (property == "Sunset"
|| property == "Sunrise"
|| property == "Midnight" ) continue;
let div = document.createElement("div");
div.classList.add("orario");
let text = document.createTextNode(property + " - " + orario[property]);
div.appendChild(text);
orarioText.appendChild(div);
}
};
fetchPreghieraTime();
output
<div class="container">
div class="tempo-preghiera-container">
<div class="orario">Fajr - 05:30</div>
<div class="orario">Dhuhr - 12:37</div>
<div class="orario">Asr - 15:28</div>
<div class="orario">Maghrib - 17:57</div>
<div class="orario">Isha - 19:27</div>
<div class="orario">Imsak - 05:20</div>
<div class="orario">Midnight - 00:37</div>
</div>
</div>

How do I use For Loop in JavaScript to show the list?

I am a beginner in JavaScript and I can't figure out the following problem: I am trying to create a simple JavaScript Movie List. I have 10 lists on the Movie List. I tried to show all of the lists with for loop, but it doesn't work.
Here's the code:
function renderModal() {
for (let i = 0; i < listMovies.length; i++) {
let movieData = listMovies[i];
document.getElementById("poster").src = movieData.img;
document.getElementById("title").innerHTML = movieData.name;
document.getElementById("genre").innerHTML = movieData.genre;
document.getElementById("rating-num").innerHTML = "Rating: "+ movieData.rating + "/10";
document.getElementById("movie-desc").innerHTML = movieData.desc;
document.getElementById("imdb-page").href = movieData.link;
return movieData;
}
}
What do I have to do?
Help me to fix it!.
You can use template tag for list and render it into target element.I am showing an example.
Movie list
<div id="movieList"></div>
template for list
<template id="movieListTemplate">
<div class="movie">
<img src="" class="poster" alt="">
<div class="title"></div>
<div class="genre"></div>
<div class="rating-num"></div>
<div class="movie-desc"></div>
<div class="imdb-page"></div>
</div>
</template>
Javascript code:
if (listMovies.length > 0) {
const movileListTemplate = document.getElementById('movieListTemplate')
const movieRenederElement = document.getElementById('movieList')
for(const movie of listMovies) {
const movieEl = document.importNode(movileListTemplate.content, true)
movieEl.querySelector('.poster').src = movie.img
movieEl.querySelector('.title').textContent = movie.name
//use all queryselector like above
}
}
Your return movieData; will stop the loop dead. Not that running it more than once will change anything since you change the same elements over and over. IDs must be unique.
Here is a useful way to render an array
document.getElementById("container").innerHTML = listMovies.map(movieData => `<img src="${movieData.img}" />
<h3>${movieData.name}</h3>
<p>${movieData.genre}</p>
<p>Rating: ${movieData.rating}/10</p>
<p>${movieData.desc}
IMDB
</p>`).join("<hr/>");
With return movieData, the for loop will ends in advance.You should put it outside the for loop.

Json file struggling with the length

So, i got everything almost working as i want it, just a mistake that im struggling. Everytime i search for an item, when the result for that item shows the length is repeated.
When i search for ox there are 2 results and that is correct, but the length (2) shows in both of them, i only display one
[Code]
const resultHtml = (itemsMatch) => {
if (itemsMatch.length > 0) {
const html = itemsMatch
.map(
(item) => `
<span>${itemsMatch.length}</span>
<div class="card">
<div class="items-img">
</div>
<div class="items-info">
<h4>${item.title}</h4>
<small>${item.path}</small>
</div>
</div>
`
)
.join('');
//console.log(html);
itemList.innerHTML = html;
}
};
////
Question 2
I got one more question, i was trying to get the image from the Json and what i got was the path haha
why the apth and not the img
const resultHtml = (itemsMatch) => {
if (itemsMatch.length > 0) {
const html =
`<span class="items-results">${itemsMatch.length} Resultados</span>` +
itemsMatch
.map(
(item) => `
<div class="card">
<div class="items-img">
${item.image}
</div>
<div class="items-info">
<h4>${item.title}</h4>
<small>${item.path}</small>
</div>
</div>
`
)
.join('');
console.log(html);
itemList.innerHTML = html;
}
};
If you move <span>${itemsMatch.length}</span> out of your map callback, it will not repeat for each item. Read more about map() here.
Replace:
const html = itemsMatch
.map(
(item) => `
<span>${itemsMatch.length}</span>
... more HTML here
`
)
.join('');
With this:
const html = `<span>${itemsMatch.length}</span>` + (
itemsMatch
.map(
(item) => `
<div class="card">
<div class="items-img">
</div>
<div class="items-info">
<h4>${item.title}</h4>
<small>${item.path}</small>
</div>
</div>
`
)
.join('')
);
Regarding your image issue:
You are just outputting the path and that's why it's printing out just the path. If you are trying to display an image then put the path as source of <img> tag.
So, instead of just:
${item.image}
Use:
<img src="${item.image}">

How to get child of div in cheerio

I am working with cheerio and I am stuck at a point where I want to get the href value of children div of <div class="card">.
<div class="Card">
<div class="title">
<a target="_blank" href="test">
Php </a>
</div>
<div>some content</div>
<div>some content</div>
<div>some content</div>
</div>
I got first childern correctly but i want to get div class=title childern a href value. I am new to node and i already search for that but i didn't get an appropriate answer.
var jobs = $("div.jobsearch-SerpJobCard",html);
here is my script
const rp = require('request-promise');
const $ = require('cheerio');
const potusParse = require('./potusParser');
const url = "";
rp(url)
.then((html)=>{
const Urls = [];
var jobs = $("div.Card",html);
for (let i = 2; i < jobs.length; i++) {
Urls.push(
$("div.Card > div[class='title'] >a", html)[i].attribs.href
);
}
console.log(Urls);
})
.catch(err => console.log(err));
It looks something like this:
$('.Card').map((i, card) => {
return {
link: $(card).find('a').text(),
href: $(card).find('a').attr('href'),
}
}).get()
Edit: the nlp library is chrono-node and I also recommend timeago.js to go the opposite way

Categories