How to loop pokemons out from the PokeAPI? - javascript

Hi I am in the process of fetching data down from the pokeapi, I can loop them out in the console, but when I send them to the div ID__Pokemon only the last index comes out, what is the best way to loop the pokemon names out in ID__Pokemon ?
let myApp = document.querySelector('#App');
const divPokemon = document.getElementById('ID__Pokemon');
const api_url = 'https://pokeapi.co/api/v2/pokemon/';
const pokemonData = async () => {
const response = await fetch(api_url);
const data = await response.json();
for (const item in data.results) {
let pokemon = data.results[item];+
console.log(pokemon.name);
divPokemon.innerHTML = `Pokemon: ${pokemon.name}`;
}
};
pokemonData();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="function.js" defer></script>
</head>
<body>
<div id="App">
<div id="ID__Pokemon"></div>
</div>
</body>
</html>

doing divPokemon.innerHTML = `Pokemon: ${pokemon.name}`; replaces the content with each iteration
Here is an edit of your code which adds a new "li" element to your list, filled with the proper text content
let myApp = document.querySelector('#App');
const divPokemon = document.getElementById('ID__Pokemon');
const api_url = 'https://pokeapi.co/api/v2/pokemon/';
const pokemonData = async () => {
const response = await fetch(api_url);
const data = await response.json();
for (const item in data.results) {
let pokemon = data.results[item];
console.log(pokemon.name);
let newPokemon = document.createElement("li");
newPokemon.innerText = `Pokemon: ${pokemon.name}`;
divPokemon.appendChild(newPokemon);
}
};
pokemonData();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="function.js" defer></script>
</head>
<body>
<div id="App">
<div id="ID__Pokemon"></div>
</div>
</body>
</html>

Related

How do you add a loading GIF spinner before AOI response in vanilla javascript?

So far I've tried using the let method make the GIF a constant and attempting to switch display type is js style function. Can someone guide me into displaying GIF image before API response and hiding it when fetch() is processed.
Html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./doggos.css">
<title>Dogs</title>
</head>
<body>
<h1>Doggos</h1>
<button class="add-doggo">Add Doggo</button>
<div class="doggos">
<div class="loader"><img src="./giphy (1).gif"></img></div>
</div>
<script src="./doggos.js"></script>
</body>
</html>
Javascript
const DOG_URL = "https://dog.ceo/api/breeds/image/random";
const doggos = document.querySelector(".doggos");
function addNewDoggo() {
const promise = fetch(DOG_URL);
promise
.then(function(response) {
const processingPromise = response.json(); //This line of code parses the API response into a usuable js object
return processingPromise; //this code returns a new promise and this process is called | PROCESS-CHAINING
})
.then(function(processedResponse) {
const img = document.createElement("img");
img.src = processedResponse.message;
img.alt = "Cute doggo";
doggos.appendChild(img);
});
}
document.querySelector(".add-doggo") .addEventListener("click", addNewDoggo)

how to store my data in local storage as object from what I've got

Two buttons counting and storing data in local storage, just trying to make it store as obj in local storage, but I'm a newbie and couldn't make it work can some1 explain how to do it from what I've got? thank you! don't know if I can just add this here or need to do it from scratch?
const wellbtn = document.querySelector('.wellbtn');
const unwellbtn = document.querySelector('.unwellbtn');
const moodwell = document.querySelector('.moodwell')
const moodunwell = document.querySelector('.moodunwell')
let wellcounter = localStorage.getItem('wellcounter');
let unwellcounter = localStorage.getItem('unwellcounter');
moodwell.innerText = `You felt well ${wellcounter} times`;
moodunwell.innerText = `You felt unwell ${unwellcounter} times`;
const addWellCounter = (() => {
moodwell.innerText = `You felt well ${++wellcounter} times`
localStorage.setItem('wellcounter', wellcounter.toString());
})
const addUnwellCounter = (() => {
moodunwell.innerText = `You felt unwell ${++unwellcounter} times`
localStorage.setItem('unwellcounter', unwellcounter.toString());
})
wellbtn.addEventListener('click', () => {
addWellCounter();
})
unwellbtn.addEventListener('click', () => {
addUnwellCounter();
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My title</title>
</head>
<body>
<h1>How do you feel ?</h1>
<button class="wellbtn">Well</button>
<button class="unwellbtn">Unwell</button>
<p class="moodwell">You felt well 0 times</p>
<p class="moodunwell">You felt unwell 0 times</p>
</body>
</html>

How do you display all images coming from the newsapi?

Hi I am trying to create a news app using the newsapi. I have managed to display the headings from the api but cant seem to manage to loop over all the images and be displayed to the screen. If you could show me how this could be done I would very much appreciate this. my code is:
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/main.css">
<title>News App</title>
</head>
<body>
<h2>BBC News</h2>
<span class="newsImage"></span>
<li class = newsList></li>
<script src="js/main.js"></script>
</body>
</html>
JavaScript
const newsList = document.querySelector(".newsList")
const newsImage = document.querySelector(".newsList")
newsImage.innerHTML =''
newsList.innerHTML= ''
var url = 'https://newsapi.org/v2/top-headlines?' +
'sources=bbc-news&' +
'apiKey=**********************';
var req = new Request(url);
fetch(req)
.then(function(response) {
return response.json()
}).then((data)=>{
console.log(data)
data.articles.map(article => {
let li = document.createElement('li')
let a = document.createElement('a')
let image = document.createElement('span')
image.innerHTML = `<img src=${data.articles.urlToImage}>`
a.setAttribute('href', article.url)
a.setAttribute('target','_blank' )
a.textContent = `${article.title}`
li.appendChild(a)
newsList.appendChild(li)
newsImage.appendChild(image)
});
})

How to create a form for comments with the ability of dynamically adding them to the list?

I need to create a form for comments with the ability to dynamically add them to the list. Each comment should have an assigned ID in consecutive order. The newest comment should be at the very bottom. Comments should be stored in the comments array. Each comment should have properties such as id (number) and text (string). Comments array must be empty when loaded initially. Each click on the "Add" button should create a new object inside the array and create element in the DOM tree.
let nextId = 1;
const comments = [];
const commentForm = document.querySelector('[data-id="comment-form"]');
const commentInput = commentForm.querySelector('[data-input="comment"]');
const button = commentForm.querySelector('[data-action="add"]');
const commentList = commentForm.querySelector('[data-id="comment-list"]');
button.addEventListener('click', () => {
const object = {};
if (commentInput.value != '') {
comments.map(() => ({ id: 'nextId++', text: commentInput.value }));
}
createElement();
});
function createElement() {
const newComment = document.createElement('li');
newComment.setAttribute('data-comment-id', comments.id);
newComment.textContent = comments.text;
commentList.appendChild(newComment);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title></title>
<link rel="stylesheet" href="./css/styles.css" />
</head>
<body>
<div id="root">
<form data-id="comment-form">
<textarea data-input="comment"></textarea>
<button data-action="add">Add</button>
</form>
<ul data-id="comment-list"></ul>
</div>
<script src="./js/app.js"></script>
</body>
</html>
There are some issues in your code:
You are trying to access commentList from commentForm, but that element is outside of the commentForm. Use document object to access the element.
comments is an array from which you are trying to access text property, there is text property on comments.
You should pass the current input value to the function so that you can set the newly created LI's text with the value.
You should use push() instead of map() to push an item into the array. nextId is a variable but you are using that as if it is a string, you should remove the quotes around it.
For the better user experience, I will suggest you to clear the value of the input after creating the item.
Demo:
let nextId = 1;
const comments = [];
const commentForm = document.querySelector('[data-id="comment-form"]');
const commentInput = commentForm.querySelector('[data-input="comment"]');
const button = commentForm.querySelector('[data-action="add"]');
const commentList = document.querySelector('[data-id="comment-list"]');
button.addEventListener('click', () => {
const object = {};
if (commentInput.value != '') {
comments.push({ id: nextId++, text: commentInput.value });
}
createElement(commentInput.value);
commentInput.value = '';
});
function createElement(ci) {
const newComment = document.createElement('li');
newComment.setAttribute('data-comment-id', comments.id);
newComment.textContent = ci;
commentList.appendChild(newComment);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title></title>
<link rel="stylesheet" href="./css/styles.css" />
</head>
<body>
<div id="root">
<form data-id="comment-form">
<textarea data-input="comment"></textarea>
<button type="button" data-action="add">Add</button>
</form>
<ul data-id="comment-list"></ul>
</div>
<script src="./js/app.js"></script>
</body>
</html>

Leaflet: How to fetch geojson from URL and pass it to L.geoJson

I try to load a geojson from an URL and display it in a map with leaflet:
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css"/>
<script src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js"></script>
</head>
<body>
<div id="my_map" style="height: 600px"></div>
<script>
const map = L.map('my_map')
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
map.setView([37.8, -96], 4);
async function load_shapefile() {
let url = 'https://raw.githubusercontent.com/shawnbot/topogram/master/data/us-states.geojson';
let shape_obj = await (await fetch(url)).json();
return shape_obj
}
L.geoJson(load_shapefile()).addTo(map);
</script>
</body>
</html>
I get on the JS Console:
Uncaught Error: Invalid GeoJSON object.
at De (GeoJSON.js:221)
at i.addData (GeoJSON.js:117)
at initialize (GeoJSON.js:92)
at new i (Class.js:22)
at Object.Ke (GeoJSON.js:439)
at leaflet.html:21
If possible, I would like to not use jQuery.
Thanks for any input!
EDIT: I replaced the url with an actual GeoJSON file, thanks #IvanSanchez!
If you want to extract the geojson and use it later you need to create another function to await the result as the operation is asynchornous:
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js"></script>
</head>
<body>
<div id="my_map" style="height: 600px"></div>
<script>
const map = L.map('my_map')
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
map.setView([37.8, -96], 4);
async function load_shapefile() {
let url = 'https://raw.githubusercontent.com/shawnbot/topogram/master/data/us-states.geojson';
const response = await fetch(url)
const shape_obj = await response.json();
console.log(shape_obj);
return shape_obj;
}
async function main() {
const json = await load_shapefile();
L.geoJson(json).addTo(map);
}
main();
</script>
</body>
</html>
Otherwise if you do not want to use the geojson instance further use then to fetch the data and immediately use them.
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js"></script>
</head>
<body>
<div id="my_map" style="height: 600px"></div>
<script>
const map = L.map('my_map')
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
map.setView([37.8, -96], 4);
let url = 'https://raw.githubusercontent.com/shawnbot/topogram/master/data/us-states.geojson';
const response = fetch(url).then(response => response.json()).then(response => {
L.geoJson(response).addTo(map);
})
</script>
</body>
</html>
#kboul's answer already points out how to fix it, but doesn't explain why it fails in the first place.
The original code is failing because async functions return an instance of Promise, and the L.GeoJSON constructor expects a static data structure.
So instead of
async function load_shapefile() {
let url = 'https://raw.githubusercontent.com/shawnbot/topogram/master/data/us-states.geojson';
let shape_obj = await (await fetch(url)).json();
return shape_obj
}
L.geoJson(load_shapefile()).addTo(map);
You can do
load_shapefile().then(function(geojsonData){
L.geoJson(load_shapefile()).addTo(map);
});
And abusing the syntax of .then() a bit to pass function references only:
load_shapefile().then(L.geoJson).then(map.addLayer.bind(map));
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js"></script>
</head>
<body>
<div id="my_map" style="height: 600px"></div>
<script>
const map = L.map('my_map')
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
map.setView([37.8, -96], 4);
async function load_shapefile() {
let url = 'https://raw.githubusercontent.com/shawnbot/topogram/master/data/us-states.geojson';
const response = await fetch(url)
const shape_obj = await response.json();
console.log(shape_obj);
return shape_obj;
}
load_shapefile().then(L.geoJson).then(map.addLayer.bind(map));
</script>
</body>
</html>

Categories