Restcountries API - getting names of currencies dynamically into HTML through Javascript - javascript

I am new to Javascript and I've been learning how to import a country's attributes into an HTML element. Some of you might recognize this code, it's from a tutorial, which is now outdated. I've been searching around for an updated solution, but couldn't find any.
First I have the function to fetch the data:
const getCountryData = function (country) {
fetch(`https://restcountries.com/v3.1/name/${country}`)
.then(response => response.json())
.then(data => renderCountry(data[0]));
};
Then I call that function, supplying a country getCountryData('czechia') to infuse it into an element like this:
const renderCountry = function(data, className = '') {
const html = `
<article class="country ${className}">
<img class="country__img" src="${data.flags.svg}" />
<div class="country__data">
<h3 class="country__name">${data.name.common}</h3>
<h4 class="country__region">${data.region}</h4>
<p class="country__row">${(+data.population / 1000000).toFixed(1)} people</p>
<p class="country__row">${data.fifa}</p>
</div>
</article>
`
countriesContainer.insertAdjacentHTML
('beforeend', html);
countriesContainer.style.opacity = 1;
}
This works fine, but the issue is that at the end of the HTML, where I input {data.fifa} I want to have the name of the country's main currency instead. Unfortunately, the data is structured in a way, that in order to have the currency's name displayed, I first have to call it's short name, as shown below:
"currencies": {
"CZK": {
"name": "Czech koruna",
"symbol": "Kč"
}
},
If I call the {data.currencies} into the string, I'm just gonna get an empty object back. If I call it as {currencies.CZK.name}, it works, but the issue is that if I call Sweden, for example, it won't display anything, because then it'd need to be {currencies.SEK.name}. How do I get around this? How can I can call a currency's name without having to incorporate CZK, SEK, USD, EUR etc. into the variable?
Any help is appreciated.

You can transform that object into an array:
const currencyArray = Object.values(data.currencies)
console.log(currencyArray[0].name)
If the country has many currencies, just change the index from 0 to 1, 2, ...

Related

Displaying Data from Javascript Fetch API - Question

I am new to working with APIs in javascript. I am looking to get input that a user puts into a box on a site (a city name) and fetch the API, to retrieve the temperature in that city. So far I have the following to fetch the API. But I am a bit lost on how to actually get that data and display it. How would I get the 'data'? I'm just not used to using APIs with Javascript and looking to learn more.
js file:
function hi() {
function temperature(input) {
const myKey = "Hidden_for_privacy";
const api = `https://api.openweathermap.org/data/2.5/weather?
q=${input}&lang=en&&appid=${myKey}&units=metric`;
fetch(api)
.then(function(response){
let data = response.json();
console.log(data);
return data;
})
Then I have this. searchUser is just representing the location the user types in:
const search = document.getElementById("searchUser");
const button = document.getElementById("submit");
button.addEventListener("click", () => {
const currentVal = search.value;
Relevant HTML:
<div class="container searchContainer">
<div class="search card card-body">
<h3>Get The Weather For a Location</h3>
<p class="lead">Enter Your Location</p>
<input type="text" id="searchUser" class="form-control"
placeholder="Location">
</div>
<br>
<div id="profile"></div>
</div>
<div class="container text-center mt-2">
<button class="btn btn-primary" id="submit">Submit</button>
</div>
<div id="content">
</div>
I think you have a few syntax errors going on before you can get into displaying data on the screen. I'd suggest concentrating on the JS implementation first to ensure you are successfully fetching data and loading it to the console. For instance, the closures in your JS might be causing problems. The hi function is creating a closure and then you are passing an argument of input into a function inside it but there is no local variables for it to grab.
Maybe try something like this to start and see what it logs:
function getTemperature() {
const myKey = "Hidden_for_privacy";
const api = `https://api.openweathermap.org/data/2.5/weather?
q=${input}&lang=en&&appid=${myKey}&units=metric`;
// .json returns a promise so you need to use .then to get the data from it synchronously
fetch(api)
.then((response) => response.json())
.then(data => console.log(data))
}

Add a javascript result to an image url

So what im trying to do is query a Minecraft server with javascript, and with the response i get back with the api, i want to grab the .playerlist and put the response in this url (https://cravatar.eu/avatar/ {name} /100.png) for each person connected
If someone knows a better way to achieve this, i would very much appreciate your input!
Im also pretty new to javascript, so not fully know what im doing :/
Heres the HTML that i have (i know it may be messy, its also not fully my code)
<div class="card"> <div class="icon"><img src="https://cdn.worldvectorlogo.com/logos/minecraft-1.svg"></div><div class="header">
<div class="image"> <img src="https://res.cloudinary.com/lmn/image/upload/e_sharpen:100/f_auto,fl_lossy,q_auto/v1/gameskinnyc/u/n/t/untitled-a5150.jpg" alt="" /> </div>
<h2>Server Status</h2>
</div>
<div id="rest">Loading...</div>
<img src="https://cravatar.eu/avatar/" $face "/>
</div>
And here is the javascript
//Query api at this address
var url = "https://api.minetools.eu/query/play.aydaacraft.online/25565";
$.getJSON(url, function(r) {
//data is the JSON string
if(r.error){
$('#rest').html('Server Offline.');
return false;
}
var p1 = '';
if(r.Players > 0 ){ p1 = '<br>'+r.Playerlist; }
// Text to display below
$('#rest').html('Total Online: '+r.Players+p1);
// Trying to add playerlist to html url
$('#face').html+p1;
});
Since you've pasted jQuery code, I'll submit my answer in jQuery. However, I do recommend you learn primitive JavaScript and not focus your attention just on jQuery... it's become something of a meme on StackOverflow.
Starting off, you really should be wrapping your code in $(document).ready this'll only run the code when the page has loaded.
$(document).ready(() => {
// The document is ready, let's run some code!
});
Then add your AJAX request as normal inside this bracket.
$(document).ready(() => {
let url = "https://api.minetools.eu/query/play.aydaacraft.online/25565";
$.getJSON(url, response => {
});
});
Okay, whilst writing this, I checked the URL provided by OP and saw that it was timing out so I've grabbed a sample response from the Minetools' documentation.
{
"MaxPlayers": 200,
"Motd": "A Minecraft Server",
"Playerlist": [
"Connor",
"Kamil",
"David"
],
"Players": 3,
"Plugins": [],
"Software": "CraftBukkit on Bukkit 1.8.8-R0.2-SNAPSHOT",
"Version": "1.8.8",
"status": "OK"
}
So in your JSON response, you can see that Playerlist is a array which can contain multiple things in one variable. You can also iterate through an array, which is what we'll be doing to build the image URLs.
We iterate through an array using forEach.
$(document).ready(() => {
let url = "https://api.minetools.eu/query/play.aydaacraft.online/25565";
$.getJSON(url, response => {
response.Playerlist.forEach(playerName => {
console.log(playerName);
});
});
});
//Console:
//Connor
//Kamil
//David
Now that we're iterating through the player list we can start assembling the URLs for these images and adding them to your document's body.
I've cleaned up your HTML, take note of the new div#user-images I've added. This'll be the place where jQuery will add your images from the forEach loop.
<div class="card">
<div class="icon">
<img src="https://cdn.worldvectorlogo.com/logos/minecraft-1.svg">
</div>
<div class="header">
<div class="image">
<img src="https://res.cloudinary.com/lmn/image/upload/e_sharpen:100/f_auto,fl_lossy,q_auto/v1/gameskinnyc/u/n/t/untitled-a5150.jpg" alt="" />
</div>
<h2>Server Status</h2>
</div>
<!-- This div tag will need to hide when there is no error, or say when there is. -->
<div id="rest">Loading...</div>
<!-- The user images will be added inside this div. -->
<div id="user-images"></div>
</div>
Now we have our HTML ready we can start using the jQuery function appendTo to add elements into our div#user-images.
$(document).ready(() => {
let url = "https://api.minetools.eu/query/play.aydaacraft.online/25565";
$.getJSON(url, response => {
response.Playerlist.forEach(playerName => {
$(`<img src="https://cravatar.eu/avatar/${playerName}" />`).appendTo("#user-images");
});
});
});
Your div#user-images should start filling up with the images of players from the Playerlist array.
I noticed you added a simple way of showing whether or not there's an error with the API. We can interact with div#rest to show/hide or change text depending on the success of the response.
$(document).ready(() => {
let url = "https://api.minetools.eu/query/play.aydaacraft.online/25565";
$.getJSON(url, response => {
if(response.error){
$("#rest").html("The server is offline!");
}else{
//There is no error, hide the div#rest
$("#rest").hide();
response.Playerlist.forEach(playerName => {
$(`<img src="https://cravatar.eu/avatar/${playerName}" />`).appendTo("#user-images");
});
}
});
});
And that's it really. I hope this gives you some understanding of arrays, and iterating through them, as well as some DOM functions from jQuery.

How to add counter in angular 6?

I have a function which grabs comments from the server, I would like to display total number of comments available in a server.
Here is the function in .ts file:
this.activeRouter.params.subscribe(params => {
// tslint:disable-next-line:prefer-const
let id = params['id'];
this.userService.getComments(id)
.pipe(
map(data => data.sort((a, b) => new Date(b.localTime).getTime() - new Date(a.localTime).getTime()))
)
.subscribe(data => this.comments = data);
});
Here is the get function in service
getComments (id: number) {
return this.http.get<Comment[]>(this.commentsUrl);
}
Here is the html for displaying comments
<div class="comments-description" *ngFor="let comment of comments">
<span class="comments_count">(353)</span>
<div class="comments-photo">
<img src="https://randomuser.me/api/portraits/men/84.jpg" alt="">
</div>
<div class="comments_wrapper">
<div class="comments_details">
<h1>{{comment.author}}</h1>
<span class="days">1d</span>
</div>
<div class="comments_text">
<p>{{comment.description}} </p>
</div>
</div>
</div>
why not simply use the length
<span class="comments_count">{{comments.length}}</span>
If you get all the comments in the response then you can use comments.length
<span class="comments_count">{{comments.length}}</span>
But the best practice is to get it from the API side. Add one more field in your API response for comment count.
Solution:
While getting comments data from server , You have to return total number of comments along with the new data.
Once you call service you can add data in one array.
and set total count in one variable.
Note:
You have to read count from sever and return result in same API or service
Update your API and get comments count using API and show your comment count.
Such counter must be on the server side.
For example, post has 10000 comments.
1 request will not fetch them all, only a portion (page).
And it's not good to get them all only to find out a count.
So the response should contain a 'count' field.

Get list of videos youtube api

so I'm trying to create a web app that when you insert a search it gets the data from the youtube API using JSON and renders a list with the videos matching your search. When it retrieves it's getting some Letter and numerical answer but not a list of the videos. Any help in the right direction will be appreciated. This is the HTML for it:
<div class="search-box-container">
<form action="#" class="js-search-form search-box">
<label for="query"></label>
<input type="text" class="js-query search-form" placeholder="Search me">
<button type="submit" class="button">Search</button>
</form>
</div>
<h2>Results</h2>
<div class="js-search-results">
</div>
And this is the JS/Jquery for it:
const YOUTUBE_SEARCH_URL =
'https://www.googleapis.com/youtube/v3/search';
`const key = 'key'//(hidden for privacy concerns);`
function getDataFromApi(searchTerm, callback) {
const query = {
part: 'snippet',
key: key,
q: `${searchTerm} in:name`,
}
$.getJSON(YOUTUBE_SEARCH_URL, query, callback);
}
function renderResult(result) {
return `
<div>
<h2>
<a class="js-result-name" href="http//www.youtube.com/watch?v=${
result.id.videoId}" target="_blank">${result.id.videoId}</a></h2>
</div>
`;
}
function displayYoutubeSearchData(data) {
console.log(data);
const results = data.items.map((item, index) => renderResult(item));
$('.js-search-results').html(results);
}
function watchSubmit() {
$('.js-search-form').submit(event => {
event.preventDefault();
const queryTarget = $(event.currentTarget).find('.js-query');
const query = queryTarget.val();
queryTarget.val("");
getDataFromApi(query,displayYoutubeSearchData );
});
}
$(watchSubmit);
This is the answer that gets rendered
You were almost there: it is just a typo.
Look at the href attribute inside the template literal returned by the renderResult() method.
href="http//www.youtube.com/watch?v=${result.id.videoId}"
Mind the wrongly formed scheme (http// vs https://).
A little bit of a context:
The YouTube API returns a collection of search results (i.e. an array of objects, data.items in your code) that match the query parameters specified in the API request.
Each item contains an id object with a videoId property. That is the "alphanumeric answer" you refer to in your question. After mapping data.items into an array of result HTML templates, you are reading that video id with ${result.id.videoId}. Then you concatenate the YouTube watch URL with the video id.
You should check the JSON structure of the search result in the YouTube Data API docs. Besides id.videoId, it contains more useful information. For example, you could prefer to show to the users the title of the video using ${result.snippet.title} instead of the alphanumeric videoId.

Loading specific div based on the results of multiple dropdowns

EDIT: Would the approach be much easier if the Javascript listed was removed completely, and the dropdown menus restyled as <div>'s within <li>'s, and the final div was generated by a Javascript onclick event? e.g.
<a id="click_link">click me</a>
$("#click_link").click(function(){
$('#div').load('http://www.link.com/');
});
Either way, the problem at hand...
My decision to use an elegant-looking javascript solution is highlighting my massive inexperience when it comes to javascript! The problem is, on the face of it, simple...
Once an option has been chosen on each of the dropdown menus, I need a final div to load so that a specific button can be shown (a link to buy the item with the specified options, e.g. choosing Necklace D, with Stone Option B, and Delivery Option A = loading div with 'Buy' Button #17)
The dropdowns are divs that are filled and styled through the Javascript (as opposed to using the simpler <form> and <input> method), giving the flexibility to add two lines of differently styled text for each option etc. - This is where I step into the realm of the unknown and my inexperience shines through.
The isolated section is viewable in its entirity here
Ok, to the code.
Here's the Javascript:
function createByJson() {
var pearlData = [
{description:'Choose your pearl...', value:'Pearls', text:'Pearls'},
{description:'Beautiful black stone', value:'Black Pearl', text:'Black Pearl'},
{description:'Classic white stone', value:'White Pearl', text:'White Pearl'}
];
$("#DropItPearls").msDropDown({byJson:{data:pearlData, name:'pearls', width: 200}}).data("dd");
var blodeuweddData = [
{description:'Choose your item...', value:'Blodeuwedd', text:'the Blodeuwedd Collection'},
{description:'A striking statement', value:'BlodeuweddCelticStatement', text:'Celtic Statement Piece'},
{description:'Gold laced flower and pearl', value:'BlodeuweddBracelet', text:'Bracelet'},
];
$("#DropItBlodeuwedd").msDropDown({byJson:{data:blodeuweddData, name:'blodeuwedd', width: 250}})
.msDropDown({on:{change:function(data, ui) {
var val = data.value;
if(val!="")
window.location = val;
}}}).data("dd");
var deliveryData = [
{description:'Choose your method...', value:'Delivery', text:'Delivery Options'},
{description:'4-6 weeks delivery', value:'Four Weeks', text:'Made To Order'},
{description:'(unavailable on this item)', value:'Rush', text:'Express Delivery', disabled:true}
];
$("#DropItDelivery").msDropDown({byJson:{data:deliveryData, name:'delivery', width: 200, selectedIndex: 1}}).data("dd");
paymentData = [
{ description:'How would you like to pay?', value:'Payment', text:'Payment Method'},
{image:'images/msdropdown/icons/Visa-56.png', description:'Secure online payment', value:'Visa', text:'Visa'},
{image:'images/msdropdown/icons/Paypal-56.png', description:'Secure online payment', value:'Paypal', text:'Paypal'},
{image:'images/msdropdown/icons/EmailPay-56.png', description:'Order by email', value:'Email Payment', text:'Send Your Details'},
{image:'images/msdropdown/icons/Mastercard-56.png', description:'(coming soon)', value:'Mastercard', text:'Mastercard', disabled:true},
{image:'images/msdropdown/icons/Collect-56.png', description:'(coming soon)', value:'Collection', text:'Order and Collect', disabled:true},
{image:'images/msdropdown/icons/Email-56.png', description:'email Menna', value:'Other Method', text:'Alternatives'}
];
$("#DropItPayments").msDropDown({byJson:{data:paymentData, name:'payments', width: 250}}).data("dd");
}
$(document).ready(function(e) {
//no use
try {
var pages = $("#pages").msDropdown({on:{change:function(data, ui) {
var val = data.value;
if(val!="")
window.location = val;
}}}).data("dd");
var pagename = document.location.pathname.toString();
pagename = pagename.split("/");
pages.setIndexByValue(pagename[pagename.length-1]);
$("#ver").html(msBeautify.version.msDropdown);
} catch(e) {
//console.log(e);
}
$("#ver").html(msBeautify.version.msDropdown);
//convert
$("select").msDropdown();
createByJson();
$("#tech").data("dd");
});
function showValue(h) {
console.log(h.name, h.value);
}
$("#tech").change(function() {
console.log("by jquery: ", this.value);
})
//
And the html:
<div id="dropOptions">
<div id="dropOptionsTitle"><p>Item</p></div>
<div id="DropItBlodeuwedd"></div>
</div>
<div id="dropOptions">
<div id="dropOptionsTitle"><p>Precious Stones</p></div>
<div id="DropItPearls"></div>
</div>
<div id="dropOptions">
<div id="dropOptionsTitle"><p>Payment</p></div>
<div id="DropItPayments"></div>
</div>
<div id="dropOptions">
<div id="dropOptionsTitle"><p>Delivery</p></div>
<div id="DropItDelivery"></div>
</div>
<div id="dropOptions">
<div id="dropOptionsTitle"><p>Buy Now!</p></div>
<div id="DropItBuy"></div>
</div>
Again, working version viewable here
Many thanks in advance!
What I think you want is for your Buy button to dynamically read what the dropdowns currently say and build a link for redirection based on that, rather than trying to update the Buy button every time a dropdown changes.
From your code I can't see what the form of the final URL is supposed to be. For example, to get the current value of the delivery option, you can check $('#DropItDelivery :selected').text() which will be something like "Made To Order".
Your Buy Now! could be a button with a click event that reads these values and constructs the URL with basic string concatenation, e.g.:
window.location = "buynow.html?delivery=" + $('#DropItDelivery :selected').text() +
"&payment=" + $('#DropItPayments :selected').text()
// etc.
Of course you'd have to handle these options on the server.
In case you want to redirect to the payment page of the processor, you can just branch based on the payment method and give them the URL you want based on that.
var pm = $('#DropItPayments :selected').text();
if (pm == "Visa")
{
// Visa payment URL construction
}
else if (pm == "Send Your Details")
{
// Send your details URL construction
}
// etc.

Categories

Resources