В предыдущей статье этой серии я описал пользовательскую конфигурацию jQuery Mobile для нашего приложения и подчеркнул важность предоставления междоменным запросам возможности загружать актуальные курсы обмена валют. Я также описал класс, который поможет нам перевести приложение на несколько разговорных языков, и я выделил второй класс для управления настройками пользователя. В этой четвертой статье я покажу вам классы, которые сохраняют, загружают и выполняют валютные операции, а также класс, объединяющий все различные компоненты нашего приложения.
Класс валюты
Когда я говорил о классе « Settings
», я описал _tableName
переменных _db
и _tableName
. Класс Currency
имеет эти переменные и имеет ту же цель. Конечно, значение _tableName
отличается, как и «валюты». Имейте в виду, что мы не храним объект — мы храним массив, содержащий экземпляры Currency
. Мы должны хранить данные после последнего обновления или последних использованных валют; нам также нужно сохранить название валюты (фактически ее сокращение) и сам курс обмена.
Мы получаем ставки от Европейского центрального банка, и они используют евро в качестве справочных денег. Таким образом, когда вы анализируете канал, вы не найдете сам курс евро (предполагается, что он равен 1,00), и все ставки будут по отношению к евро. Это приводит к сложному методу сравнения валют не в евро, который я подробно объясню при описании метода convert()
.
Исходя из того, что я уже сказал, начало класса Currency
выглядит следующим образом:
function Currency(abbreviation, rate) { var _db = window.localStorage; var _tableName = 'currencies'; this.abbreviation = abbreviation; this.rate = rate; }
Как и в классе « Settings
», у нас будут методы save()
и load()
. Последний идентичен тому, который уже обсуждался, в то время как первый тихо отличается, потому что мы управляем массивом. Поскольку мы не хотим дублировать валюты, нам нужно проверить, сохранена ли данная валюта, прежде чем добавлять в массив. Если валюта уже присутствует, мы просто обновим курс обмена. В противном случае мы поместим весь объект в массив. Для достижения этой цели я создам статический метод getIndex()
, который возвращает индекс валюты, если она найдена, или возвращает false
противном случае. Так же, как вы видели для класса Settings
, я напишу статический метод утилиты для извлечения массива, содержащего экземпляры Currency
называется getCurrencies()
.
Теперь, когда вы знаете об этой сложной ситуации, я могу показать вам код методов save()
и load()
.
this.save = function() { var currencyIndex = Currency.getIndex(this.abbreviation); var currencies = Currency.getCurrencies(); if (currencyIndex === false) currencies.push(this); else currencies[currencyIndex] = this; _db.setItem(_tableName, JSON.stringify(currencies)); } this.load = function() { return JSON.parse(_db.getItem(_tableName)); }
Ниже приведен код для двух статических методов:
Currency.getCurrencies = function() { var currencies = new Currency().load(); return (currencies === null) ? [] : currencies; } Currency.getIndex = function(abbreviation) { var currencies = Currency.getCurrencies(); for(var i = 0; i < currencies.length; i++) { if (currencies[i].abbreviation.toUpperCase() === abbreviation.toUpperCase()) return i; } return false; }
Теперь, когда мы можем сохранять и загружать валюты, нам нужен метод для математического преобразования валют. Прежде чем показывать вам код методов, я должен подчеркнуть одну вещь. Как я уже сказал, в ленте используется евро в качестве базовой валюты, поэтому вы не будете хранить отдельные курсы обмена для каждой валюты — это будет пустая трата памяти. Мы разработаем метод конвертации евро в другие валюты для каждого желаемого типа валюты.
Теперь предположим, что вы хотите конвертировать из USD в AUD, что вы можете сделать? Решение заключается в том, что вы сначала конвертируете в евро, а затем в валюту, которая вам действительно нужна.
Чтобы достичь этой цели, вам нужно сначала поделить на начальный курс, а затем умножить на целевой курс валюты. Для метода convert()
требуется три параметра: значение для преобразования, начальная валюта и целевая валюта. Этот метод основан на другом методе, называемом getRate()
, который, используя abbreviation
(сокращение названия валюты), получает соответствующий курс getRate()
. getRate()
опирается на метод, который я еще не объяснил, называется getCurrency()
. Как вы можете себе представить, он очень похож на getCurrencies()
, за исключением того, что он принимает аббревиатуру в качестве параметра и возвращает экземпляр Currency
если поиск завершился успешно, или null
если он не прошел.
Исходный код этих трех методов приведен ниже:
Currency.getCurrency = function(abbreviation) { var index = Currency.getIndex(abbreviation); return (index === false) ? null : Currency.getCurrencies()[index]; } Currency.getRate = function(abbreviation) { var currency = Currency.getCurrency(abbreviation); return (currency === null) ? 0 : currency.rate; } Currency.convert = function(value, from, to) { // Round up to the 2nd decimal return Math.round(value / Currency.getRate(from) * Currency.getRate(to) * 100) / 100; }
Последние два метода — это те, которые будут использоваться при обновлении полей выбора, чтобы выбрать валюты для сортировки по алфавиту. Их имена являются compareTo()
и compare()
, и их код выглядит следующим образом:
Currency.prototype.compareTo = function(other) { return Currency.compare(this, other); } Currency.compare = function(currency, other) { if (other == null) return 1; else if (currency == null) return -1; return currency.abbreviation.localeCompare(other.abbreviation); }
Сервисные функции
В этом разделе я расскажу о служебных функциях, содержащихся в файле functions.js
. Обратите внимание, что я не буду объяснять updateIcons()
, потому что он уже обсуждался и был представлен в предыдущей серии. Итак, если вы хотите понять, что он делает, вы можете прочитать раздел «Обновление значков на основе размера экрана» в Построение мобильного приложения на основе местоположения с HTML5 и Javascript: Часть 4 .
Тестирование на требования
«Конвертер валют» не предъявляет особых требований. Фактически, единственное обязательное условие, которое нам нужно, — это возможность хранить данные с помощью API веб-хранилища. Хотя возможность подключения к Интернету важна, она необходима только при первом запуске приложения, поскольку ему нужно будет загрузить последние тарифы из RSS-канала Европейского центрального банка. Но после этого пользователь может продолжать работать в автономном режиме с немного устаревшими курсами конвертации валют. Очевидно, что без подключения к Интернету мы не сможем обновлять тарифы.
Чтобы проверить требования, я создам функцию checkRequirements()
, которая будет проверять поддержку API веб-хранилища. Если устройство не поддерживает его, приложение уведомляет пользователя, используя Cordova Notification API, и возвращает false
, поэтому кнопку для обновления конвертации валют можно отключить. Код этой функции показан ниже.
function checkRequirements() { if (typeof window.localStorage === 'undefined') { console.log('The database is not supported.'); navigator.notification.alert( 'Your device does not support the database used by this app.', function(){}, 'Error' ); return false; } return true; }
Как вы видите, я также написал инструкцию console.log()
чтобы помочь вам отладить проект в случае необходимости. Помните, что использование alert()
не рекомендуется.
Перевод страниц
Чтобы перевести элементы index.html
, я буду использовать API-интерфейс Globalization , представленный в Cordova 2.2.0., getPreferredLanguage()
позволяет вам получать информацию о локали и часовом поясе пользователя, особенно благодаря таким методам, как getPreferredLanguage()
(который получает клиентский текущий разговорный язык) и getLocaleName()
(который получает код идентификатора текущей настройки языка клиента, например, en_US или it_IT).
Кроме того, этот API имеет методы для выполнения таких операций, как преобразование дат и чисел в строки с использованием надлежащего локального формата, основанного на настройках пользователя. Методы, которые реализуют эти преобразования: dateToString()
и numberToString()
соответственно. Обратите внимание, что, как и в других API-интерфейсах Cordova, эти методы являются асинхронными, поэтому они используют функции обратного вызова для успешных и неудачных вызовов.
В нашем проекте мы будем использовать некоторые из ранее цитируемых методов, а именно: getLocaleName()
, dateToString()
и numberToString()
. Этот API очень важен, потому что он позволяет продвинуть пользовательский опыт на один шаг вперед по сравнению с тем, что вы могли сделать в предыдущих версиях. Обратите внимание, что в настоящее время поддерживаются следующие платформы: Android, BlackBerry WebWorks (OS 5.0+), iOS и Windows Phone 8.
Как вы увидите из приведенного ниже кода, я использовал метод getLocaleName()
для получения идентификатора языка, который я буду использовать для получения правильного языка из объекта Translation
. После получения я переберу текстовые строки, чтобы перевести различные учебные элементы. Теперь вы должны наконец понять, почему я использовал имя элемента как свойства. Вы также заметите использование Audero Text Changer для изменения текста элементов, что я иллюстрировал в первой части этой серии.
/** * Translate the main page */ function translateMainPage() { navigator.globalization.getLocaleName( function(locale) { var translation = Translation[locale.value.substring(0, 2)]; if (typeof translation === 'undefined') return; for(var key in translation) $('#' + key).auderoTextChanger(translation[key]); }, function() { console.log('An error has occurred with the translation'); } ); }
Вывод
В этой четвертой статье я описал класс Currency
и все его методы. Как вы узнали, у него есть несколько служебных методов, которые позволяют вам писать новые методы с очень небольшим количеством строк кода. Я также показал, как тестировать минимальные требования к приложениям, и дал краткий обзор API глобализации, а также конкретные методы, используемые в нашем проекте. Чтобы помочь нам управлять переводом элементов интерфейса, я использовал плагин Audero Text Changer . В следующей части серии я покажу вам остальные functions.js
файла functions.js
чтобы завершить обсуждение.