Hello friends, today in this blog, we will learn how to create a currency converter using Javascript and API. Our previous blog showed how to create a random color generator with a 3D Effect. You can check my other javascript projects after reading this blog.
In today's globalized world, it's not uncommon to need to convert currency regularly. Whether you're traveling abroad, making international transactions, or simply want to keep track of the value of your investments in different currencies, having access to an accurate and easy-to-use currency converter is essential.
In this blog post, we'll show you how to create a currency converter using JavaScript and an API. JavaScript is a powerful and widely used programming language that can be used to create dynamic and interactive web applications, while an API (Application Programming Interface) allows us to connect to external services and retrieve data in a structured way. By combining these two tools, we can create a simple yet effective currency converter that can be used by anyone with an internet connection.
Whether you're a beginner or an experienced developer, this tutorial is designed to be accessible and easy to follow. We'll walk you through each step of the process, from setting up the project to fetching data from the API and displaying the results. By the end of this tutorial, you'll have a fully functional currency converter that you can use and customize to suit your needs. So, let's get started!
In this project, there is a currency converter as you can see in the image above. You just need to enter the amount and select the currency you want to convert. For example, let's assume I want to convert Indian Rupees. So I will click on the county Flag and a pop-up modal will be opened and I will be able to select a currency, there is a search option, and I can search currencies. I no result is found then this message will be shown:-
After selecting the currency, the results of all currencies will be shown and you can search which currency result you want.
You may like these:
- Awesome Neumorphism Social Icon Button with Tooltip using HTML, CSS, and Javascript
- Share Modal Dark UI Design using HTML, CSS, and Javascript
- Glassmorphism Login Form using HTML and CSS
- Social Media Icon Hover Effect Using HTML and CSS
Note:
You can check live demo and download code files from here.
Code of HTML, CSS, and JavaScript Files
Here's the good news: you don't have to write all the code of this project from scratch! I have created a GitHub repository that contains all the HTML, CSS, and JavaScript code needed to build the app. You can check it out and use it as a starting point for your own project.
HTML CODE
Just paste this code into HTML File which you have created.
<!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>Currency Converter - InCoder</title>
<link rel="stylesheet" href="main.css" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
/>
</head>
<body>
<div id="loading">
<img src="loader.gif" alt="Loading..." />
</div>
<div class="mainContainer">
<div class="title">Currency Converter</div>
<div class="fromCurrencyInput">
<span id="flag">
<img
src="https://static.vecteezy.com/system/resources/previews/011/571/519/original/circle-flag-of-india-free-png.png"
alt="Country Flag"
/>
<p>INR</p>
<input type="hidden" id="selectedCurrency" value="INR" />
</span>
<input
type="number"
placeholder="Enter Amount"
id="conversionAmount"
value="100"
onkeydown="getConversion()"
/>
</div>
<div class="convertedCurrencyBox">
<span></span>
<div class="convertedList">
<div class="searchBox" style="margin-top: 1rem">
<input
type="text"
placeholder="Search here..."
class="searchInput"
id="convertedFilter"
/>
<i class="fa-solid fa-magnifying-glass"></i>
</div>
<div class="loadingScreen">
<i class="fa-solid fa-spinner fa-spin"></i>
<p>Loading Data...</p>
</div>
<div class="notFound">
<i class="fa-solid fa-face-frown"></i>
<h2>No Result Found</h2>
<p>
There are no currency that match your current filters. Try removing
some of them to get better results.
</p>
</div>
<div class="convertedListTag"></div>
</div>
</div>
</div>
<div class="countriesModal">
<button class="closeModal"><i class="fa-solid fa-xmark"></i></button>
<div class="modalBox">
<div class="searchBox">
<input
type="text"
placeholder="Search Currency..."
class="searchInput"
id="searchInp"
/>
<i class="fa-solid fa-magnifying-glass"></i>
</div>
<div class="notFound">
<i class="fa-solid fa-face-frown"></i>
<h2>No Result Found</h2>
<p>
There are no currency that match your current filters. Try removing
some of them to get better results.
</p>
</div>
<div class="countriesBox"></div>
</div>
</div>
<script src="countriesData.js"></script>
<script src="script.js"></script>
</body>
</html>
CSS CODE
@import url("https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap");
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Poppins", sans-serif;
}
body {
display: flex;
height: 100vh;
align-items: center;
justify-content: center;
background: rgb(185 26 88 / 45%);
}
::-webkit-scrollbar {
width: 5px;
}
::-webkit-scrollbar-track {
background: rgb(185 26 88 / 18%);
}
::-webkit-scrollbar-thumb {
border-radius: 5px;
background: rgb(185 26 88 / 45%);
}
::-webkit-scrollbar-thumb:hover {
background: rgb(185 26 88 / 70%);
}
.mainContainer {
width: 18rem;
height: 30rem;
padding: 1rem;
overflow: hidden;
position: relative;
border-radius: 1.9rem;
background: rgb(185 26 88);
}
.mainContainer .title {
color: #ffffff;
font-size: 1.6rem;
margin-top: 0.5rem;
text-align: center;
}
.fromCurrencyInput {
display: flex;
margin-top: 1rem;
padding-top: 0.2rem;
border-radius: 0.5rem;
padding-bottom: 0.2rem;
border: 2px dashed #ffffffc4;
justify-content: space-between;
}
.fromCurrencyInput input {
border: 0;
width: 9.5rem;
font-size: 1rem;
color: #ffffff;
text-align: right;
padding-left: 0.5rem;
padding-right: 0.5rem;
background: transparent;
}
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
margin: 0;
}
.fromCurrencyInput input:focus {
border: 0;
outline: none;
}
.fromCurrencyInput input::placeholder {
color: #ffffff;
font-size: 1rem;
}
#flag {
display: flex;
height: 2.5rem;
cursor: pointer;
color: #ffffff;
margin-left: 0.4rem;
align-items: center;
border-radius: 0.5rem;
max-width: fit-content;
justify-content: center;
transition: background 0.2s ease-in-out;
}
#flag:hover {
background: #ffffff29;
}
#flag img {
height: 1.8rem;
margin-left: 0.5rem;
margin-right: 0.5rem;
}
#flag p {
margin-right: 0.5rem;
}
.countriesModal {
top: 0;
left: 0;
opacity: 0;
width: 100vw;
display: flex;
height: 100vh;
position: fixed;
align-items: center;
pointer-events: none;
justify-content: center;
backdrop-filter: blur(2px);
transition: opacity .1s ease;
background-color: #ffffff47;
}
.countriesModal.active {
opacity: 1;
pointer-events: all;
}
.modalBox {
margin: 2rem;
width: 35rem;
height: 25rem;
padding: 2rem;
border-radius: 2.5rem;
background: #ffffff;
transform: translateY(-1.5rem);
transition: transform .38s ease-in-out;
}
.countriesModal.active .modalBox {
transform: translateY(0rem);
}
.searchBox {
border: 0;
width: 95%;
display: flex;
height: 2.5rem;
overflow: hidden;
margin-left: auto;
margin-right: auto;
border-radius: 2rem;
align-items: center;
justify-content: space-between;
background: rgb(185 26 88 / 20%);
}
.searchBox input {
border: 0;
width: 90%;
height: 100%;
font-size: 1rem;
padding-left: 1rem;
color: rgb(185 26 88);
background: transparent;
}
.searchBox input:focus {
border: 0;
outline: none;
}
.searchBox input::placeholder {
color: rgb(185 26 88);
}
.searchBox i {
font-size: 1.1rem;
color: rgb(185 26 88);
margin-right: 0.8rem;
}
.countriesBox {
width: 100%;
height: 17rem;
display: grid;
margin-top: 2rem;
overflow-y: scroll;
place-items: center;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
}
.countriesBox .countryTag {
display: flex;
margin: 0.5rem;
display: flex;
height: 2.8rem;
padding: 0 1rem;
cursor: pointer;
font-weight: 600;
user-select: none;
width: fit-content;
border-radius: 5rem;
align-items: center;
color: rgb(185 26 88 / 70%);
justify-content: space-between;
transition: all 0.1s ease-in-out;
border: 2px solid rgb(185 26 88 / 70%);
}
.countriesBox .countryTag:hover,
.countriesBox .countryTag.selected {
background: rgb(185 26 88 / 25%);
border: 2px solid rgb(255 197 203);
}
.countriesBox .countryTag.selected {
outline-offset: 2px;
outline: 2px solid rgb(185 26 88 / 70%);
}
.countriesBox .countryTag img {
height: 1.8rem;
margin-right: 0.5rem;
}
.notFound {
width: 100%;
height: 100%;
display: none;
margin-top: 2rem;
text-align: center;
}
.notFound i {
font-size: 5rem;
margin-bottom: 0.5rem;
color: rgb(185 26 88 / 70%);
}
.notFound h2 {
font-size: clamp(1.5rem, 8vw, 2.5rem);
color: rgb(185 26 88);
}
.notFound p {
font-size: 0.9rem;
}
.convertedCurrencyBox .notFound i{
font-size: 4rem;
}
.convertedCurrencyBox .notFound h2 {
font-size: 1.9rem;
color: rgb(185 26 88);
}
.convertedCurrencyBox .notFound p {
font-size: 0.8rem;
padding-left: 1rem;
padding-right: 1rem;
}
.closeModal{
border: 0;
top: 1.5rem;
right: 1.5rem;
width: 2.5rem;
height: 2.5rem;
cursor: pointer;
position: fixed;
color: #ffffff;
font-size: 1.2rem;
border-radius: .5rem;
background: rgb(185 26 88 / 55%);
}
.convertedCurrencyBox{
left: 0;
top: 10rem;
width: 100%;
height: 100%;
overflow-y: scroll;
position: absolute;
background: #ffffff;
border-top-left-radius: 1.5rem;
transition: top .3s ease-in-out;
border-top-right-radius: 1.5rem;
}
.convertedCurrencyBox.active{
top: 0;
}
.convertedCurrencyBox > span{
width: 4rem;
cursor: grab;
height: .4rem;
display: block;
margin-left: auto;
margin-top: 0.8rem;
margin-right: auto;
border-radius: .5rem;
background: #00000038;
}
.convertedListTag{
margin-top: .5rem;
}
.convertedTag{
display: flex;
cursor: pointer;
padding-top: .5rem;
position: relative;
align-items: center;
padding-right: 1rem;
padding-bottom: .8rem;
justify-content: space-between;
border-bottom: 1px solid #0000001f;
}
.convertedTag:first-child{
margin-top: 1rem;
}
.convertedTag:last-child{
margin-bottom: 10rem;
}
.convertedCurrencyBox.active .convertedTag:last-child{
margin-bottom: 0rem;
}
.convertedTag #flag{
cursor: auto;
margin-left: 1rem;
}
.convertedTag #flag img{
height: 2rem;
}
.convertedTag .convertedAmount{
font-weight: 500;
font-size: 1.5rem;
}
.convertedTag #flag p{
color: #000;
margin-left: .2rem;
}
.convertedTag .conversionData{
bottom: 0;
right: 1rem;
font-size: .7rem;
position: absolute;
}
.loadingScreen{
width: 100%;
height: 11rem;
display: none;
margin-top: 1rem;
align-items: center;
flex-direction: column;
justify-content: center;
}
.loadingScreen i{
font-size: 3rem;
margin-bottom: .5rem;
}
#loading{
top: 0;
left: 0;
z-index: 2;
width: 100vw;
display: flex;
height: 100vh;
position: fixed;
align-items: center;
justify-content: center;
background: rgb(255 151 163);
}
JavaScript CODE (countriesData.js)
// currency: Country
let countryList = {
"AED" : "AE",
"AFN" : "AF",
"XCD" : "AG",
"ALL" : "AL",
"AMD" : "AM",
"AOA" : "AO",
"AQD" : "AQ",
"ARS" : "AR",
"AUD" : "AU",
"AZN" : "AZ",
"BAM" : "BA",
"BBD" : "BB",
"BDT" : "BD",
"XOF" : "BE",
"BGN" : "BG",
"BHD" : "BH",
"BIF" : "BI",
"BMD" : "BM",
"BND" : "BN",
"BOB" : "BO",
"BRL" : "BR",
"BSD" : "BS",
"BWP" : "BW",
"BZD" : "BZ",
"CAD" : "CA",
"CDF" : "CD",
"XAF" : "CF",
"CHF" : "CH",
"CLP" : "CL",
"CNY" : "CN",
"COP" : "CO",
"CRC" : "CR",
"CUP" : "CU",
"CVE" : "CV",
"CYP" : "CY",
"CZK" : "CZ",
"DJF" : "DJ",
"DKK" : "DK",
"DOP" : "DO",
"DZD" : "DZ",
"ECS" : "EC",
"EEK" : "EE",
"EGP" : "EG",
"ETB" : "ET",
"EUR" : "FR",
"FJD" : "FJ",
"FKP" : "FK",
"GBP" : "GB",
"GEL" : "GE",
"GGP" : "GG",
"GHS" : "GH",
"GIP" : "GI",
"GMD" : "GM",
"GNF" : "GN",
"GTQ" : "GT",
"GYD" : "GY",
"HKD" : "HK",
"HNL" : "HN",
"HRK" : "HR",
"HTG" : "HT",
"HUF" : "HU",
"IDR" : "ID",
"ILS" : "IL",
"INR" : "IN",
"IQD" : "IQ",
"IRR" : "IR",
"ISK" : "IS",
"JMD" : "JM",
"JOD" : "JO",
"JPY" : "JP",
"KES" : "KE",
"KGS" : "KG",
"KHR" : "KH",
"KMF" : "KM",
"KPW" : "KP",
"KRW" : "KR",
"KWD" : "KW",
"KYD" : "KY",
"KZT" : "KZ",
"LAK" : "LA",
"LBP" : "LB",
"LKR" : "LK",
"LRD" : "LR",
"LSL" : "LS",
"LTL" : "LT",
"LVL" : "LV",
"LYD" : "LY",
"MAD" : "MA",
"MDL" : "MD",
"MGA" : "MG",
"MKD" : "MK",
"MMK" : "MM",
"MNT" : "MN",
"MOP" : "MO",
"MUR" : "MU",
"MVR" : "MV",
"MWK" : "MW",
"MXN" : "MX",
"MYR" : "MY",
"MZN" : "MZ",
"NAD" : "NA",
"XPF" : "NC",
"NGN" : "NG",
"NIO" : "NI",
"NPR" : "NP",
"NZD" : "NZ",
"OMR" : "OM",
"PAB" : "PA",
"PEN" : "PE",
"PGK" : "PG",
"PHP" : "PH",
"PKR" : "PK",
"PLN" : "PL",
"PYG" : "PY",
"QAR" : "QA",
"RON" : "RO",
"RSD" : "RS",
"RUB" : "RU",
"RWF" : "RW",
"SAR" : "SA",
"SBD" : "SB",
"SCR" : "SC",
"SDG" : "SD",
"SEK" : "SE",
"SGD" : "SG",
"SKK" : "SK",
"SLL" : "SL",
"SOS" : "SO",
"SRD" : "SR",
"STD" : "ST",
"SVC" : "SV",
"SYP" : "SY",
"SZL" : "SZ",
"THB" : "TH",
"TJS" : "TJ",
"TMT" : "TM",
"TND" : "TN",
"TOP" : "TO",
"TRY" : "TR",
"TTD" : "TT",
"TWD" : "TW",
"TZS" : "TZ",
"UAH" : "UA",
"UGX" : "UG",
"USD" : "US",
"UYU" : "UY",
"UZS" : "UZ",
"VEF" : "VE",
"VND" : "VN",
"VUV" : "VU",
"YER" : "YE",
"ZAR" : "ZA",
"ZMK" : "ZM",
"ZWD" : "ZW"
}
JavaScript CODE (script.js)
const searchBox = document.querySelector('.searchBox')
convertedFilter = document.querySelector('#convertedFilter')
countriesBox = document.querySelector('.countriesBox')
notFound = document.querySelector('.notFound')
clearSearch = document.querySelector('.clearSearch')
closeModal = document.querySelector('.closeModal')
countryFlag = document.querySelector('#flag')
countriesModal = document.querySelector('.countriesModal')
selectedCurrency = document.querySelector('#selectedCurrency')
convertedListTag = document.querySelector('.convertedListTag')
conversionAmount = document.querySelector('#conversionAmount')
loadingScreen = document.querySelector('.loadingScreen')
convertedCurrencyBox = document.querySelector('.convertedCurrencyBox')
searchInp = document.querySelector('#searchInp')
APIKey = '60ec6c2270a80ca6c3a356d4'
fetchedData = []
const getDataFromAPI = () => {
let URL = `https://v6.exchangerate-api.com/v6/${APIKey}/latest/${selectedCurrency.value}`
fetch(URL).then(response => response.json()).then((result) => {
fetchedData.push(result)
})
}
const getConversion = () => {
convertedListTag.innerHTML = ""
convertedListTag.style.display = 'none'
loadingScreen.style.display = 'flex'
let conversionVal = conversionAmount.value
setTimeout(() => {
let rateData = fetchedData
for (currencyCode in countryList) {
convertedListTag.innerHTML += `<div class="convertedTag">
<span id="flag">
<img src="https://flagcdn.com/40x30/${countryList[currencyCode].toLocaleLowerCase()}.png" alt="">
<p data-code="${currencyCode}">${currencyCode}</p>
</span>
<div class="convertedAmount">
${((rateData[0].conversion_rates[selectedCurrency.value] / rateData[0].conversion_rates[currencyCode]) * conversionVal).toFixed(2)}
</div>
<div class="conversionData">1 ${selectedCurrency.value} = ${rateData[0].conversion_rates[currencyCode]} ${currencyCode}</div>
</div>`
}
loadingScreen.style.display = 'none'
convertedListTag.style.display = 'block'
}, 2000)
}
getDataFromAPI()
getConversion()
new Promise((resolve, reject) => {
for (currencyCode in countryList) {
countriesBox.innerHTML += `<div class="countryTag">
<img src="https://flagcdn.com/40x30/${countryList[currencyCode].toLocaleLowerCase()}.png" alt="">
<p data-code="${currencyCode}">${currencyCode}</p>
</div>`
}
resolve(true)
}).then(() => {
console.log("done")
})
conversionAmount.addEventListener("keyup", () => {
let conversionVal = conversionAmount.value
if (conversionVal == "" || conversionVal == "0") {
conversionAmount.value = '1'
}
})
const filterData = () => {
notFound.style.display = 'none'
countriesBox.style.display = 'grid'
let searchedVal = searchInp.value.toLowerCase()
searchedCurrency = []
searchedCurrency = Object.keys(countryList).filter(data => {
return data.toLocaleLowerCase().startsWith(searchedVal)
}).map(data => {
countriesBox.innerHTML = ''
return `<div class="countryTag">
<img src="https://flagcdn.com/40x30/${countryList[data].toLocaleLowerCase()}.png" alt="">
<p data-code="${data}">${data}</p>
</div>`
}).join('')
if (searchedCurrency != "") {
countriesBox.innerHTML += searchedCurrency
} else {
countriesBox.innerHTML = ''
countriesBox.style.display = 'none'
notFound.style.display = 'block'
}
}
filterData()
const filterConvertedData = () => {
notFound.style.display = 'none'
convertedListTag.style.display = 'block'
let searchedVal = convertedFilter.value.toLowerCase()
searchedCurrency = []
searchedCurrency = Object.keys(countryList).filter(data => {
return data.toLocaleLowerCase().startsWith(searchedVal);
}).map(data => {
convertedListTag.innerHTML = ''
let conversionVal = conversionAmount.value
let convertedRates = fetchedData[0].conversion_rates
return `<div class="convertedTag">
<span id="flag">
<img src="https://flagcdn.com/40x30/${countryList[data].toLocaleLowerCase()}.png" alt="">
<p data-code="${data}">${data}</p>
</span>
<div class="convertedAmount">
${(convertedRates[data] * conversionVal).toFixed(2)}
</div>
<div class="conversionData">1 ${selectedCurrency.value} = ${convertedRates[data]} ${data}</div>
</div>`;
}).join('')
if (searchedCurrency != "") {
convertedListTag.innerHTML += searchedCurrency
} else {
convertedListTag.innerHTML = ''
convertedListTag.style.display = 'none'
notFound.style.display = 'block'
}
}
window.addEventListener("click", (e) => {
if (e.target.classList.contains("countryTag")) {
let countryTag = document.querySelectorAll('.countryTag')
countryTag.forEach(tag => {
tag.classList.remove("selected")
})
e.target.classList.add('selected')
selectedCurrency.value = e.target.querySelector('p').innerText
countriesModal.classList.remove("active")
let currentTag = document.querySelector(`[data-code="${selectedCurrency.value}"]`)
code = currentTag.getAttribute('data-code')
countryFlag.querySelector('img').setAttribute('src', `https://flagcdn.com/40x30/${countryList[code].toLocaleLowerCase()}.png`)
countryFlag.querySelector('p').innerText = selectedCurrency.value
getConversion()
} else if (e.target.parentElement.classList.contains("countryTag")) {
let countryTag = document.querySelectorAll('.countryTag')
countryTag.forEach(tag => {
tag.classList.remove("selected")
})
e.target.parentElement.classList.add('selected')
selectedCurrency.value = e.target.parentElement.querySelector('p').innerText
countriesModal.classList.add("active")
countriesModal.classList.remove("active")
let currentTag = document.querySelector(`[data-code="${selectedCurrency.value}"]`)
code = currentTag.getAttribute('data-code')
countryFlag.querySelector('img').setAttribute('src', `https://flagcdn.com/40x30/${countryList[code].toLocaleLowerCase()}.png`)
countryFlag.querySelector('p').innerText = selectedCurrency.value
getConversion()
}
})
countryFlag.addEventListener("click", () => {
countriesModal.classList.add("active")
let countryTag = document.querySelectorAll(`[data-code="${selectedCurrency.value}"]`)
countryTag[0].parentElement.classList.add('selected')
})
closeModal.addEventListener("click", () => {
countriesModal.classList.remove("active")
})
convertedFilter.addEventListener("keyup", () => {
convertedListTag.innerHTML = ""
convertedCurrencyBox.classList.add('active')
if (convertedFilter.value == "") {
convertedCurrencyBox.classList.remove('active')
}
filterConvertedData()
})
window.onload = () => {
document.getElementById("loading").style.display = "none"
}
Top comments (0)