Средства управления датой в jQuery UI

Дино Эспозито (Dino Esposito) | 12 февраля 2010 года

Когда-то работа с датами в контексте веб-приложения была серьезной проблемой. Сегодня все по-другому, и станет еще лучше с появлением HTML 5. Ведь в HTML 5 ожидается поддержка тегом <input> нескольких новых атрибутов типа, в том числе атрибута date. Исходя из этого, можно ожидать, что браузеры скоро начнут предлагать встроенные функции выбора даты, и что правильный ввод дат в формы больше не будет такой проблемой, как сейчас.

Если честно, хотя нам все еще не хватает стандартного решения для работы с датами в веб-формах ввода, мы по крайней мере можем полагаться на множество предложений из различных источников в рамках сообщества. Независимо от того, нужен ли простой выбор даты или сложный интерфейс для обработки диапазонов дат и многомесячные календари, можно найти подключаемый модуль или компонент, который даст отправную точку.

Например, в библиотеке jQuery UI имеется виджет datepicker, который преобразует простой элемент ввода текста в настраиваемое средство выбора даты.

Простая конфигурация элемента выбора даты

После настройки библиотеки jQuery UI и правильной привязки файлов ее тем и скриптов к проекту, можно добавить уровень скрипта к элементам HTML DOM, чтобы расширения библиотеки могли работать. Предположим, что имеется форма с элементом ввода, нацеленным на сбор дат:

<form>
   <h2>Прием даты</h2>
   <input type="text" id="FavoriteDay" />
</form>

Чтобы позволить пользователю выбрать дату ввода из всплывающего календаря, включите библиотеку jQuery UI для календаря, как показано ниже:

<script type="text/javascript">
    $(document).ready(function() {
        $("#FavoriteDay").datepicker();
    });
</script>

Использование блока конфигурации JavaScript, который запускается после полной загрузки документа и присоединяет обработчики событий, а также выполняет другие настройки — это хорошая техника, позволяющая хранить разметку отдельно от логики представления JavaScript. Пока все хорошо. На рис. 1 показана ситуация на этот момент.


Рис. 1. Стандартный элемент выбора даты

Элемент выбора даты автоматически выбирает текущую дату и предоставляет пользователю интерфейс на основании текущих региональных настроек. Чтобы задать начальное отображение другой даты, можно использовать объект параметров. Вот как определить можно дату по умолчанию:

<script type="text/javascript">
    $(document).ready(function() {
        $("#FavoriteDay").datepicker(
            { defaultDate: new Date(2010, 1, 8) }
        );
    });
</script>

Свойство defaultDate задает дату, которая выбирается при открытии элемента выбора даты. Это значение игнорируется, если элемент ввода содержит допустимое значение даты.  Дату по умолчанию можно задать несколькими способами. Например, можно передать объект Date как в примере или передать строку, которая представляет задаваемую дату.  Строка будет проанализирована в соответствии с текущим форматом даты. Формат даты можно задать с помощью свойства dateFormat в параметрах компонента или использовать формат по умолчанию для текущих региональных параметров. Вот как можно задать формат:

<script type="text/javascript">
    $(document).ready(function() {
        $("#FavoriteDay").datepicker(
            { 
              defaultDate: new Date(2010, 1, 8),
              formatDate: 'dd-mm-yy'
            }
        );
    });
</script>

Интересно отметить, что jQuery UI поддерживает специальный относительный синтаксис для определения текущей даты. Этот синтаксис идеально подходит для сценариев, в которых пользователь выбирает дату для регистрации события или встречи. Если задать для свойства defaultDate значение “+1”, это интерпретируется как “выбрать следующий день”. Аналогично, строка “+10d +1m” показывает выбор даты, отстоящей от текущей на 10 дней и 1 месяц.

Локализация элемента выбора даты

На рис. 1 видно, что пользовательский интерфейс элемента выбора даты использует английский язык. Это просто настройка по умолчанию. Можно загрузить локализованный файл скрипта и соответственно настроить параметры отображения виджета. Локализованные файлы скрипта можно загрузить на странице jquery-ui.googlecode.com/svn/trunk/ui/i18n. Имя локализованного скрипта jquery.ui.datepicker-XX.js,, где буквы XX обозначают язык, например it для итальянского или de для немецкого. Пример:

<head runt="server">
    <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
    <link href="../../Content/jq-ui-Themes/sunny/jquery-ui-sunny.css" type="text/css" />   
    :
    <script type="text/javascript" src="/Scripts/jQueryUI/jquery-ui-1.7.2.min.js"></script>  
    <script type="text/javascript" src="/Scripts/jQueryUI/jquery.ui.datepicker-it.js"></script>  
</head>

Простой привязки файла скрипта недостаточно. Также необходимо, чтобы библиотека jQuery UI учитывала эту настройку. Для этого используется массив $.datepicker.regional, как показано ниже:

<script type="text/javascript">
    $(document).ready(function() {
        $("#FavoriteDay").datepicker($.datepicker.regional['it']);
    });
</script>

На рис. 2 показан локализованный элемент выбора даты.


Рис. 2. Локализованный элемент выбора даты для отображения пользовательского интерфейса на итальянском языке

Хотя библиотека jQuery UI предлагает отличную поддержку локализации, в настоящее время у нее нет встроенной возможности для определения текущих языковых настроек и соответствующего обновления пользовательского интерфейса. Вообще, можно найти несколько подключаемых модулей и средств для автоматизации загрузки локализованных скриптов. Например, это делает элемент управления ASP.NET ScriptManager. Другим возможным вариантом является подключаемый модуль локализации jQuery. Этот подключаемый модуль доступен на странице keith-wood.name/localisation.html. Интересно рассмотреть, как ScriptManager с его свойством EnableGlobalization и подключаемый модуль локализации jQuery справляются с решением этой проблемы.

Подключаемый модуль локализации jQuery определяет язык с помощью данных, возвращаемых объектом navigator в объектной модели браузера. Элемент управления ScriptManager внедряет на страницу код JavaScript, который сообщает сведения о глобализации, доступные на сервере. Давайте сначала обсудим решение, применяемое подключаемым модулем локализации jQuery.

var lang = window.navigator.userLanguage || window.navigator.language;  
lang = lang.substring(0, 2)
if (lang === "en")
    lang = "";

Объект браузера navigator предоставляет сведения о языке через разные свойства в зависимости от браузера. В частности, в Internet Explorer используется свойство userLanguage, а в браузерах на основе Mozilla — свойство language. Кроме того, обратите внимание, что оба свойства возвращают полную строку культуры в виде комбинации кодов языка и культуры, например it-IT или en-US.  С другой стороны, массив jQuery UI regional распознает только коды языков. По этой причине необходимо удалить первые две буквы из строки языка, возвращаемой объектом window.navigator.

Всегда ли работает этот метод? Этот метод определенно работает, но следует заметить, что он возвращает язык, заданный на уровне браузера. Это может не отражать языковые параметры пользователя, работающего с браузером. Другими словами, если изменить язык в диалоговом окне, показанном на рис. 3, это изменение не будет распознано объектом браузера navigator.


Рис. 3. Диалоговое окно "Язык" в Internet Explorer

Как определить предпочитаемый язык пользователя и обработать его в JavaScript? Предпочитаемый язык передается с помощью заголовка HTTP, определяющего допустимый язык. Эти данные доступны на сервере, но их непросто извлечь из клиента. Однако, если ваша веб-страница динамическая (например, страница ASP.NET), вы можете динамически создать переменную JavaScript с культурой, обнаруженной на сервере, что и делает свойство объекта ScriptManager EnableGlobalization. Вот пример кода:

var culture = '<%= System.Globalization.CultureInfo.CurrentCulture.TwoLetterISOLanguageName %>';

Если этот код внедрен на веб-страницу, во время выполнения создается следующий фрагмент JavaScript:

var culture = 'it';

Теперь можно программно задать язык элемента выбора даты, как показано ниже:

$("#FavoriteDay").datepicker($.datepicker.regional[culture]);

Другие параметры элемента выбора даты

Виджет datepicker предлагает несколько параметров, которые можно использовать для настройки его интерфейса. Например, свойства altField и altFormat позволяют автоматически копировать выбор даты в другое поле ввода и в заданном формате.

$("#FavoriteDay").datepicker(
   { 
       altField: '#actualDate', 
       altFormat: 'yy::mm::dd'
   }
);

Если свойство altField указывает на идентификатор другого текстового поля ввода, назначение выполняется автоматически, а также применяется формат, заданный свойством altFormat.

Обычно календарь всплывает при щелчке текстового поля, связанного с элементом выбора даты. Однако это поведение можно изменить, чтобы включить отображение всплывающего календаря и при нажатии на кнопку.

$("#FavoriteDay").datepicker(
   { 
       showOn: 'button', 
       buttonText: 'Choose'
   }
);

Свойство showOn может принимать следующие значения: focus, button или и то и другое. Значение по умолчанию focus. Значение focus показывает, что календарь будет отображаться, когда связанное текстовое поле получит фокус ввода. Значение button показывает, что существует кнопка, которую нужно нажать. Однако, создавать кнопку самостоятельно не нужно. Просто присвойте значение свойству buttonText, и библиотека создаст кнопку сама. По желанию кнопка может быть создана на основе изображения.  

Логическое свойство changeMonth изменяет элемент выбора даты, добавляя раскрывающийся список для выбора месяца. Пример можно увидеть на рис. 4.


Рис. 4. Раскрывающийся список месяцев в элементе выбора даты

Обратите внимание на несколько особенностей на рис. 4. Во-первых, пользовательский интерфейс локализован; во-вторых, он отображает дни предыдущего, текущего и следующего месяцев.  Чтобы добавить дни из других месяцев, необходимо добавить еще одно логическое свойство: showOtherMonths.

Как еще можно сочетать параметры локализации с параметрами отображения? Следующий пример — возможно первое, что приходит в голову — просто не будет работать:

$("#FavoriteDay").datepicker(
     $.datepicker.regional['it'], 
     { ... }
);

Эти два действия должны выполняться по отдельности, как разные операции. Сначала нужно задать язык, а потом — любые необходимые параметры:

$("#FavoriteDay").datepicker(
     $.datepicker.regional['it']);
$("#FavoriteDay").datepicker(
   'option',
   { ... }
);

После присоединения функции datepicker к заданному элементу DOM ее параметры по-прежнему можно изменять, но эта операция должна выполняться как запрос изменения параметра.  В предыдущем коде ‘option’ — это ключевое слово, которое определяет сообщение, отправляемое виджету.

Отображение нескольких месяцев

Компонент datepicker не ограничен одновременным отображением только одного месяца. Количество одновременно отображаемых месяцев можно задать. Для этого в коллекции options имеется свойство numberOfMonths, которое связано со свойством showCurrentAtPos. Первое свойство указывает число отображаемых месяцев начиная с текущей даты. Свойство showCurrentAtPos указывает позицию текущего месяца в отображении. Например, предположим, что для свойстваnumberOfMonths задано значение 3, а для свойства showCurrentAtPos — 1, как показано ниже:

$("#FavoriteDay").datepicker('option', 
  {
    numberOfMonths: 3, 
    showCurrentAtPos:1
  }
);

В результате отображается три месяца, но текущий месяц является вторым. Если выбрана дата в феврале, первым месяцем будет январь, а затем — февраль и март. На рис. 5 показан ожидаемый результат.


Рис. 5. Отображение нескольких месяцев для элемента выбора даты

Свойство numberOfMonths также может принимать массив из двух целых чисел. Первое число указывает количество строк, а второе — количество столбцов. Вместе эти два числа описывают отображаемую таблицу месяцев.

Особенно интересными являются свойства minDate и maxDate. Они позволяют определить интервал дат для выбора. Могут выбираться только даты, попадающие в этот интервал. Остальные даты могут отображаться, но будут затененными и недоступными для выбора.

Кроме того, элемент выбора даты jQuery UI поддерживает недели в своем формате. Если задать свойство showWeek, виджет будет отображать сведения о неделях.

События

В завершение этой статьи коротко рассмотрим события, определенные для виджета datepicker. Имеются такие традиционные события, как onClose и onSelect.  Первое запускается при закрытии элемента выбора даты, а второе — при выборе даты. Событие onChangeMonthYear запускается при переходе компонента на новый месяц или новый год.

Два других события придают элементу выбора даты определенную мощность: beforeShow и beforeShowDay. Событие beforeShow запускается перед отображением элемента выбора даты. Обработчик события должен передавать объект параметров, используемый для динамической настройки компонента. Таким же образом, событие beforeShowDay запускается перед отображением каждого дня в календаре. Вот пример обработчика события:

$("#FavoriteDay").datepicker('option', 
  {
     beforeShowDay: function(date) {
          if (date.getMonth() == 1 && (date.getDate() >5 && date.getDate() <10))
               return [false, ''];
           return [true, ''];
     }
  }
);

Обработчик события получает отображаемую дату и возвращает массив, первым элементом которого является логическое значение, показывающее, будет ли дата доступна для выбора. Второй элемент может по желанию указывать стиль CSS для данной даты. На рис. 6 показан пример, в котором несколько дней февраля отключены.


Рис. 6. Отключение нескольких дней в календаре

Как видите, событие beforeShowDay идеально подходит для отображения выходных и рабочих дней в приложении ведения календаря.

Заключение

Даты являются важным типом данных для любого типа приложений, и веб-приложения не исключение. Для эффективного программирования выбора даты необходимы не только классы, но и специальные элементы пользовательского интерфейса для работы с датами. Элементы выбора даты и календари сегодня являются необходимыми средствами, и многие из них уже существуют в готовом виде. В библиотеке jQuery UI есть собственное средство — виджет datepicker — в котором достигнута сбалансированность гибкости и встроенных возможностей. Дополнительные сведения см. на странице docs.jquery.com/UI/Datepicker.