Local undefined 404 when doing API call - javascript

This project is using the cocktail api to search for a specific ingredient (think gin or vodka) and then return all the drinks that contain the ingredient. I was able to get the results to display, but I wanted the thumbnail pic of the drink (included in the api as strDrinkThumb). When I try to get the pictures to display I get the follow error:
GET http://local/undefined 404 (Not Found)
window.addEventListener('DOMContentLoaded', (event) => {
console.log('DOM fully loaded and parsed');
});
let ingredients = document.getElementById('ingredients');
let searchTerm= document.getElementById('search-Bar');
let searchBtn = document.getElementById('searchBtn');
let drinkInfo = document.getElementById('drinkInfo');
let ingredientList = []
searchBtn.addEventListener("click", async (e) => {
const searchString = searchTerm.value.toLowerCase();
fetch(`https://www.thecocktaildb.com/api/json/v1/1/filter.php?i=${searchString}`)
.then((response) => response.json())
.then((filteredIngredients) => {
displayIngredient(filteredIngredients.drinks);
})
.catch((error) => {
});
});
function displayIngredient(drinkData){
const ingredients = [];
//maps over array and makes new array
drinkInfo.innerHTML = drinkData.map( ({strDrink}) => { //destructuring
//use backticks and html
return` <div> //use backticks and html
<div class="card" style="width: 14rem;">
<div class="card-body">
<h5 class="card-title">${strDrink} </h5>
<img src="${drinkData.strDrinkThumb}"/>
</div></div>
`; //use backticks and html
}).join('');
drinkInfo.appendChild(drinkInfo);
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Cocktail App</title>
<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>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header>
<input type="text" id="search-Bar" placeholder="Enter main ingredient..."/>
<button id="searchBtn">search</button>
</header>
<div class="drinkInfo" id="drinkInfo">
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script>
<script type="text/javascript" src="./extrafile.js"></script>
</body>
</html>

In drinkData.map function you are only pulling strDrink value from the object, you need also get strDrinkThumb
Then you are trying get strDrinkThumb from drinkData which is an array, not an object.
Try this:
drinkInfo.innerHTML = drinkData.map( ({strDrink, strDrinkThumb}) => { //destructuring
//use backticks and html
return` <div> //use backticks and html
<div class="card" style="width: 14rem;">
<div class="card-body">
<h5 class="card-title">${strDrink} </h5>
<img src="${strDrinkThumb}"/>
</div></div>
`; //use backticks and html
}).join('');

Related

Webpage eventlistener and script section not running

Trying to make a basic webpage where you can type a message for it to be displayed on the website. However, the script section of my website does not seem to work.
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<script>
document.addEventListener('DOMContentLoaded', function()
{
let submit = document.querySelector('#submit');
submit.addEventListener('click',function()
{
let questions = document.querySelectorAll('.question');
let input = document.querySelector('input');
for (let i =0; i< questions.length; i++)
{
if questions[i].innerHTML == ""
{
questions[i].innerHTML = 'a';
}
else
{
continue;
}
}
});
function myfunction()
{
alert('test');
}
});
</script>
<title>Write A Message!</title>
</head>
<body class="p-3 mb-2 bg-secondary text-white">
<h1>How to write a message</h1>
<hr>
<p>Type a Message into the textbox below to display a public letter!</p>
<div>
<input type = 'text'>
<button id = 'submit'>Type a message!</button>
</div>
<div>
<h1>Message 1!</h1>
<hr>
<p class = 'question'></p>
<h2>Message 2!</h2>
<hr>
<p class = 'question'></p>
<h3>Message 3!</h3>
<hr>
<p class = 'question'></p>
<button onclick = 'myfunction()'>test</button>
</div>
</body>
</html>
I tried adding a button that would display an alert as well but it does not run as well when clicked.
First, javscript that contains listener/reference to DOM elements is better to include in the end on body, avoid putting in head.
Second, myfunction() is not accessible bebcause you included it under DOMContentLoaded. It should be outside of the listener (global scope).
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<title>Write A Message!</title>
</head>
<body class="p-3 mb-2 bg-secondary text-white">
<h1>How to write a message</h1>
<hr>
<p>Type a Message into the textbox below to display a public letter!</p>
<div>
<input type='text'>
<button id='submit'>Type a message!</button>
</div>
<div>
<h1>Message 1!</h1>
<hr>
<p class='question'></p>
<h2>Message 2!</h2>
<hr>
<p class='question'></p>
<h3>Message 3!</h3>
<hr>
<p class='question'></p>
<button onclick='myfunction()'>test</button>
</div>
<script>
document.addEventListener('DOMContentLoaded', function(){
let submit = document.querySelector('#submit');
submit.addEventListener('click',function(){
let questions = document.querySelectorAll('.question');
let input = document.querySelector('input');
for (let i =0; i< questions.length; i++){
if (questions[i].innerHTML == ""){
questions[i].innerHTML = 'a';
} else {
continue;
}
}
});
});
function myfunction() {
alert('test');
}
</script>
</body>
</html>

How can I use input/search between multiple HTML files?

I'm trying to create a site where you can search up any country and it'll show you detailed information on it using REST Countries API. I want to have a first HTML page with just a search box in the middle where you type your country. You then press search and it'll redirect you to another HTML page where I've set up a template for the countries flag, capital, population, currency, region, and subregion.
I have no clue how to connect them and I've tried messing with the input box id value, looking at search bar & REST Countries API tutorials, but I've figured out nothing. I added a search box to the page where I want ONLY the information to be displayed for testing and it works if I type in the exact country name and it is case sensitive.
How could I even connect these pages & search bar? And if it is possible, how could I make it suggest me countries after I type in one letter?
Main HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/style.css">
<link href="https://fonts.googleapis.com/css2?family=Dosis:wght#500&display=swap" rel="stylesheet">
<script src="https://kit.fontawesome.com/ae3cf15842.js" crossorigin="anonymous"></script>
<title>CountryProjectA</title>
</head>
<body>
<div>
<div class="search-box" >
<input class= "search-txt" type="text" id="search" placeholder="Search for a country" />
<a class="search-btn" href="">
<i class="fas fa-search-location fa-lg"></i>
</a>
</div>
</div>
<script src="main.js"></script>
</body>
</html>
Country info display HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/info-style.css">
<title>Info</title>
</head>
<body>
<h1>Countries</h1>
<div id="main-container">
<div id="flag-container">
<img src="" alt="">
</div>
<div id="info-container">
<input name="" id="countries"></select>
<p>Capital: <span id="capital"></span></p>
<p>Population: <span id="population"></span></p>
<p>Currencies: <span id="currencies"></span></p>
<p>Region: <span id="region"></span></p>
<p>Subregion: <span id="subregion"></span></p>
</div>
</div>
<script src="main.js"></script>
</body>
</html>
Main JS
const countriesList = document.getElementById("countries");
let countries;
countriesList.addEventListener("change", newCountrySelection);
function newCountrySelection(event) {
displayCountryInfo(event.target.value);
}
fetch("https://restcountries.eu/rest/v2/all")
.then(res => res.json())
.then(data => initialize(data))
.catch(err => console.log("Error:", err));
function initialize(countriesData) {
countries = countriesData;
let options = "";
countries.forEach(country => options+=`<option value="${country.alpha3Code}">${country.name}</option>`);
countriesList.innerHTML = options;
countriesList.selectedIndex = Math.floor(Math.random()*countriesList.length);
displayCountryInfo(countriesList[countriesList.selectedIndex].value);
}
function displayCountryInfo(countryByName) {
const countryData = countries.find(country => country.name === countryByName);
document.querySelector("#flag-container img").src = countryData.flag;
document.querySelector("#flag-container img").alt = `Flag of ${countryData.name}`;
document.getElementById("capital").innerHTML = countryData.capital;
document.getElementById("population").innerHTML = countryData.population.toLocaleString("en-US");
document.getElementById("currencies").innerHTML = countryData.currencies.filter(c => c.name).map(c => `${c.name} (${c.code})`).join(", ");
document.getElementById("region").innerHTML = countryData.region;
document.getElementById("subregion").innerHTML = countryData.subregion;
}
Thank you!
You should use this to get the input value in your Javascript code when someone clicks the search button.
document.getElementsByClassName("search-btn")[0].onclick = function() {
var searchInput = document.getElementById("search").value;
// call the search function here and redirect to the other page where you display results.
}
As for suggesting names, you can use the Google Places Autocomplete API for that: https://developers.google.com/places/web-service/autocomplete. Just call the API in the oninput event handler for #search.
Hope this helps!

How can I join together values in submit text box into a url API call?

I'm working on a project where you ask the National Parks API for info of parks based on the state abbreviation you enter, as in OR(Oregon) or WA (Washington), etc. I understand how to write it for one value, using template literals, but if I search for more than one state at a time, that when writing the code gets tricky. Im looking to get it to send a call to the api like this:
https://developer.nps.gov/api/v1/parks?stateCode=or%2Cwa
I would be putting "or,wa" into my search box
(Documentation for National Parks API endpoint I'm using:
https://www.nps.gov/subjects/developer/api-documentation.htm#/parks/getPark)
JS:
'use strict'
$(watchForm());
function watchForm(){
$('form').submit(event => {
event.preventDefault();
getParkInfo();
})
}
function getParkInfo(){
var searchBox = $('.inputBox').val();
var numResults = $('.numPerPage').val();
const url = *** How do I write this???***
fetch(url)
.then(response => response.json())
.then(response => {
console.log(response)
displayResults(response);
})
}
function displayResults(response){
$('#results-list').empty();
for(let i = 0; i < response.data.length; i++){
$('#results-list').append(
`<li>
<h3>${response.data[i].fullName}</h3>
<p>${response.data[i].description}</p>
<p>${response.data[i].addresses[i]}</p>
<a href="${response.data[i].directionsUrl}"<p>Address</p></a>
</li>`
)
}
$('#results').removeClass('hidden');
}
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Search Your Favorite National Parks</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<h1>NPS Search Up</h1>
<form>
<input class="inputBox" type="text" required> Search for Park
<br><br>
<input class="numPerPage" type="text" value="10" required> Results per page
<br><br>
<input class="submitBox" type="submit">
</form>
<section id="results" class="hidden">
<h2>Search Results</h2>
<ul id="results-list">
</ul>
</section>
</div>
<script
src="https://code.jquery.com/jquery-3.4.1.js"
integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
crossorigin="anonymous"></script>
<script src="script.js" async defer></script>
</body>
</html>
Create a new URL instance with your base url.
var url = new URL("https://developer.nps.gov/api/v1/parks");
and then add your query parameters to this URL instance like this
url.searchParams.append('stateCode', searchBox)
url.searchParams.append('limit', numResults);
var joinedSearchEntry = searchBox.split(',').join('%2C')
var url = `https://developer.nps.gov/api/v1/parks?stateCode=${joinedSearchEntry}`
or save a line
var url = `https://developer.nps.gov/api/v1/parks?stateCode=${searchBox.split(',').join('%2C')}`
Let me know if I'm missing something but this should be fine.

How can I join together values in input text box into a url API call?

I'm working on a project where you ask the National Parks API for info of parks based on the state abbreviation you enter, as in OR(Oregon) or WA (Washington), etc. I understand how to write it for one value, using template literals, but if I search for more than one state at a time, that when writing the code gets tricky. Im looking to get it to send a call to the api like this:
https://developer.nps.gov/api/v1/parks?stateCode=or%2Cwa
I would be putting "or,wa" into my search box
(Documentation for National Parks API endpoint I'm using:
https://www.nps.gov/subjects/developer/api-documentation.htm#/parks/getPark)
JS:
'use strict'
$(watchForm());
function watchForm(){
$('form').submit(event => {
event.preventDefault();
getParkInfo();
})
}
function getParkInfo(){
var searchBox = $('.inputBox').val();
var numResults = $('.numPerPage').val();
const url = *** How do I write this???***
fetch(url)
.then(response => response.json())
.then(response => {
console.log(response)
displayResults(response);
})
}
function displayResults(response){
$('#results-list').empty();
for(let i = 0; i < response.data.length; i++){
$('#results-list').append(
`<li>
<h3>${response.data[i].fullName}</h3>
<p>${response.data[i].description}</p>
<p>${response.data[i].addresses[i]}</p>
<a href="${response.data[i].directionsUrl}"<p>Address</p></a>
</li>`
)
}
$('#results').removeClass('hidden');
}
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Search Your Favorite National Parks</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<h1>NPS Search Up</h1>
<form>
<input class="inputBox" type="text" required> Search for Park
<br><br>
<input class="numPerPage" type="text" value="10" required> Results per page
<br><br>
<input class="submitBox" type="submit">
</form>
<section id="results" class="hidden">
<h2>Search Results</h2>
<ul id="results-list">
</ul>
</section>
</div>
<script
src="https://code.jquery.com/jquery-3.4.1.js"
integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
crossorigin="anonymous"></script>
<script src="script.js" async defer></script>
</body>
</html>
You can split the value by ",", then trim and join back together with "%2C":
document.getElementById("b").onclick = () => {
let sCodes = document.getElementById("p").value
console.log(sCodes.split(",").map(code => code.trim()).join("%2C"))
}
<input id="p" />
<button id="b">Create State Code Val</button>

ng-click works kind of

I am learning angular js right now and have hit another rut. I am trying to make my buttons change the movie ID. I know it is recognizing the click because I had it change some words in the HTML file to test it. I think it isn't talking to my JS file.
I found this during my search http://jsfiddle.net/7Sg6a/. The docs just have an expression inside the parenthesis and this example has parameters. I tried both and a few other but neither worked.
Here is my latest failed attempt. If I could get a nudge in the right direction I would be very grateful.
<!DOCTYPE HTML>
<html lang = "en" ng-app="movies"><!-- lets page use controllers/movies.js-->
<head>
<title>Watch a movie!</title>
<meta charset = "UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta name="description" content="">
<meta name="keywords" content="">
<link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://www.mysite.com/rss/rss2.xml" />
<link href="css/bootstrap.css" rel="stylesheet" type="text/css">
<link href="css/style.css" rel="stylesheet" type="text/css">
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.0/css/bootstrap-combined.min.css" rel="stylesheet">
<!-- <link href="css/bootstrap-responsive.min.css" rel="stylesheet" type="text/css"> -->
<!-- Preloading scripts? -->
<script src="js/angular.min.js"></script>
<script src="http://code.angularjs.org/1.2.0rc1/angular-route.min.js"></script>
<!--<script src="js/angular-resource.min.js" type="text/javascript"></script>-->
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<!-- <script src="js/bootstrap.js"></script> -->
<script src="controllers/movies.js"></script>
</head>
<body>
<div id="wrapper">
<header>
<div id="logo">
<img src="images/logo.png" alt="Cinema Plus - Movies plus a whole lot more." class="img-responsive">
</div>
</header>
<nav>
<div class='row-fluid'>
<div class="span2"></div>
<button ng-click="nowShowing()" type="button" class="btn btn-primary btn-lg span4 "><h3>NOW PLAYING</h3></button>
<button ng-click="comingSoon()" type="button" class="btn btn-default btn-lg span4 "><h3>COMING FRIDAY</h3></button>
<div class="span2"></div>
</div>
</nav>
<div id='content' class='row-fluid'>
<div class='span8 info'>
<h2 ng-controller = "movieController">{{movies.title}}</h2>
<h2 ng-controller = "movieController">RATED: {{movies.mpaa_rating}}</h2>
<h2 ng-controller = "movieController">{{movies.runtime}} Minutes</h2>
<p ng-controller = "movieController">DESCRIPTION: {{movies.synopsis}}</p>
</div>
<div class='span4 poster'>
<img ng-controller = "movieController" src={{movies.posters.original}} alt={{movies.title}} class="img-responsive">
</div>
</div>
<div>
Note: This theator only plays one movie at a time. film will be hard coded into the app. Would like to see it fed by RSS orsomething in the future.
</div>
</div> <!-- END WRAPPER -->
</body>
</html>
JS
var movies = angular.module('movies', []);
movies.controller('movieController', function ($scope, $http) {
$http.jsonp('http://api.rottentomatoes.com/api/public/v1.0/movies/771303861.json', {
params: {
apikey: 'wq98h8vn4nfnuc3rt2293vru',
callback: 'JSON_CALLBACK'
}
})
.success(function (data) {
$scope.movies = data;
});
});
movies.click('nowShowing', function ($scope){
alert("asdasd");
});
how long until I actually get this and can stop asking stupid questions?
your .click function doesn't belong. You're using Angular like jQuery, and it's more (awesome) than that. You need to put the nowShowing function and such inside your controller:
var movies = angular.module('movies', []);
movies.controller('movieController', function ($scope, $http) {
$http.jsonp('http://api.rottentomatoes.com/api/public/v1.0/movies/771303861.json', {
params: {
apikey: 'secret',
callback: 'JSON_CALLBACK'
}
})
.success(function (data) {
$scope.movies = data;
});
$scope.nowShowing = function(){
//whatever is in here will execute when a user interacts with an element with the ng-click="" directive
}
});
Also, I would highly recommend you create a service for your http requests to your api. You are creating a tightly coupled app with your current approach.
movies.factory('moviedata',function($http){
return
$http.jsonp('http://api.rottentomatoes.com/api/public/v1.0/movies/771303861.json', {
params: {
apikey: 'secret',
callback: 'JSON_CALLBACK'
}
})
})
then 'inject' it in your controller like so:
movies.controller('movieCtrl',function($scope, moviedata){
//resolve returned promise
moviedata.success(function(data){
$scope.data = data;
});
$scope.nowShowing = function($log){
//whatever is in here will execute when a user interacts with an element with the ng-click="" directive
$log.info("nowShowing method fired");
}
})

Categories