Accessible currency converter, including dropdown and API usage

Accessible currency converter, including dropdown and API usage

With website visitors from around the globe and having to convert currencies when doing a quotation, I figured embedding a currency converter instead.

But obviously, exchange rates had to be up-to-date as they can be quite volatile, so I needed an API to retrieve current exchange rates. I could implement this in two different ways:

  • server side via PHP;
  • or client side using JavaScript.

I went with the latter: JavaScript.

Exchange rate API

This appeared to be the easiest part after Googling for "exchange rate api". ExchangeRatesApi.io is a free API with up-to-date rates for Australian Dollar (AUD) to South African Rand (ZAR), returned in JSON format. While already using jQuery, I could just use $.getJSON to fetch the data.

Exchange rate API result

The result of the API call will be similar to the following, but then with up to date exchange rate data:

GET https://api.exchangeratesapi.io/latest HTTP/1.1

{
"base": "EUR",
"date": "2018-04-08",
"rates": {
"CAD": 1.565,
"CHF": 1.1798,
"GBP": 0.87295,
"SEK": 10.2983,
"EUR": 1.092,
"USD": 1.2234,
...
}
}

Lack of currency symbols

One downside of this API was that it did not return currency symbols. As a result, I just searched for a static list of currencies, as unlike exhange rates, symbols won't change. While fetching the exchange rates, you can just merge the two JSON objects.

Setting up the currency picker

Styling the currency picker was the first step. Within the CMS that I used, I introduced a shortcode to be able to configure the default options within the button-group. This actually was the first version and looked like this:

€ 10
€ 25

Support more currencies

But while already using an API to fetch current exhange rates for these currencies, I figured I might as well go the extra mile and also support all additional currencies. The reason? Visitors from 44 different countries visited my website in the last week and 78 countries during the last month.

However, showing all those options next to the other limited default options would only clutter the user interface, so I decided to introduce a dropdown, and inserting additional currencies as items within the dropdown. The result was as following:

Accessibility of the combined currency picker

Sweet, right? But obviously, WCAG 2.1 / accessibility still matters as well. Bootstrap does support keyboard accessibility of anchors within a dropdown, but I used radio buttons instead of anchors/hyperlinks. I tried implementing listbox to keep HTML more straighforward though, but it just resulted in more complex JavaScript and accessibility even regressed, so I quickly reverted to radio buttons.

The best part is that when you opened the dropdown, you can use the up and down arrow keys to loop through the options, both the options in the default setup as well as the options within the dropdown. As long as the name attribute values of the input-elements are the same, this just is default browser behaviour, resulting in accessibility by default.

Involved JavaScript

Obviously, I created this currency picker using Bootstrap JS for the dropdown component on top of (customized) Bootstrap CSS for both the button group and dropdown menu. But additional JS was needed to fetch the exchange rates and change all values based on choosen currency.

Prevent performance regression

But next to additional JavaScript, additional work needed to be done as well. And as demonstrated in my JavaScript chatbot performance visualizer, you would rather keep the main thread of the browser as idle as possible. So this was my approach:

  1. API data only gets loaded once during the lifecycle of the page. Your latest selected currency, symbol and exchange rate gets saved into sessionStorage;
  2. On refresh, latest selected currency gets retrieved from sessionStorage and correct .btn gets highlighted. This way, no new API call has to be made;
  3. A new API call is only being made on opening the dropdown menu (or selecting one of the static radio-buttons). If original radio-selection is within the dropdown-menu, it gets highlighted;
  4. Each time the dropdown-menu is being shown, focus is moved to either the radio-button that is/should be already selected, or else the first radio-button in the dropdown (both using tabindex=-1).

Is it performant? Yes it is! When tested using Google's PageSpeed Insights, this blog article would score around 98 to 100%, on mobile! And if you've read the whole article, you now know it can be done, even when using jQuery (and Bootstrap JS), like this and many other websites do.

Full code example

I republished this setup on codepen, but then with inlined JSON instead, containing the symbols. You can find it on codepen with default Bootstrap CSS.

Watch the codepen

As it's just styled using CSS, so you can style them whatever you like, or even replace Bootstrap CSS or JS with your preferred libraries. Happy coding!