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.
Let's Set up the Project
- Create a new folder for your project and name it something descriptive.
- Inside the project folder, create a new file called index.html. This will be your main HTML file.
- Open index.html in a code editor such as Visual Studio Code.
- Inside the head section of index.html, create a new link element that links to your CSS file. The link element should look like this: "<link rel="stylesheet" href="styles.css">" Make sure to replace styles.css with the name of your CSS file.
- Save the changes to index.html.
- In the same project folder, create a new file called styles.css. This will be your main CSS file.
- Open styles.css in a code editor.
- Write your CSS rules inside styles.css.
- Save the changes to styles.css.
- In the head section of index.html, create a new script element that links to your JavaScript file. The script element should look like this: "<script src="script.js"></script>" Make sure to replace script.js with the name of your JavaScript file.
- Save the changes to index.html.
- In the same project folder, create a new file called script.js. This will be your main JavaScript file.
- Open script.js in a code editor.
- Write your JavaScript code inside script.js.
- Save the changes to script.js.
Now you have successfully created a basic HTML, CSS, and JavaScript file and linked them together. Any changes you make to your CSS or JavaScript files will be reflected in your index.html file when you refresh the page.
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
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"
}
Here is the Final Output of this Code
Hurray! now you've created a Currency Converter 😎. You can download files by clicking on the download button after downloading file if you are facing any kind of problem feel free to ask me in the comment section and you can also contact me via e-mail. Thanks for giving your precious time for reading this blog. Here is the download button:-