Build a Currency Converter with jQuery Mobile and Cordova: 5

Share this article

In the previous article in this series, I described the classes and functions needed to perform currency conversions within our app. I also illustrated the Cordova Globalization API and how we can use it to translate the written instructions on the main page of “Currency Converter.” In this next installment, I’ll show you the remaining functions of the functions.js file and a brief overview of the Cordova Connection and InAppBrowser APIs.

Utility Functions

Updating the “Last Update” Label

In the introductory article of this series, I explained that our project will store the downloaded currency rates so that the user can use the application offline. Since the currency exchange rates change every day, it’s important to notify the user of how old his exchange rates are. If he feels that they are too old, he can run an update and download the latest. For this reason, the main page has the following code:
<label id="last-update-label">Last update of exchange rates:</label>
<span id="last-update"></span>
The <span> having id="last-update" is where we’ll inject the date of the last update. Th date will be written in the format that best suits the user preferences determined by the Globalization API, which I explained in the previous article. Recalling the third article where we talked about the user settings, you should recall that we update and save the date each time the user request an exchange rates update via the Settings class and its methods. The function that updates the text of the above <span> tag is updateLastUpdate(), and its markup is the following:
function updateLastUpdate()
{
  if (typeof Settings.getSettings().lastUpdate === 'undefined')
  {
    $('#last-update').text('-');
    return;
  }

  // Show the last time the rates have been updated
  navigator.globalization.dateToString(
    new Date(Settings.getSettings().lastUpdate),
    function (date)
    {
      $('#last-update').text(date.value);
    },
    function ()
    {
      $('#last-update').text('-');
    }
  );
}

Updating the Rates

The method that deals with the actual updating is updateExchangeRates(). At the very beginning of the method, there is a test to verify whether the device is connected to the Internet or not. The test is done using the Cordova Connection API—an object that gives access to the device’s cellular and wifi connection information. It has one property called type that checks the active network connection that is being used and can assume the following values (as constants):
  • Connection.UNKNOWN
  • Connection.ETHERNET
  • Connection.WIFI
  • Connection.CELL_2G
  • Connection.CELL_3G
  • Connection.CELL_4G
  • Connection.NONE
If the device has an active connection, the function makes a call to the European Central Bank RSS feed to retrieve the rates using the jQuery ajax()
method. Once retrieved, the rates are stored using the Currency class, and the lastUpdate data of the user’s settings is updated as well, so the user knows that they’re working with the latest currency exchange rates. The two select boxes and the “last update” label of the main page are updated using this current data. Then, the two select menus are filled using a function called fillCurrenciesSelection(), which I’ll describe in a few moments. As a final note, if the rate update fails, the user is notified with an alert of this failure shown using the Cordova Notification API. So, what exactly will happen if the first test fails? Well, if the device does not have an active Internet connection, the app will check if there are any stored rates. If there are no stored currency exchange rates, the user is notified of the issue, and the “Convert” button is disabled, because there aren’t any ways to run any currency conversions. The code that implements this functionality is listed below:
/**
 * Update the exchange rates using the ECB web service
 */
function updateExchangeRates()
{
  if (navigator.network.connection.type !== Connection.NONE)
  {
    $.mobile.loading(
      'show',
      {
        text: 'Updating rates...',
        textVisible: true
      }
    );

    $.get(
      'http://www.ecb.int/stats/eurofxref/eurofxref-daily.xml',
      null,
      function(data)
      {
        var $currenciesElements = $(data).find('Cube[currency]');
        // The EURO is the default currency, so it isn't in the retrieved data
        var currencies = [new Currency('EUR', '1')];

        var i;
        for(i = 0; i < $currenciesElements.length; i++)
        {
          currencies.push(
            new Currency(
              $($currenciesElements[i]).attr('currency'),
              $($currenciesElements[i]).attr('rate')
            )
          );
        }

        currencies.sort(Currency.compare);
        // Store the data
        for(i = 0; i < currencies.length; i++)
          currencies[i].save();

        // Update settings
        var settings = Settings.getSettings();
        if ($.isEmptyObject(settings))
          settings = new Settings();
        settings.lastUpdate = new Date();
        settings.save();

        fillCurrenciesSelection();
        updateLastUpdate();
        $('#submit-button').button('enable');
      },
      'XML'
    )
    .error(function() {
      console.log('Unable to retrieve exchange rates from the provider.');
      navigator.notification.alert(
        'Unable to retrieve exchange rates from the provider.',
        function(){},
        'Error'
      );
      if (Currency.getCurrencies().length === 0)
        $('#submit-button').button('disable');
    })
    .complete(function() {
      $.mobile.loading('hide');
    });
  }
  // Check if there are data into the local storage
  else if (Currency.getCurrencies().length === 0)
  {
    console.log('The connection is off and there aren't rates previously stored.');
    navigator.notification.alert(
      'Your device has the connection disabled and there aren't rates previously stored.n' +
      'Please turn on your connection.',
      function(){},
      'Error'
    );
    $('#submit-button').button('disable');
  }
}

Filling the Select Boxes

The function to update the select boxes isn’t very hard to grasp. It simply retrieves the stored currencies using the getCurrencies() method of the Currency class and then insert each of them using the jQuery append() method. It’s worth noting that after all the currencies are inserted, this function searches for the last origin and destination currencies saved within the user preferences If these last used currencies are found, they are automatically selected. In this scenario, the listview widget needs to be refreshed, which accomplished using the method selectmenu() and passing the string refresh to it. The complete source of fillCurrenciesSelection() is listed below:
/**
 * Use the stored currencies to update the selection lists
 */
function fillCurrenciesSelection()
{
  var currencies = Currency.getCurrencies();
  var $fromCurrencyType = $('#from-type');
  var $toCurrencyType = $('#to-type');

  // Empty elements
  $fromCurrencyType.empty();
  $toCurrencyType.empty();

  // Load all the stored currencies
  for(var i = 0; i < currencies.length; i++)
  {
    $fromCurrencyType.append('
' +      currencies[i].abbreviation + '
');
    $toCurrencyType.append('
' +      currencies[i].abbreviation + '
');
  }

  // Update the selected option using the last currencies used
  var settings = Settings.getSettings();
  if (!$.isEmptyObject(settings))
  {
    var currency = $fromCurrencyType.find('[value="' + settings.fromCurrency + '"]');
    if (currency !== null)
      $(currency).attr('selected', 'selected');

    currency = $toCurrencyType.find('[value="' + settings.toCurrency + '"]');
    if (currency !== null)
      $(currency).attr('selected', 'selected');
  }

  $fromCurrencyType.selectmenu('refresh');
  $toCurrencyType.selectmenu('refresh');
}

Managing External Links

As you’ve seen in the interface design of “Currency Converter”, the aurelio.html file have several external links within it. Those links aren’t very useful, but I do need to explain an important concept. Until a few versions ago, Cordova opened external links in the same Cordova WebView that was running the application. So, once it opened a link, when the user clicked the “back” button, the last project’s page was shown exactly as it was before the user left it. But, in the most recent release of the framework, this behavior was changed; now, the external links are opened by default using the Cordova WebView if the URL is in your app’s whitelist. URLs that aren’t on your whitelist are opened using the InAppBrowser API. Citing the official documentation, the InAppBrowser is a web-browser that is shown in your app when you use the window.open call. This API has three methods: addEventListener(), removeEventListener()
, and close(). The first allows you to listen for three events (loadstart, loadstop, and exit) and allows you to attach a function that runs as soon as those events are fired. The second method, as you might guess, is used to remove a previously-attached listener. Finally, the close() method is used to close the InAppBrowser window. If the user opens a link that is shown in the InAppBrowser or the system browser and then goes “back” to the application, all the CSS and jQuery Mobile enhancements are lost. This happens because the external link doesn’t the reference the cited files and when the user goes back into the app; the file is loaded as it were requested for the first time, but without passing through the main page. Obviously, this is something you’ll want to avoid, which highlights the importance of the the whitelist within the Cordova configuration file and the next function come in help. The aim of the openLinksInApp() function is to catch the clicks on all the external links (recognized by using the target="_blank" attribute), preventing the unwanted default behavior and opening them using the window.open() method. As you’ll see in the code shown below, I’ll use the _target parameter so that the links will be opened using the WebView, because I’ll put these URLs in the Cordova whitelist. Using this technique, we’ll avoid the issues described above, and your app will continue to look and function as expected.
/**
 * Open all the links as internals
 */
function openLinksInApp()
{
   $("a[target="_blank"]").on('click', function(event) {
      event.preventDefault();
      window.open($(this).attr('href'), '_target');
   });
}

Conclusion

In this article, I described several other functions of the functions.js file, highlighting the key points of each. I also explained the Cordova Connection and the InAppBrowser API and how they work. As we’ve seen, dealing with external links is extremely important when you’re using jQuery Mobile to build your mobile app interface. In the next and final article in this series, I’ll show you the function that initializes the application, called initApplication(), and the Cordova configuration file that we will use alongside the Adobe PhoneGap Build service to package our “Currency Converter” app.

Frequently Asked Questions about Building a Currency Converter with jQuery Mobile and Cordova

How can I ensure that the currency conversion rates are always up-to-date?

To ensure that your currency conversion rates are always up-to-date, you need to use a reliable API that provides real-time exchange rates. In the tutorial, we used the Open Exchange Rates API. This API provides up-to-date and accurate exchange rates for various currencies. You can set up your application to fetch the latest rates at regular intervals, ensuring that your currency converter always provides the most accurate conversions.

Can I add more currencies to the converter?

Yes, you can add more currencies to your converter. The Open Exchange Rates API supports over 170 currencies. You can add these currencies to your converter by modifying the code to include the additional currencies. You will need to add the currency code to the list of currencies in your application and ensure that the API fetches the exchange rates for these currencies.

How can I make my currency converter mobile-friendly?

The tutorial uses jQuery Mobile, a touch-optimized web framework for smartphones and tablets. jQuery Mobile provides a unified user interface system that works across all popular mobile device platforms. It is built on the jQuery core and uses HTML5 and CSS3 to provide a lightweight, easy-to-use framework for developing mobile-friendly applications.

Can I use another API instead of Open Exchange Rates?

Yes, you can use another API for your currency converter. There are several APIs available that provide exchange rates. However, you will need to modify the code to work with the API you choose. Make sure to check the documentation of the API for information on how to fetch the exchange rates.

How can I handle errors in the application?

Error handling is an important part of any application. In the tutorial, we use the jQuery Ajax error function to handle errors. This function is called if the Ajax request fails. You can use this function to display an error message to the user or to take other actions in case of an error.

Can I use this tutorial to build a currency converter for a different platform?

This tutorial is specifically designed for building a currency converter with jQuery Mobile and Cordova. However, the principles and techniques used in this tutorial can be applied to other platforms as well. You will need to adapt the code to work with the platform you are using.

How can I improve the performance of my currency converter?

There are several ways to improve the performance of your currency converter. One way is to optimize the code. This can include reducing the number of API calls, using efficient algorithms, and minimizing the use of resources. Another way is to use a caching mechanism to store the exchange rates. This can reduce the number of API calls and improve the speed of the converter.

Can I add additional features to my currency converter?

Yes, you can add additional features to your currency converter. Some possible features include a history of exchange rates, a comparison of different currencies, or a graph showing the fluctuation of exchange rates. You will need to modify the code to add these features and may need to use additional APIs or libraries.

How can I test my currency converter?

Testing is an important part of developing any application. You can test your currency converter by using different currencies and checking if the conversion rates are correct. You can also test the error handling by disconnecting from the internet or using invalid currency codes.

Can I monetize my currency converter?

Yes, you can monetize your currency converter. There are several ways to do this. You can display ads, offer premium features, or charge for the app. However, you need to ensure that your app provides value to the users and complies with the terms of service of the app store and the API provider.

Aurelio De RosaAurelio De Rosa
View Author

I'm a (full-stack) web and app developer with more than 5 years' experience programming for the web using HTML, CSS, Sass, JavaScript, and PHP. I'm an expert of JavaScript and HTML5 APIs but my interests include web security, accessibility, performance, and SEO. I'm also a regular writer for several networks, speaker, and author of the books jQuery in Action, third edition and Instant jQuery Selectors.

jQuerymobilemobile web tutorialsTutorials
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week