TMDB pagination JavaScript - javascript

I m want implement pagination with js and apirest from themoviedb.
Response give me a total_pages and total_results. I ve 2 buttons, prev and next.
Thanks in advance for help me to understand. Best regards.
I´m student and now i want create my repo as exercise and practice
My full code
//buttons
const btnAtras = document.getElementById('btnAtras')
const btnAdelante = document.getElementById('btnAdelante')
//api props
const key ='MyKey';
const lang ='es-ES';
let page =1
const fetch1 = fetch('https://api.themoviedb.org/3/movie/now_playing?api_key='+key+'&language='+lang+'&page='+page).then(resp=> resp.json())
const fetch2 = fetch('https://api.themoviedb.org/3/genre/movie/list?api_key='+key+'&language='+lang).then(resp=>resp.json())
//multifetch request
const allData = Promise.all([fetch1,fetch2])
allData.then(data=>{
let genres = data[1].genres
let movies = data[0].results
let currentPage = data[0].page;
let totalPages = data[0].total_pages
console.log(currentPage)
console.log(totalPages)
//map for taking all genre_ids to resolve genre_names
for (let movie of movies) {
movie.genres = genres.filter((item) => ((movie.genre_ids.indexOf(item.id) >= 0)));
movie.genre_names = movie.genres.map(item => item.name);
}
//getting all data
getCardFilm(movies);
})
//function to create each card template
function getCardFilm (data){
const cardContent = document.getElementById('playingNow');
let content = '';
const _baseUrlImg = 'https://image.tmdb.org/t/p/original';
data.forEach(film =>{
const {title,genre_names, poster_path, release_date, overview, id} = film;
content += `
<div class='card m-2' style='width: 22rem;' >
<img src='${_baseUrlImg+poster_path}' class='card-img-top' style='height:460px;width:100%;' alt='Imágen de la pelicula'>
<div class='card-header text-start'style='height: 6rem;'>
<h5 class='card-title'>${title}</h5>
<p class='card-text text-muted'>Lanzamiento: ${release_date}</p>
</div>
<div class='card-body text-start' id='linkFilm'>
<p class='card-text m-0'>${overview}</p>
</div>
<div class="card-footer text-muted " style='width:100%;
height:4rem;'>
<span class='text-center text-dark'>
${genre_names}
</span>
</div>
</div>
`
})
cardContent.innerHTML=content;
}```

Related

How to refresh page after filtering or mapping in javascript

I need to create a contact list with data from an API of random people. My page has a simple form (input + button) then after click should show a new list or filtered data from last list if there is some input text. The data is being fetch correctly and recorded into localStorage (limited to 10 users).
The problem: data is being added to the page instead of refreshing into the page.
How can I have new data on page for every click?
async function fetchPeople() {
const URL = 'https://randomuser.me/api/?results=10';
const res = await fetch(URL);
let data = await res.json();
return data;
}
async function data(name) {
let filteredData = [];
if (name.length > 0) {
let newdata = JSON.parse(localStorage.getItem('contacts'));
filteredData = newdata.filter((contact) => {
return contact.name.first.toLowerCase().includes(name);
});
} else {
let data = await fetchPeople();
localStorage.setItem('contacts', JSON.stringify(data.results));
filteredData = data.results;
return filteredData;
}
return filteredData;
}
async function printData() {
let ul = document.querySelector('#cards');
let name = document.querySelector('#contact').value.toLowerCase();
let filteredData = [];
filteredData = await data(name);
filteredData.forEach((contact) => {
let li = document.createElement('li');
li.innerHTML = `
<div class="card">
<img src="${contact.picture.large}"
alt="${contact.name.first} ${contact.name.last}"
class="card__image">
<h2 class="card__name">${contact.name.first} ${contact.name.last}</h2>
<p class="card__email">${contact.email}</p>
<p class="card__location">${contact.location.city}-${contact.location.state}</p>
<button class="card__btn">${contact.location.country}</button>
</div>`;
ul.appendChild(li);
});
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
<section class="form">
<div class="search">
<h1>Contact List</h1>
<div class='search__field'>
<input type="text" name="contact" id="contact" placeholder="Nome do contato" class="search__name form-control">
<button type="button" onclick='printData()' class='btn btn-primary search__btn'>Search</button>
</div>
</div>
</section>
<section class="results">
<ul class="cards" id="cards"></ul>
</section>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
JSFiffle
https://jsfiddle.net/w7gknc2t/
You need to clear ul innerHTML before appending new data.
async function printData() {
let ul = document.querySelector('#cards');
let name = document.querySelector('#contact').value.toLowerCase();
let filteredData = [];
filteredData = await data(name);
ul.innerHTML = '';
filteredData.forEach((contact) => {
let li = document.createElement('li');
li.innerHTML = `
<div class="card">
<img src="${contact.picture.large}"
alt="${contact.name.first} ${contact.name.last}"
class="card__image">
<h2 class="card__name">${contact.name.first} ${contact.name.last}</h2>
<p class="card__email">${contact.email}</p>
<p class="card__location">${contact.location.city}-${contact.location.state}</p>
<button class="card__btn">${contact.location.country}</button>
</div>`;
ul.appendChild(li);
});
}

How to get const from forEach method in javascript?

I have django application with quiz model:
class Quiz(models.Model):
name = models.CharField(max_length=50)
topic = models.CharField(choices=TOPICS, max_length=50)
number_of_questions = models.IntegerField(validators=[MinValueValidator(1)])
time = models.IntegerField(help_text="duration of quiz in minutes", default=5)
pass_score = models.IntegerField(help_text="score required to pass in %", default=90, validators = [MaxValueValidator(100), MinValueValidator(0)])
difficulty = models.CharField(choices=DIFFICULTY_CHOICES, max_length=10)
I get it in view:
def quiz_view(request, pk):
quiz = models.Quiz.objects.get(pk=pk)
return render(request, 'quizes/quiz.html', {'obj':quiz})
Then I get data of obj in html:
{% for obj in object_list %}
<button class="modal-button" data-pk="{{ obj.pk }}" data-name="{{ obj.name }}" data-topic="{{ obj.topic }}" data-questions="{{ obj.number_of_questions }}" data-difficulty="{{ obj.difficulty }}" data-time="{{ obj.time }}" data-pass="{{ obj.pass_score }}">
{{ obj.name }}
</button>
{% endfor %}
<div id="modal"></div>
Then I get data from button in javascript forEach method:
let modal = document.getElementById('modal')
const modalBtns = [...document.getElementsByClassName('modal-button')]
modalBtns.forEach(modalBtn => modalBtn.addEventListener('click', ()=>{
const pk = modalBtn.getAttribute('data-pk')
const name = modalBtn.getAttribute('data-name')
const topic = modalBtn.getAttribute('data-topic')
const numQuestions = modalBtn.getAttribute('data-questions')
const difficulty = modalBtn.getAttribute('data-difficulty')
const passScore = modalBtn.getAttribute('data-pass')
const time = modalBtn.getAttribute('data-time')
if(modal.classList.contains('close-modal')){
modal.classList.remove('close-modal')
}
modal.classList.add('open-modal')
modal.innerHTML = `
<p class="text">Are you sure you want to open</p><p class="name_of_quiz"><b>${name}?</b></p>
<ul class="description">
<li>Topic: ${topic}</li>
<li>Questions: ${numQuestions}</li>
<li>Difficulty: ${difficulty}</li>
<li>Score to pass: ${passScore}%</li>
<li>Time to solve: ${time} min</li>
</ul>
<div class="buttons-container">
<button class="close-button" onclick="close_modal()">Close</button>
<button class="proceed-button" id='start_button' onclick="startQuiz()">Yes</button>
</div>
`
}))
So when user clicks on button it sets open-modal:
.open-modal{
visibility: visible !important;
}
And we can see it. Then when I click 'proceed-button', I should get pk by running startQuiz():
function startQuiz(){
console.log(pk)
}
But I get an error:
`'pk' is not defined'.
Can I somehow get pk from forEach method?
i found your problem. You can't use a const. Constants have a block scope. Use parameters instead. A snippet of your javascript could be:
let modal = document.getElementById('modal')
const modalBtns = [...document.getElementsByClassName('modal-button')]
modalBtns.forEach(modalBtn => modalBtn.addEventListener('click', ()=>{
const pk = modalBtn.getAttribute('data-pk')
const name = modalBtn.getAttribute('data-name')
const topic = modalBtn.getAttribute('data-topic')
const numQuestions = modalBtn.getAttribute('data-questions')
const difficulty = modalBtn.getAttribute('data-difficulty')
const passScore = modalBtn.getAttribute('data-pass')
const time = modalBtn.getAttribute('data-time')
if(modal.classList.contains('close-modal')){
modal.classList.remove('close-modal')
}
modal.classList.add('open-modal')
modal.innerHTML = `
<p class="text">Are you sure you want to open</p><p class="name_of_quiz"><b>${name}?</b></p>
<ul class="description">
<li>Topic: ${topic}</li>
<li>Questions: ${numQuestions}</li>
<li>Difficulty: ${difficulty}</li>
<li>Score to pass: ${passScore}%</li>
<li>Time to solve: ${time} min</li>
</ul>
<div class="buttons-container">
<button class="close-button" onclick="close_modal()">Close</button>
<button class="proceed-button" id='start_button' onclick="startQuiz(${pk})">Yes</button>
</div>
`
}))
function startQuiz(pk){
console.log(pk)
}
With some value types it can happen that it doesn't work properly. If it doesn't work, write a comment with the type of pk.

click event listener method is not working on a specific div

I am trying to add an event listener to my "degree section div" but it is not working nor am I getting any errors. I have tried multiple ways of traversing the DOM to reach the "degree-section" div but to no avail.
Any kind of help is welcome and appreciated
Code:
let city = document.querySelector('#city');
let searchbtn = document.querySelector('.search-btn');
let city_name = document.querySelector('.city-name');
let temp = document.querySelector('.temp');
let feels_like = document.querySelector('.feels-like');
let humidity = document.querySelector('.humidity');
let locationIcon = document.querySelector('.weather-icon');
let checkbox = document.getElementById('celcius');
let weather_sec = document.querySelector('.weather-info');
let degree_section = weather_sec.firstElementChild;
let degree_section_span = degree_section.getElementsByTagName('span')[0];
//let wind = document.querySelector('.wind');
async function getUrl(city) {
try {
let theUrl = url + city + '&appid=' + apiKey;
let response = await fetch(theUrl, {
mode: 'cors'
})
let data = await response.json();
//Get data from api and change html content based on the recieved data
let temp_data = data.main.temp
temp.textContent = temp_data;
let feels_like_data = data.main.feels_like;
feels_like.textContent = feels_like_data + "K";
let humidity_data = data.main.humidity;
humidity.textContent = humidity_data;
let {
icon
} = data.weather[0];
locationIcon.innerHTML = `<img src="icons/${icon}.png">`;
//change K to C
degree_section.addEventListener('click', () => {
//logging a message just to check if it is working
console.log("c")
})
} catch (err) {
let error = document.createElement('span')
error.className = "error";
error.textContent = "Location does not exist"
let top_center_div = document.querySelector('.top-center')
top_center_div.appendChild(error)
city_name.textContent = "No city found"
}
}
searchbtn.addEventListener('click', (e) => {
let cityName = city.value;
city_name.textContent = cityName
console.log(cityName)
getUrl(cityName)
})
<body>
<div class="loc-container">
<div class="location">
<h1 class="city-name">City</h1>
<div class="weather-icon"><img src="icons/unknown.png" /></div>
</div>
</div>
<div class="weather-info">
<div class="degree-section">
<h2 class="temp">0.0</h2>
<span>K</span>
</div>
<div class="info-section">
<div class="info-flex">
<h3 class="feels-like">0K</h3>
<h4>Feels Like</h4>
</div>
<div class="info-flex">
<h3 class="humidity">0</h3>
<h4>Humidity</h4>
</div>
<div class="info-flex">
<h3 class="wind">0</h3>
<h4>Wind</h4>
</div>
</div>
</div>
<div class="top-center">
<div class="form">
<input type="text" name="city" id="city" required>
<label for="city" class="label-name"><span class="search-name">Search City...</span></label>
</div>
<!-- <i class="fas fa-search search-btn"></i> -->
<i class="material-icons search-btn" style="font-size: 35px;">search</i>
</div>
<script src="weather.js"></script>
</body>
This is what "data" looks like
{"coord":{"lon":72.8479,"lat":19.0144},"weather":[{"id":711,"main":"Smoke","description":"smoke","icon":"50d"}],"base":"stations","main":{"temp":303.14,"feels_like":303.45,"temp_min":301.09,"temp_max":303.14,"pressure":1014,"humidity":45},"visibility":2500,"wind":{"speed":3.09,"deg":120},"clouds":{"all":20},"dt":1638773692,"sys":{"type":1,"id":9052,"country":"IN","sunrise":1638754125,"sunset":1638793848},"timezone":19800,"id":1275339,"name":"Mumbai","cod":200}
Thank you in advance!
I believe the problem is with
let degree_section_span = degree_section.getElementsByTagName('span')[0];
since it selects the wrong element. Try changing it to
let degree_section_span = weather_sec.querySelector('.check');
and see if it works. You can also change the variable name to something more appropriate, while you're at it.
EDIT:
I think this is what you're trying to do. For the sake of siplicity , I removed everything not related to temp:
let target = weather_sec.querySelector("div.check"),
temp_data = data.main.temp;
temp.textContent = temp_data;
target.addEventListener('click', () => {
cel = parseInt(temp_data) - 273.15;
temp.textContent = cel.toFixed(2);
temp.nextElementSibling.textContent = "C";
});
So after 48hrs of debugging I finally figured out what is wrong. If you see in my HTML I have a div.top-center at the bottom. And due to some dimension issues in my css file the height of div.top-center spanned the entire page so essentially all of my divs were being wrapped inside div.top-center so even if I assigned a click event to my div.degree-section the target was always div.top-center and that is why the click event was not showing the proper output.

Cannot pass Object as param to onClick while iterating with innerHTML

I am currently iterating through a list of movies and want to be able to make each element clickable and pass their respective movie information to the click event.
Here is how I iterate through my data. I want to be able to pass the movie information to the click event so that when I click on a movie, I can display its information :
const APIKEY = 'api_key=blabla....';
const BASE_URL = 'https://api.themoviedb.org/3';
const API_URL = BASE_URL + '/discover/movie?sort_by=popularity.desc&' + APIKEY;
const IMG_URL = 'https://image.tmdb.org/t/p/w500';
const SEARCH_URL = BASE_URL + '/search/movie?' + APIKEY;
const main = document.getElementById('main')
const form = document.getElementById('form')
const search = document.getElementById('search')
getMovies(API_URL);
function getMovies(url) {
fetch(url).then(res => res.json()).then(data => {
showMovies(data.results);
console.log(data.results)
})
}
function showMovies(data){
main.innerText = '';
data.forEach((movie, index) => {
let {title, poster_path, release_date, overview} = movie;
let movieEl = document.createElement('div');
movieEl.classList.add('movie');
movieEl.innerHTML = `
<div onclick="showMovieInfo(${movie[index]})" style="cursor: pointer;">
<img src="${IMG_URL + poster_path}" alt="${title}">
<div class="movie-info">
<h3>${title}</h3>
<span>${release_date.slice(0,4)}</span>
</div>
<div class="overview">
${overview}
</div>
</div>
`
main.appendChild(movieEl)
})
}
For Now i just want to be able to console.log the movie info for each
function showMovieInfo(movie) {
console.log(movie)
}
Currently I get this error when I click on an element: Uncaught SyntaxError: Unexpected identifier
Do you guys know what I could do to make it work?
The problem here ist that the "movie" object don´t exist in the "innerHTML" context. One Solution would be to serialise the movie Object or pass the Index and than get the Object from the data Array.
You can´t pass an Object to innerHTML so you have to pass a Primitive values like string or number.
const main = document.getElementById('main');
const IMG_URL = "/"
const data = [{title: "New Movie", poster_path:"",release_date:"2021-10-31", overview:"nice movie" }];
function showMovieInfo(movieId){
console.log(data[movieId])
}
function showMovies(data){
main.innerText = '';
data.forEach((movie, index) => {
let {title, poster_path, release_date, overview} = movie;
let movieEl = document.createElement('div');
movieEl.classList.add('movie');
movieEl.innerHTML = `
<div onclick="showMovieInfo(${index})" style="cursor: pointer;">
<img src="${IMG_URL + poster_path}" alt="${title}">
<div class="movie-info">
<h3>${title}</h3>
<span>${release_date.slice(0,4)}</span>
</div>
<div class="overview">
${overview}
</div>
</div>
`
main.appendChild(movieEl)
})
}
showMovies(data);
<div id="main">
</div>

Using fetch results as function parameters

i have fetchTeam(teamName) function which gets an array of players and displays them in HTML. and another function that takes a player name as a parameter and displays the player stats. Something like this....
let result = document.getElementById("result");
let teamName;
const fetchTeam = async (teamName) => {
teamName = document.getElementById("teamName").value;
const response = await fetch(`http://localhost:3000/${teamName}`);
const data = await response.json();
let team = data.teamStats;
let players = data.playerStats;
const teamName = team[0].Name;
const logo = team[0].Logo;
const WL = team[0].WL;
result.innerHTML = `
<br><div class="top">
<h3>${teamName}</h3>
<h4>Win / Loss: ${WL}</h4>
<img src=${logo}></div>
<div class="flex-container">
<div class="flex-child">
<button class='name' onclick="fetchPlayer("${players[0][0].Player}")> ${players[0][0].Player} </button> ...
`
That all works fine except the onclick fetchPlayer function at the bottom.... Heres the code for that:
const results = document.getElementById("results");
const fetchPlayer = async (player) => {
const response = await fetch(`https://get-player.herokuapp.com/${player}`);
const data = await response.json();
results.innerHTML = `
<br>
<div class="layout">
<div class="child"><img src="${data.sprite}[0]"><br>${data.mons[0]}</div>
`
As you can see, i want to display the team members and then clicking on a member name will show their stats.
edit: format
There are several issues in your code.
First, you redeclare teamName in your fetchTeam function. That cannot work.
const fetchTeam = async (teamName) => {
teamName = document.getElementById("teamName").value;
...
const teamName = team[0].Name;
}
Second, your button syntax is incorrect :
<button class='name' onclick="fetchPlayer("${players[0][0].Player}")>
should be
<button class='name' onclick="fetchPlayer('${players[0][0].Player}')">
Third, as pointed out in this answer, in your fetchPlayer function
<img src="${data.sprite}[0]"> should be <img src="${data.sprite[0]}">
In the fetchPlayer function,
Change <img src="${data.sprite}[0]"> to <img src="${data.sprite[0]}">

Categories

Resources