calendar

An article by Gaspard Bucher

Display a calendar.

  1. action
  2. ajax
  3. API
  4. classes
  5. common attributes
  6. conditions
  7. context
  8. dates
    1. calendar
    2. date
    3. now
    4. parse_date
  9. display
  10. forms
  11. i18n
  12. meta
  13. SQLiss
  14. urls

Display a calendar.

  • select query to get elements to display
  • attr date field to filter elements and place them
  • size (large|tiny) changes the way day names are displayed (default “large”)
  • start_day (0-6) week start day (0 = Sunday)
  • type (month|week) full month / single week (default “month”)
  • tz timezone name
  • assign_as (role) use calendar to create links
  • used (‘remove’,’warn’) allow removing links to other resource eventually with a warning
  • split_hours split day at these hours and execute loop for each part

The calendar shows the current month/week around the contextual date, either set by the “date” parameter or by using main date.

Full example

<div do='calendar' attr='date' select='posts where #{cal_start} <= date and date < #{cal_end} in project order by date asc, title asc'>
  <h3 do='header'>
    <r:link date='date.advance(:months =&gt; -1)' t='img_prev_page'/>
    <r:date format='%B'/>
    <r:link date='date.advance(:months =&gt; 1)' t='img_next_page'/>
  </h3>
  <r:cell>
    <span do='date' format='%e'/>
    <ol>
      <li do='each' do='link' eval='title.limit(10)'/>
    </ol>
    <r:else do='date' format='%d'/>
  </r:cell>
</div>

The content of the ‘cell’ block is executed for each cell in the calendar with the list of events for the given day. The “else” clause is executed if there is no event.

Short example

<div do='calendar' attr='date' select='posts where #{cal_start} <= date and date < #{cal_end} in project order by date asc, title asc'/>

This example produces the same results as the full example (uses some default zafu).

Building query

When creating the query for elements, you should use “cal_start” and “cal_end” dates. These will map the whole interval of shown dates (including days in previous/next month). The query should not include the last date:

posts where #{cal_start} <= date and date < #{cal_end} in project

“date” in cell

When the block is executed for each cell in the calendar, the “date” variable is set to the cell’s date. Please note that this is an UTC date representing the beginning of the day in the given timezone. This is NOT the time without hours/minutes and seconds.

For example, if the timezone is “Asia/Jakarta” (UTC+7). The “date” for the 21st of April 2011 would be “2011-04-20 17:00”. Since date formating is timezone aware, if you show the date with <r:date format='%d %H:%M'/>, you will get the expected “21 00:00”.

All dates in Zena are Time objects representing an UTC value. This is true for the elements fetched by the query and for the “date” in the cell.

Because “date” refers to the cell’s date, if you have an attribute called “date”, you need to use <r:show attr='date' format='%k'/> to display the event time for example. You should also use “this.date” in a “do” block for the same reason.

Timezone support

The calendar displays and fetches events for a specific timezone. The default is to use the visitor’s timezone but this can be overwritten with the “tz” parameter.

<div do='calendar' attr='date' tz='Asia/Jakarta' select='posts where #{cal_start} <= date and date < #{cal_end} in project'/>

public event

When showing dates for a public event, it is a good practice to display the timezone and to fix it either for the whole page or section with default (best method) or by using the “tz” parameter on the calendar.

Zena is clever enough to propagate the timezone setting to the calendar block so you do not have to set it on <r:show>, <r:link> and <span do='date'/> methods, but if you use “strftime”, you have to pass “tz” as timezone:

<b do='date.strftime("%e", tz)'/>

Ajax

Since fast loading calendars are a common need, here is a zafu snippet to create a calendar with Ajax based month navigation:

<div do='block' name='cal' do='calendar' attr='date' select='posts where #{cal_start} <= date and date < #{cal_end}'>
  <h3 do='header'>
    <r:link date='#{date.advance(:months =&gt; -1).strftime("%Y-%m-%d", tz)}' update='cal' t='img_prev_page'/>
    <r:date format='%B %Y'/>
    <r:link date='#{date.advance(:months =&gt; 1).strftime("%Y-%m-%d", tz)}' update='cal' t='img_next_page'/>
  </h3>
</div>