Fetching data from an API - Console Repeats - javascript

I am having a bit of trouble.
I need to create a website that will display three random Chuck Norris jokes using the following API: http://www.icndb.com/api/. I have to use the following URL to fetch the jokes: http://api.icndb.com/jokes/random/3.
My HTML is as follows:
<!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>Chuck Norris Jokes</title>
<link rel="stylesheet" href="css/main.css" type="text/css">
</head>
<body>
<!-- Added a navigation bar to display logo. -->
<nav class="navigation-bar">
<img src="images/Logo.png" alt=Logo id="logo" />
</nav>
<!-- Created a container so I can set the grid sections. -->
<div id="container">
<!-- First container for the heading and the image. -->
<div>
<h1>Chuck Norris Jokes</h1>
<img src="images/chuck.png" alt="Chuck Norris Armed" id="chuckshoot">
</div>
<!-- Second section for the text and for the button. -->
<div id="jokegen">
<div id="jokeTxt">
<p id="j1"></p>
<p id="j2"></p>
<p id="j3"></p>
</div>
<button id="jokeBtn" value="fetch">Click Here For A Chuckle!</button>
</div>
</div>
<script type="text/javascript" src="js/main.js"></script>
</body>
</html>
My Javascript is as follows:
// Created an array for the Chuck Norris jokes.
let joke = [];
// Attached an event handler to the button.
document.getElementById('jokeBtn').addEventListener('click', function () {
// Fetching the API.
fetch("http://api.icndb.com/jokes/random/3")
// Grabbing the information from the JSON file.
.then(res => res.json())
// Fetching the joke from value in JSON.
.then(function (result) {
for (let i = 0; i < result.value.length; i++) {
jokes = result.value[0].joke;
jokes2 = result.value[1].joke;
jokes3 = result.value[2].joke;
console.log(jokes);
console.log(jokes2);
console.log(jokes3);
console.log(typeof joke);
// Displaying the fetched jokes in HTML.
document.getElementById("j1").innerHTML = jokes;
document.getElementById("j2").innerHTML = jokes2;
document.getElementById("j3").innerHTML = jokes3;
}
}),
// If the above could not be executed and an error should occur.
error => {
console.log(error + "");
};
})
The HTML is showing correctly but in console all three jokes appear even if I call a single joke. Please see the screenshot below:
Thank you in advance for the help.

You can simplify the Javascript a little and use a forEach loop on the value property within the response.
The error => {console.log(error + "")} piece is not quite right - that should be within a catch segment - ie .catch( err=>console.log(err) ) or similar
document.getElementById( 'jokeBtn' ).addEventListener('click', ()=>{
fetch( 'https://api.icndb.com/jokes/random/3' )
.then( res => res.json() )
.then( json => {
if( json.type=='success' ){
json.value.forEach( ( obj, i )=>{
let node=document.getElementById( 'j' + ( i + 1 ) );
if( node )node.innerHTML=obj.joke;
})
}
})
})
<nav class="navigation-bar">
<img src="images/Logo.png" alt=Logo id="logo" />
</nav>
<div id="container">
<div>
<h1>Chuck Norris Jokes</h1>
<img src="images/chuck.png" alt="Chuck Norris Armed" id="chuckshoot">
</div>
<div id="jokegen">
<div id="jokeTxt">
<p id="j1"></p>
<p id="j2"></p>
<p id="j3"></p>
</div>
<button id="jokeBtn" value="fetch">Click Here For A Chuckle!</button>
</div>
</div>

Related

How to populate different category data from the same api at the DOM using javascript?

I'm currently working with news API and trying to populate different category (i.e sports, science, business etc) under different heading on the same page of the website, but failed to do so. Here I tried to use template literal, as first created a template literal in the api named category and initiated it using let. So there are two sections "Trending Blogs" and "You May Like" so here I wanna show two different category in the two different section respectively. Here I'm attaching the code in the following.
Here is the code in 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="/styles/utils.css" />
<link rel="stylesheet" href="/styles/navbar.css" />
<link rel="stylesheet" href="/styles/body.css" />
<script
src="https://kit.fontawesome.com/e582ecfb98.js"
crossorigin="anonymous"
></script>
<title>Document</title>
</head>
<body>
<!-- <h1>This is a blog site</h1> -->
<!-- Navbar starts from here -->
<nav class="navigation max-width-0 m-auto">
<div class="middle">
<b> Blogsite</b>
</div>
<div class="left">
<ul>
<li><a class="header-elements" href="./index.html">Home</a></li>
<li><a class="header-elements" href="./about.html">About</a></li>
<li><a class="header-elements" href="./contact.html">Contact</a></li>
</ul>
</div>
<div class="right">
<input type="text" placeholder="Article Search" />
<button class="btn"><i class="fa fa-magnifying-glass"></i></button>
</div>
</nav>
<!-- Navbar ends -->
<!-- body starts -->
<div class="content max-width-1 m-auto">
<h1 class="land-heading">Welcome to Blogsite</h1>
<p class="intro">
Atameo allows travellers to capture their trips in a completely new way.
It records your route, adds your photos, videos and music and turns your
adventures into your personal travel profile. Have all your travel
experiences in one place and find out more about your travel style by
diving into your personal travel statistics: How far did you travel last
year? What’s the highest point you have been to? How much of the world
have you seen? Inspire others to go out and explore, while getting
inspired by some of the most daring journeys of our time. Explore.
Capture. Inspire.
</p>
<hr />
<h1 class="land-heading">Trending Blogs</h1>
<div class="blog-section" id="blog-section">
</div>
<h1 class="land-heading">You may like</h1>
<div class="blog-section" id="blog-section2">
</div>
<h1 class="land-heading">Categories</h1>
<div class="blog-section" id="category">
<div class="r1c1 block">
<a href=""
><img
class="img"
src="https://www.nomadicmatt.com/wp-content/uploads/2022/07/parisnm3.jpeg"
alt="img"
/>
<p class="blog-title">NM+ Weekly Update: Europe Edition</p></a
>
</div>
</div>
</div>
<!-- Body ends -->
<!-- Footer starts -->
<div class="footer m-auto">
<label for="">Feedback</label>
<input type="text" class="" placeholder="First Name" />
<input type="text" placeholder="e-mail" />
<button type="submit" class="btn btn-foot">Send Feedback</button>
</div>
<div class="m-auto copyright">
<p>copyright 2022 #md_arif</p>
</div>
<!-- Footer ends -->
<script src="./scripts/app.js"></script>
</body>
</html>
`
Here is the code of vanilla-js
console.log("Here we go");
let blogSection = document.getElementById("blog-section");
let blogSection2 = document.getElementById("blog-section2");
function generateCards(e) {
const newXHRRequest = new XMLHttpRequest();
// let source = 'the-times-of-india';
let apikey = '75da3b7678de41fcb76359935aabdc3d'
let category = '';
newXHRRequest.open(
"GET",
`https://newsapi.org/v2/top-headlines?country=in&category=${category}&pagesize=3&apiKey=${apikey}`,
true
);
newXHRRequest.getResponseHeader("content-type", "application/json");
newXHRRequest.onload = function () {
if (this.status === 200) {
let myCards = JSON.parse(this.responseText);
console.log(myCards);
let articles = myCards.articles;
// console.log(articles);
let itemsHtml = "";
articles.forEach((element) => {
// console.log(articles);
// category="sports";
console.log(element);
let items = `<div class="r1c1 block">
<a href="${element["url"]}" target="_blank"><img class="img" src=${element["urlToImage"]} alt="img">
<p class="blog-title">${element["title"]}</p></a>
</div>`;
itemsHtml += items;
});
blogSection.innerHTML = itemsHtml;
blogSection2.innerHTML = itemsHtml;
} else {
console.log("Some error occured");
}
};
newXHRRequest.send();
}
generateCards();

In my Project (Random quote generator). I am unable to sort issue?

I am making Random quote machine project using vanilla javaScript. I am doing this project using fetch-api(quotable.io) and simple Dom manipulation. My code is correct but there is some issues that I am unable to identify.
My Code is:
<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="Random.css">
<title>Random Quotes Machines</title>
</head>
<body>
<h1>Random Quotes </h1>
<br> <br>
<div class="container">
<p class="p">undefined </p>
<h6 class="author"> undefined</h6>
</div>
<button class="NextQuote" onclick="NextQuote()">NextQuote</button>
<!-- <button class="previous">Previous</button> -->
<script>
let container = document.getElementsByClassName("container");
let p = document.querySelector(".p");
let author = document.querySelector(".author");
let rem;
function NextQuote (){
rem = Math.floor(Math.random()*100);
fetch('https://api.quotable.io/random')
.then(response => response.json())
.then(quotes => {
p.innerHtml = '"${quotes.content}"';
}
);
}
</script>
</body>
</html>
You need to change innerHtml to innerHTML.
And you need to change '"${quotes.content}"' to quotes.content.
The result would be:
fetch('https://api.quotable.io/random')
.then(response => response.json())
.then(quotes => {
p.innerHTML = quotes.content;
}
);
Your sample almost works. There are only some small issues in your code:
quotes.content contains a plain text, to add the text to the paragraph you could use p.textContent instead.
you are using simple quotes instead of backticks for the template string, so your variable quotes.content wouldn't be interpolated.
To make it work replace the line p.innerHtml = '"${quotes.content}"'; with p.textContent = `"${quotes.content}"`;

What could be wrong with my keypress event?

I'm trying to make a weather app, and use the API from openweathermap, I copied the baseurl from the web like this but it's not currently working...
const api = {
key:"03173bc8739f7fca249ae8d681b68955"
baseurl:"https://home.openweathermap.org/api_keys"
}
const searchbox=document.querySelector('.search-box');
searchbox.addEventListener('keypress', setQuery)
function setQuery(evt){
if (evt.keyCode==13)
//getResults(searchbox.value)
console.log(searchbox.value)
}
So when I type in the search box, the console doesn't show anything...
This is my html file:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title> </title>
<link rel="stylesheet" href="weather.css">
</head>
<body>
<div class="app-wrap">
<header>
<input type="text" autocomplete="off" class="search-box" placeholder="Search for a city...">
</header>
<main>
<section class="location">
<div class="city">HCM City, Viet Nam</div>
<div class="date">Friday 25 June 2021</div>
</section>
<div class="current">
<div class="tempt">15<span>°C</span></div>
<div class="weather">Sunny</div>
<div class="high-low">13°C / 16°C</div>
</div>
</main>
</div>
<script src="weather.js"></script>
</body>
</html>
Is there something wrong with the baseurl or something, can anybody tell me?
wrap the selector with " ";
const searchbox = document.querySelector(".search-box");
also correct your api obj:
const api = {
key: "03173bc8739f7fca249ae8d681b68955",
baseurl: "https://home.openweathermap.org/api_keys"
}
You missed to add single quote in querySelector.
const searchbox=document.querySelector('.search-box'); // Corrected
also you need to update the API object
const api = {
key:"03173bc8739f7fca249ae8d681b68955",
baseurl:"https://home.openweathermap.org/api_keys"
}

How can I get search functionality to work when typing in search queries in the input box?

I am making a news style app that uses the newsapi. I want to ask how do I get search functionality to work, how do I get the HTML input box to display the results of what you type in. I have tried a few times to get it to work but can't. Any suggestions appreciated.
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/style.css">
<title>News App</title>
</head>
<body>
<header>
<h1 class="heading">News</h1>
<form class="searchform" autocomplete="off">
<input class="searchBox" name="search" type="text" >
<button type="submit">Submit</button>
</form>
<li class="newsList"></li>
<script src="js/main.js"></script>
</header>
</body>
JavaScript
const newsList = document.querySelector(".newsList")
const newsImage = document.querySelector(".newsList")
const form = document.querySelector("form.search")
newsImage.innerHTML = ''
newsList.innerHTML= ''
const url = 'https://newsapi.org/v2/everything?' +
'q=${search}&' +
'from=2021-06-02&' +
'sortBy=popularity&' +
'apiKey=****************';
let 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="${article.urlToImage}" >`
a.setAttribute('href', article.url)
a.setAttribute('target','_blank' )
a.textContent = `${article.title}`
li.appendChild(a)
newsList.appendChild(li)
newsImage.appendChild(image)
});
})
function handleSubmit(e){
e.preventDefault()
console.log(e.target)
}
form.addEventListener('submit', handleSubmit)
Okay so I don't have an API key to the news API that you are using but I instead used a free Rick & Morty API to answer your question.
I had to make some alterations to your code in order to get it to work with my API but I added a bunch of comments in the code snippet to hopefully make it make a bit of sense why I made the changes and also how you can change it back to work with your news API. Good luck!
const characters = document.querySelector(".characters");
const searchInput = document.querySelector("#search");
characters.innerHTML = "";
// We also changed this here to include the actual act of fetching the data - you would instead do your news fetch here.
function handleClick(e) {
let url = "https://rickandmortyapi.com/api/character/";
// This here maps a HTMLCollection into a JavaScript array and then removes previous children if they exist,
// this is to clear the list items prior to a new search.
if (characters.children.length > 0)
Array.from(characters.children).forEach((child) => child.remove());
// If we provide a search input include it in the URL - note the only search we can do here is for pages so the input is now a number.
// This is where you would instead change your news URL and append the "searchInput.value" into the "search section" like so:
//
// const url =
// "https://newsapi.org/v2/everything?" +
// `q=${searchInput.value}&` +
// "from=2021-06-02&" +
// "sortBy=popularity&" +
// "apiKey=****************";
//
// Note that in order to use a variable you need backticks as your quote delimeter. See like `${variable}` instead of '' or "".
if (searchInput.value)
url =
"https://rickandmortyapi.com/api/character/" +
`?page=${searchInput.value}`;
let req = new Request(url);
fetch(req)
.then(function (response) {
return response.json();
})
.then((data) => {
console.log(data);
// I removed your image mapping here because I had no image from this free Rick and Morty API but I hope you get the idea.
data.results.map((character) => {
let li = document.createElement("li");
let a = document.createElement("a");
a.setAttribute(
"href",
"https://rickandmortyapi.com/api/character" + `/${character.id}`
);
a.setAttribute("target", "_blank");
a.textContent = `${character.name}`;
li.appendChild(a);
characters.appendChild(li);
});
});
}
<!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" />
<!-- I removed this because I had no css file -->
<!-- <link rel="stylesheet" href="css/style.css" /> -->
<title>Test App</title>
</head>
<body>
<header>
<h1 class="heading">Test</h1>
<form class="searchform" autocomplete="off">
<!-- <input id="search" class="searchBox" name="search" type="text" /> -->
<!-- Because my search in the free API could only handle numbers I changed the type here -->
<!-- You will want to change that back to the above commented out text field -->
<input id="search" class="searchBox" name="search" type="number" />
<!-- Instead of using prevent default I changed the action here to be the onclick of the button -->
<!-- That fires off our "handleClick()" method that lives in our main.js file -->
<button type="button" onclick="handleClick()">Submit</button>
</form>
<div class="characters"></div>
<script src="main.js"></script>
</header>
</body>
</html>

Javascript - looping through data with each click

I'm fairly new to Javascript I have been playing with some data fetching for the past few days. I created this very simple program (if you can even call it that), where if you click a button, it will generate a div with a random user (using jsonplaceholder API). My issue is, that whenever the button is clicked, it gives me all 10 users at once. I'd like it to give me one user with each click instead. As I said, I am fairly new to JS so I'm not sure how to aproach this (I guess some sort of a loop would be involved?). Any sort of advice, tips or anything would be welcomed ! Thank you !
Here is my code (Using Bootstrap 4 for styling and Axios for data fetching):
const mainButton = document.getElementById('mainButton');
const targetDiv = document.getElementById("targetDiv");
mainButton.addEventListener('click', () => {
axios
.get("https://jsonplaceholder.typicode.com/users")
.then(function(response) {
let ourRequest = response;
renderData(ourRequest.data);
})
.catch(function(error) {
console.log(error);
});
function renderData(data) {
var stringHTML = "";
for (i = 0; i < data.length; i++) {
stringHTML += `
<div class="col-md-4">
<div class="card">
<div class="card-header">
User ID: #${data[i].id}
</div>
<div class="card-body">
<h4 class="card-title">${data[i].name}</h4>
<p class="card-text">Email - <em>${data[i].email}</em></p>
<p class="card-text">Phone - <em>${data[i].phone}</em></p>
<p class="card-text">Address - <em>${data[i].address.street}, ${data[i].address.city}, ${data[i].address.zipcode}</em></p>
</div>
</div>
</div>
`;
}
targetDiv.insertAdjacentHTML("beforeend", stringHTML);
}
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="main.css">
<title>JSON Users</title>
</head>
<body>
<div class="container">
<div class="text-center my-5">
<h1 class="display-4">Random JSON Users</h1>
<p>This is a random user generator, click the below button to get a
random person!</p>
<button id="mainButton" class="btn btn-primary">Get User!</button>
</div>
<!-- Users -->
<div id="targetDiv" class="row">
</div>
</div>
<!-- JavaScript -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="main.js"></script>
</body>
</html>
If I get it right that your GET method is asking for users, so response contains more that one user. This response you send to renderData method and there you generate your div for each user from response. I supouse to change your GET method to get only one user or send only one user to renderData method like ourRequest.data[0] from your current solution.

Categories

Resources