Ovládací prvek Calendar umožňuje uživateli velmi komfortní volbu data v aplikaci. Bohužel, jako u většiny webových ovládacích prvků, je tento komfort vázán na JavaScript. V článku si ukážeme, jak v aplikaci doplnit kalendář o podobnou funkčnost i u klientů bez JavaScriptu, byť ne tolik komfortní.

O ovládacím prvku kalendáře už jsme psali v článku, ve kterém ukazujeme, jak je pro uživatele pohodlné, když zvolené datum vidí nejen napsané, ale i přímo zvýrazněné v kalendáři. V tomto článku umožníme uživateli v kalendáři datum i vybrat. A aby ani uživatelé, kteří nemají podporu JavaScriptu, nebyli ochuzeni o názornou ukázku zvoleného dne, využijeme zde kalendář alespoň jako zobrazovací prvek. Datum, které uživatel s podporou JavaScriptu zvolí prostě klepnutím myši v kalendáři, necháme ostatní uživatele zadat v alternativním textovém poli. Textové pole můžeme navíc nechat viditelné pouze v prohlížečích bez JavaScriptu. Tak vytvoříme univerzální názorný kalendář. Prohlédněte si ukázku (zdrojový kód).

Nejprve výtah kódu stránky, kde je kalendář doplněn o alternativní textové pole:

<asp:Calendar Id=“Calendar1″ RunAt=“server“>
  <SelectedDayStyle ForeColor=“White“ BackColor=“#6699FF“ />
</asp:Calendar>
<noscript>
  <asp:TextBox AutoPostBack=“False“ Id=“txtDate“ ToolTip=“Datum dodání“ Size=“10″ MaxLength=“10″ RunAt=“server“ />
  <asp:Button OnClick=“Set_Date“ ToolTip=“Zvolit datum“ Text=“&raquo;“ RunAt=“server“ /><br />
</noscript>
<asp:RegularExpressionValidator Id=“vldDate“ ValidationExpression=“^(0[1-9]|[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012]|[1-9])[- /.](19|20)\d\d$“ ControlToValidate=“txtDate“ ErrorMessage=“Zadané datum je neplatné“ Display=“Dynamic“ RunAt=“server“ />

Pod ovládacím prvkem Calendar vidíme textové pole a odesílací tlačítko uzavřené do značek noscript. Tak zajistíme, že alternativní možnost volby data bude k dispozici jen u klientů bez JavaScriptu. Připojen je také validátor, který musíme ponechat mimo část noscript, jinak by při vygenerování klientského skriptu došlo k chybě (klientský skript pro validaci generovaný .NET frameworkem by se pak snažil pracovat s „neexistujícím prvkem“). Toto však nevadí, protože validátor do stránky generuje výstup jen při vzniku chyby a k té může v našem případě dojít jen když do textového pole bude zadáno datum v nesprávném formátu. Pokud textové pole pro zadání data nebude vidět, nemůže do něj nikdo nic napsat a validátor nebude mít důvod cokoli hlásit.

Pro validaci formátu zadávaného data využijeme regulární výraz, který umožní zadat většinu v našich končinách obvyklých tvarů data – den, měsíc a rok, přičemž oddělovačem může být tečka, lomítko nebo pomlčky. Takovéto zadání totiž pro české prostředí (Culture) bezproblémů pojme metoda Parse, pomocí níž získáváme z textového pole datum typu DateTime.

Dále si popíšeme obsluhu alternativního textového pole:

void Set_Date(object sender, System.EventArgs e)
{
  if (vldDate.IsValid)
  {
    if (txtDate.Text.Length > 0)
    {
      try
      {
        Calendar1.SelectedDate = DateTime.Parse(txtDate.Text);
        Calendar1.VisibleDate = Calendar1.SelectedDate;
      }
      catch
      {
        vldDate.IsValid = false;
      }
    }
    txtDate.Text = Calendar1.SelectedDate.ToShortDateString();
  }
}
void Page_Load(object sender, System.EventArgs e)
{
  if (!IsPostBack)
  {
    Calendar1.SelectedDate = DateTime.Today;
  }
}

V obsluze události Page_Load zjistíme, jestli jde o první zobrazení formuláře porovnáním vlastnosti IsPostBack – pokud ano, pak zde pro ukázku nastavíme vybrané datum v kalendáři na dnešní datum.

Dále máme definovanou obsluhu události, kterou vyvolává stisknutí tlačítka pro alternativní volbu data „Set_Date“. Zde jednoduše ověříme, zda ve vlastnosti IsValid neprotestuje validátor textového pole. Potom otestujeme, zda je text delší než 0 znaků. Mohli bychom sice využít i validátor povinné položky, ovšem bylo by nutné zadávat datum do textového pole vždy při odesílání formuláře (a tedy i při klikání na položky v kalendáři) a to rozhodně není žádoucí. Pokud tedy je zadán nějaký text, pokusíme se jej nastavit jako datum v kalendáři. Dojde-li k výjimce (dojde k ní například pokud je zadáno neplatné datum 31. 2. 2003), sdělíme validátoru, že datum i tak není validní. Výsledkem tak bude zobrazené chybové hlášení validátoru. Nakonec nezávisle na tom, zda se podařilo nastavit nové datum v kalendáři, vnutíme do textového pole vybrané datum z kalendáře. Pokud vše proběhlo vpořádku, bude v kalendáři i v textovém poli nové datum, pokud ne, zůstane v textovém poli původní nezměněné datum z kalendáře a bude viditelné chybové hlášení validátoru.

Datum při finálním zpracování v aplikaci pak v každém případě dostáváme jako vlastnost kalendáře SelectedDate typu DateTime (v našem příkladu tedy Calendar1.SelectedDate). Prvek kalendáře umí vybírat (volit) i více dnů najednou (přístupné jsou pak v kolekci SelectedDates) v závislosti na nastavení SelectionMode. Alternativní volba více dní pomocí textového pole je také možná – zpracování je ale trochu komplikovanější v závislosti na tom, zda chceme volit dny jednotlivě nebo najednou celý týden či měsíc, a v naší ukázce není s tímto použitím kalendáře počítáno.

Aplikaci můžeme samozřejmě doplnit o různé kontroly rozsahu dat, například nepovolit zvolit datum starší než aktuální. K tomu použijeme obsloužení událostí, které manipulace s kalendářem vyvolává. Významná je zejména SelectionChanged, kterou se hodí použít pro kontrolu, zda zvolené datum není mimo rozsah. Z dalších bych upozornil ještě na VisibleMonthChanged, kde můžeme například omezit výběr měsíce jen v určitém intervalu – bude-li měsíc viditelného data vyšší než povolený, nastavíme viditelné datum v kalendáři na nejvyšší povolené datum.

Pro hromadné použití ve více stránkách nebo aplikacích by se hodilo jej přepsat jako user control nebo server control, tento článek má však za cíl hlavně ukázat možnosti alternativního zpřístupnění ovládacích prvků a jak je bez obav používat i tam, kde by to jinak nebylo možné.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět