n: smd_calendar | v: 0.56 | f: /

Documentation for the Textpattern plugin smd_calendar by Stef Dawson follows this short message from our sponsor ;-)

Plugin list button Plugin download button Compressed plugin download button


Render a calendar with one or more articles as events on each day. Useful for gig guides, “what’s on” or scheduling apps.


  • Full-size / mini calendar by month, with ISO week support
  • Nav: next/prev month or month/year dropdown. Year range can be from first/last article or +/- N years
  • One article = one event, native to TXP: posted date = the date it appears in the calendar (overrideable)
  • Filter events by cat / section / author / status / time / expiry
  • Specify event frequency in custom field (1 week / 10 days / 3 months / etc)
  • Custom fields for in/exclusions (dates on which an event is (re)scheduled/cancelled/omitted)
  • Multi-day spanned events based on article expiry
  • Display future, expired or sticky events
  • Holidays per-calendar
  • Pass each event to a form/container. Spanned and/or recurring events can be sent to a separate form. Cell format also customisable
  • Conditional tests for flags and dates so you can build your own logic
  • Table-, row-, cell-, and event-level classes for indicating different scenarios
  • Tags to display recurring events; event/calendar characteristics; or the current date/time

Installation / Uninstallation

Requires Textpattern 4.4.1+

Download the plugin from either, or the software page, paste the code into the TXP Admin->Plugins pane, install and enable the plugin. Create any needed custom fields. Visit the forum thread for more info or to report on the success or otherwise of the plugin.

To uninstall, delete from the Admin->Plugins page.

Naming convention

The core of the plugin is the smd_calendar tag, which renders a standard calendar. Each cell contains one or more events that occur on that day. Before diving into the tags here are the basics:

  • *calid% : you may put more than one calendar on a page: each can be uniquely referenced with a calendar ID so they may be controlled independently
  • *event% : an article. Any article written in the given section(s) will appear on the calendar as long as its expiry hasn’t been met. More than one event may appear in each cell
  • *event flag% : events can either be standard, they can recur, they can span multiple days, dates can be unscheduled or omitted from the calendar, or extra dates can be added
  • *cell flag% : a series of flags are used to label each cell according to what it contains. Cells can either be empty (i.e. no date: the filler cells at the start/end of the month), they can be a regular day (no flag), they can contain an event, or may be a holiday

Flags provide information about the cell / event — and can be tested with the conditional tag — while the corresponding class names are just there for your CSS use.

When assigned as classes, flags always take the ‘class’ prefix (i.e. the 1st item given in smd_calendar’s classprefixes attribute) — whether they appear at the event or cell levels. The only classes that take the optional 2nd ‘event’ prefix are the fields you specify in the eventclasses attribute.

Standard cells and events

The following cumulative naming rules apply:

  • Normal (day) cells don’t have a class assigned to them unless you specify one with cellclass
  • Any cell that contains an event (of any type) is flagged as an event
  • Any cell that falls on a holiday is given the flag hols
  • The current day is given the flag today

A single event (aka article) with a Posted date will be flagged standard, unless it recurs or spans more than one day.

Recurring events

If you have nominated a field as your stepfield you may enter a comma-separated list of frequencies at which the event is to repeat. The format of the repetition is number interval, e.g. 4 weeks or 10 days or 6 months. The plugin will do its best to figure out what you mean. See date input formats for more.

A few points:

  • second tuesday will show an event every 2nd Tuesday from the start date (i.e. fortnightly)
  • second tuesday ?month ?year will substitute the current month and year in first, and then calculate the date, resulting in the event only recurring on the 2nd Tuesday of each month. You must use both ?month and ?year if you choose this type of date or your event won’t appear
  • 20 ?month will show the event on the 20th of every month
  • things like first thursday or last friday or this tuesday don’t need the ?month or ?year because they can only occur monthly, and will only show the event on the given day of the month

If you can find a use for it, you may specify multiple frequencies, for example 3 days, 1 week. That means you would see the event on the 1st day, then the 3rd, 6th, 7th, 9th, 12th, 14th, 15th, 18th, 21st, 24th… days thereafter. Note that the event only occurs once on the 21st day even though the two frequencies clash.

Recur rules:

  • The repetition will continue forever1 unless you specify an expiry time
  • The very first event of a recurring set will be flagged with recurfirst
  • Each following cell that contains a recurring event will be flagged with recur
  • Both flags are applied to the event as classes using the class prefix
  • Repeated events may be cancelled or omitted on a per-date basis

1 ‘forever’ is limited to 99999 recurrences per event, or 274 years’ worth of daily events. Either UNIX will run out of dates or PHP will run out of memory long before you reach this limit :-)

Multi-day (spanned) events

Any event that has:

  • a start date
  • an expiry date that is a day or more later than the start date, and
  • does not have any repetition in its stepfield

is flagged as a multi. By default the first event is displayed in full and each ‘continuation’ event is shown only as a right arrow in subsequent cells. Events may span months or years and the plugin figures everything out using flag rules:

  • The first cell of a spanned set is multifirst
  • The last cell is multilast
  • Every other cell is a multi except if the event rolls over into the next month. In that case, the entry on the 1st of the month is a multiprev to indicate it belongs to a previous event
  • If the 1st day of the month is the last day of the event, the multiprev is dropped in favour of multilast

Switch off spanning completely with showspanned="0". Events that have an expiry then become standard events.

‘Continuation’ cells may be processed with a separate form (spanform). If you choose not to use a spanform, the standard form or container will be used and you will have to distinguish between the different multi flags yourself using the conditional tag.

You can also cancel or omit days of a spanned event in the same manner as you do with recurring events, except you cannot cancel the first day; you should move the event start date and apologise!

Cancelling and omitting events

Plans change and you may find that a gig has to be cancelled. Perhaps you advertise a weekly boot fair but the field is waterlogged one week. No problem: nominate a skipfield in your smd_calendar tag and enter the date of the cancelled event.

Or you might run a theatre web site that has a three-week production performance on weeknights only. Instead of setting up three separate events — one for each week — nominate an omitfield and list the dates on which the performance does not air. Omitted dates will not, under any circumstances, appear on the calendar and they override cancelled dates/holidays. If cellplus mode is used, you will however see a cell flag labelled omit (plus class prefix) in case you do wish to style such cells.

To specify the dates in either field, use any acceptable date format, but derivatives of dd-monthname-yyyy or monthname-dd-yyyy are the most unambiguous to avoid problems (e.g. is 1/5 Jan 5th or May 1st). You can specify as many cancellations or omissions as you like; comma-separate each one. You may also specify ranges of dates to omit/cancel by using the notation start date => end date.

By default, cancelled events will not appear on the calendar. If you use showskipped="1" the event will appear in the cell as normal and the cancel flag will apply to the event (and cell if you choose) so you may detect/style it.

Extra dates

When events are cancelled you may elect to reschedule the event on a different date instead of having to create a new event with identical details. Use the extrafield to simply add it to the calendar on its new day. You might also use this feature if you have a recurring event on the 1st of every month but for some reason you have to move one of the events a day or two. Simply cancel the offending date and add the new date using extrafield.

The list of dates can be in any standard date format (including date ranges using start => end). They will be added to the calendar and flagged as extra. Also see the extrastrict attribute.

If your original event spans more than one day, you may elect to schedule the entire block again. Add a ‘+’ after any date you wish to repeat in its entirety, e.g. 2009-Mar-12+, 2009-Jun-18+, 2009-Feb-19 would copy the entire event block to March and June, but only the 1st date to Feb 19th. Events/cells are flagged as both extra and multi where applicable.


  • if you schedule an extra event on a day that already contains the same event (perhaps on a spanned or recurring date) you may see two identical events on the same day. Try and avoid this, unless it’s your intended behaviour
  • date ranges and the ‘+’ syntax are mutually exlcusive on any date (e.g. 2009-Mar-10+ => 2009-Mar-15 is illegal)


Public holidays need not be a nuisance to your events. Give the plugin a holiday list and it’ll make sure any recurring or multi events are not scheduled on those days. Standard one-off events are permitted by default because you might want to organise a special event on that day, though you can forbid those too if you wish.

The list of dates you specify can be entered directly in a string in the holidays attribute or in a <txp:variable />:

<txp:variable name="nat_hols"
     value="Dec 25, 26 Dec, 31/Dec, Jan-1,
        May 4 2009, 2009-08-31" />
<txp:smd_calendar holidays="txpvar:nat_hols" />

That list shows some of the variety and breadth of formats the plugin allows. There are more. Note that the events without a year occur on the same date every year, whereas the ones with a year will only occur on that specific date.

Once your dates are defined you can control which events are allowed to fall on those dates via holidayflags. Combining that attribute, showspanned, showskipped and the forms — along with the conditional tag — can give a wide variety of ways to display events and cells.

Holiday cells are given the flag hols, and any event that is not specifically permitted by the holidayflags is automatically assigned a cancel flag if it falls on one of the days. Omitted dates will, however, cause the cancel flag to be removed.

Tag: <txp:smd_calendar>

Put this tag wherever you want your calendar to appear. Use the following attributes to control its output. The default value is unset unless stated otherwise.

Display attributes

Calendar size. Options:
The small is more geared towards a minical, although functionally there isn’t much between them
Default: large
First day of the week to show in the calendar. 0=Sunday, 1=Monday … 6=Saturday
Default: 0
Way in which day names are rendered. Options:
ABBR shows abbreviated day names; Mon, Tue, Wed, etc
FULL uses full names
Any valid strftime() codes. Locale-specific names are returned
A comma-separated list of custom day names surrounded by {} brackets
Example, for two-letter German weekdays: dayformat="{So,Mo,Di,Mi,Do,Fr,Sa}". The first day in the list must represent Sunday or things will break
Default: ABBR
Way in which the month names are rendered. Options:
FULL shows full month names
ABBR uses abbreviated names
Any valid strftime() codes. Locale-specific names are returned
A comma-separated list of custom month names surrounded by {} brackets
Example, for single-letter month names: monthformat="{J,F,M,A,M,J,J,A,S,O,N,D}". The first month in the list must represent January or things will break
Default: FULL
Use a select dropdown for rapid access to weeks, months or years instead of fixed names. Choose one or more of:
Note: week and month are mutually exclusive
You may also specify up to two extra arguments, separated by : chars. These add text in front of and behind the week/month/year, respectively
Example: select="week:WEEK#, year:<:>" displays a select list with entries like this: WEEK#15 <2009>
Add a dedicated submit button to week/month/year select lists. Specify the text you wish to appear on the button. It will have the CSS class name smd_cal_input
Default: unset (i.e. auto-submit on select list change)
Show ISO week numbers as a column at the start of the calendar. Any text in this attribute enables the feature, and becomes the heading of the ISO week column
You may change the default week number in each cell by adding a comma and some text; whatever you enter will be put in each ISO week cell. Use the following replacement codes in your markup to insert the relevant info:
Example: isoweeks="wk, #{week}" will put ‘wk’ at the top of the column and something like #24, #25, #26… beneath it. If the first item is omitted, there will be no column heading
Note that if this feature is enabled, firstday will be forced to start on a Monday as governed by the ISO specification
Comma-separated pair of items you want to appear as prev/next arrows in the calendar
Default: &#60;, &#62;
Add a caption to the calendar
Add a summary to the calendar

Filter attributes

Which events to display. Options:
Default: any
Hide or show expired events. Options:
unset (use the TXP Preference ‘Publish expired articles’)
0 (hide)
1 (show)
Events in this status list are published on the calendar. Options:
Default: live
Filter events by this list of categories. Use SMD_UNCAT for uncategorised events
Consider sub-categories. Choose a numeric nesting level to consider, or the word all
Filter events by this list of sections
Filter events by this list of author login names
Filter events by this list of author Real Names (note: may add one extra query)
If your calendar appears on the front page of your site and you have not used the section attribute, then:
0: only shows events from sections marked with On front page
1: shows all events from all sections
Default: 0
Start the calendar on this month from 1 (Jan) to 12 (Dec). Normal calendar navigation overrides this value
If static is used, this month becomes the only one you may view
If unset, and no m= value appears on the URL line, the current month is used
Start the calendar during the month containing this ISO week (from 1 to 53)
Ignored if static or one of the calendar navigation controls is used
If a w= value appears on the URL line, the given week overrides any month value
Start the calendar at this 4-digit year. Normal calendar navigation overrides this value
If static is used, this year becomes the only one you may view
If unset, and no y= value appears on the URL line, the current year is used
Force the calendar to be fixed to one month/year (i.e. no navigation). Month and year decided by attributes month and year or, if omitted, the current date will be used

Form attributes

Use the given TXP form to process each event
If the smd_calendar tag is used as a container it will be used in preference to the form
If neither are used, a default is used (Large: hyperlinked article title, Small: empty event)
Display spanned events differently to standard events; they usually use the same form/container
If neither are specified, a right-arrow will be used to indicate continuation of the previous day’s event
Note: the first day of a spanned set is not passed to the spanform; only continuation cells are passed to it
Display recurring events differently to standard events
Note: the first event of a recurring set is not passed to recurform
cellform (only on large calendars)
Use if you wish to build each cell entirely from scratch
There are some replacement variables you can use to insert dynamic pieces of information in your cells
Note: you cannot use TXP article or plugin tags in the Form
Use if you wish to build the header yourself
There are some replacement variables you can use to insert dynamic pieces of information in your header

Field-based attributes (custom fields or other article fields)

ID of a field within which an event may be told to repeat
Note: it is the field’s ID not its name, so for custom fields you must use custom_1 or custom_2 etc
Without this attribute, no recurring events may be defined
ID (not name) of a field that contains a list of dates on which this event is to be omitted
ID (not name) of a field that contains a list of dates on which this event is cancelled
ID (not name) of a field from which a list of additional event dates may be given; the same event details will be copied to the new day(s)
Control visibility of extra dates on the calendar. Options:
0: extrafield dates automatically appear on the calendar
1: restrict new dates from appearing after the event’s expiry date
Default: 0
Control visibility of cancelled events on the calendar. Options:
0 (hide)
1 (show)
Default: 0
Control visibility of spanned events on the calendar. Options:
0 (hide)
1 (show)
Default: 1
IDs (not names) of up to two fields from which posted and expiry date stamps may be read. Comma-separate the field names; the first will be used as the Posted date and the second as the Expiry
If either is omitted or mangled, the article’s “real” posted/expiry date will be used instead
If the expiry date occurs before the start date, your datefields will be ignored and a warning will be issued

Config attributes

List of dates that are decreed as holidays
May be deferred to a <txp:variable />, in which case define your list in a named variable and use holidays="txpvar:my_var_name" to read them into the plugin
Permit certain event flags to be scheduled on holidays. List one or more of:
Default: standard
HTML ID to apply to the table that holds the calendar. This becomes the value of the URL variable calid
Use this if you have more than one calendar on a page and wish to control them separately via the URL vars
HTML ID to apply to the prev/next/month/year navigation form
A comma-separated list that specifies how many years your calendar spans. Visitors will not be permitted to navigate (next/prev) the calendar outside this range. Options:
0: use the earliest (posted) event as the earliest year, and the latest (modified or posted, whichever is greater) event as the latest year
any other single number expands the range equally in past & future directions
any pair of numbers subtracts the first from the earliest event and adds the second number of whole years to the latest event
adding c to either value causes the current year to be used instead of the earliest or latest event
Example: yearwidth="2,4c" subtracts 2 years from the earliest event and adds 4 whole years to today’s date
Default: 0
When dealing with multiple calendars on a page it is often beneficial to use different names for w=, m= or y= in the URL so you can navigate calendars individually. This attribute enables you to rename the w, m, & y variable to any name specified after a colon (:)
Example: remap="w:wk, y:yr"
linkposted (only on small calendars)
Each cell that contains an event flag of the given type(s) will have its day number linked to the event’s true start date instead of the cell’s date. This allows you to always link to a valid article/event
Note that if more than one event occurs in the cell, the link will only be to the first event the plugin finds
Example: if you have a weekly event that starts on the 20th December 2008, setting linkposted="recur" will cause the link to be date=2008-12-20 every week. Without linkposted, the dates would be 2008-12-20, 2008-12-27, 2009-01-03, and so on
Default: recur, multi, multiprev, multilast (i.e. any recurring or spanned event)
Keep track of this comma-separated list of variables in the URL when navigating the calendar using the next/prev or month/year select lists. If you wish to maintain state yourself or do something exotic, empty this attribute first to avoid weirdness. Options:
any other URL variable of your choosing
Example: use maintain="section, article, calid" if you have an individual article page with a calendar in a sidebar, so the currently viewed article will remain in view when changing date
Default: calid
Add your own name/value pairs to the calendar’s URL.
Example: nameval="tracker=mycal, keep=1" would add ?tracker=mycal&keep=1 to the URL. Useful if you want to maintain some values which you can’t add to the URL on page load
Delimiter between each event.
Default: comma

Style attributes

Each flagged event can be given a CSS class based on its flag name(s). Classes can be applied to events, cells, or both. You may also promote (i.e. copy) all event classes that occur in a day to the cell itself so you can style the cell based on the events it contains. Options:
cellplus (for copying unique event classes to the containing cell)
Note you should not use cell and cellplus together because the latter overrides the former
Default: cell, event
Comma-separated list of up to two prefixes to apply to your class names. The first prefix is applied to cell-level classes (and flags) and the second prefix is applied to event classes (see eventclasses)
If you only specify one prefix, it will be used for both. If you use classprefixes="" then no prefixes will be used at all
Default: smd_cal_, smd_cal_ev_
Class name of the calendar table itself
Default: unset
Class name of each table row
Default: unset
Class name of each table cell
Default: unset
Class name of any cells that don’t contain a day number (i.e. the blank cells at the start & end of a month)
Default: empty
Class name of each cell containing an ISO week
Default: week
Class name of the prev/next month nav arrows. If a comma-separated list is used, the first item will be the name of the class of the previous month, the 2nd item of the next month. If a single value is used, both class names will be the same
Default: navprev, navnext
Class name of both the month and year in the calendar header (either the <span> or <select> tags). If mywraptag is used, the class is applied to the wraptag instead
Default: unset
Comma-separated list of items to add as classes to each event. Each are prefixed with the event prefix
Example: eventclasses="ID, AuthorID, custom_5" would add three classes to each event corresponding to the event’s ID, its author (login) name and the contents of custom_5
If you use cellplus, these classes will be copied to the cell level. Some special names exist: category adds both Category1 and Category2 (if set); gcat will add the current ‘global’ category (if filtering by category); author adds the author ID (if filtering by author); section adds the current section
Default: category
HTML tag, without brackets, to wrap each event with
Default: span
HTML tag, without brackets, to wrap around both month + year dropdown select lists and submit button
Default: unset

Using a cellform with replacement variables

If you don’t like the layout of the default cell, you can do it yourself with the cellform attribute. The cells are generated last, so by the time the plugin reaches this attribute, all events have already been processed by any of your forms/containers. Thus you can’t use TXP article or plugin tags.

To build your own cells you often need information such as the events that fall on a particular day; or the week, month or day numbers, etc. So you may also insert any of the following replacements to have the relevant value inserted among your markup:

  • {day} / {dayzeros} : day of the week (1-31 / 01-31)
  • {weekday} : weekday in the local language, or from your dayformat list
  • {weekdayfull} or {weekdayabbr} : weekday in the local language
  • {week} : ISO week number (01-53)
  • {month} / {monthzeros} : month number (1-12 / 01-12)
  • {monthname} : month name in the local language, or from your monthformat list
  • {monthnamefull} or {monthnameabbr} : month name in the local language
  • {year} : 4-digit year
  • {shortyear} : 2-digit year
  • {isoyear} : 4 digit ISO year
  • {shortisoyear} : 2 digit ISO year
  • {evid} : event (article) ID
  • {events} : all events for the day
  • {standard} : only standard events
  • {recurfirst} / {recur} : various recurring events
  • {allrecur} : all recurring events for the day
  • {multifirst} / {multi} / {multiprev} / {multilast} : various multi events
  • {allmulti} : all multi events for the day
  • {cancel} : only cancelled events
  • {extra} : only extra events

Using a headerform

You can create your own header if you wish and employ any of the following replacements in the markup:

  • {firstday} : current weekday (as a number from 0 to 6)
  • {daynames} : comma-separated day names
  • {isoweekhead} : ISO week heading
  • {week} : ISO week
  • {month} : month
  • {year} : year
  • {isoyear} : ISO year

Differences between large and small calendars

  • cellform cannot be used on a small calendar
  • By default, no event descriptions are placed in the small calendar. You can add them yourself if you wish using a form/container
  • The only thing rendered in a small calendar cell is the hyperlinked date and any flags so you can style the boxes
  • classlevels are ignored: everything is automatically assigned at the cell level (i.e. cellplus is set)
  • eventclasses are still honoured if you wish to use a form to process them yourself
  • The small calendar outputs year-month-day-title or messy permlinks only

Tag: <txp:smd_if_cal>

This conditional tag allows you — inside your container/forms — to test certain conditions of the current event/cell. For enhanced conditional checking (perhaps in conjunction with smd_cal_now), consider the smd_if plugin. The default value is unset unless stated otherwise.


The cell or event flag(s) you want to test, each separated by a comma. List one or more of:
SMD_ANY (will trigger if the cell or event contains any of the above)
The calendar ID you wish to check for a match
The year the current cell falls in
The ISO year the current cell falls in
The month number (1-12) that the current cell falls in
The ISO week number that the current cell falls in
The day number the current cell falls in
Method of combining the nominated tests. Options:
or: tag will trigger if at least one of the tests is true
and: tag will only trigger if all the tests are true
Default: or

‘And’ logic is useful for checking if the cell is of a certain type AND is later than the 15th of the month, for example.

Rudimentary comparators can be applied to the (iso)year, month, week and day attributes. Normally the value you supply will be tested for an exact match but if you prefix it with one of the following character sequences then the behaviour changes:

  • > tests if attribute is greater than the given value (e.g. year=">2008")
  • >= tests if attribute is greater than or equal to the given value (e.g. month=">=7")
  • < tests if attribute is less than the given value
  • <= tests if attribute is less than or equal to the given value
  • ! tests if attribute is not the given value (e.g. day="!15")

Tag: <txp:smd_cal_info>

Inside your smd_calendar container/forms, use this tag to output certain information about the current event.


Comma-separated list of types of information you want to display. Options:
s (current section)
article (id of the currently viewed article)
any other article variable such as section (the current article’s section), authorid, article_image, etc
If using the html attribute, you may optionally specify the name you want the variable to appear as in the URL string. The variables all take on sensible defaults (e.g. ‘section’ becomes ?s=<section name>, ‘category1’ becomes ?c=<category1 name>, etc).
Example: <txp:smd_cal_info type="catgeory:the_cat" html="1" /> means you would see ?the_cat=<category1 name> in the URL
Default: flag
The characters you want to use to separate each item you asked for. Note it is the characters between each item so the very first entry will not have the join in front of it (see join_prefix)
Default: a space
The string you want to put in front of the first item in the returned list. If you do not specify this attribute it tries to be clever:
If using type="flag" the join_prefix is set to the same as join. Thus with join=" cal_" you might get cal_multi cal_today cal_hols
If using html="1" the join_prefix is set to a question mark, thus: type="month,year,category" html="1" might render ?m=12&y=2008&c=gigs, which can be put straight on the end of an anchor
Default: SMD_AUTO
Control in which format the information is returned. Options:
0: return items verbatim
1: return items as a URL parameter string. This is useful if you are building your own content inside each cell via a form and wish to maintain the current search environment. If you allow people to filter events by category or author you can use this to return the ‘current’ state of certain variables so you can pass them to the next page and maintain state
Note: Setting this attribute to 1 overrides the join attribute and sets it to an ampersand
Default: 0
Escape HTML entities such as <, > and & for page validation purposes. Use escape="" to turn this off
Default: html

Tag: <txp:smd_cal_class>

Inside your smd_calendat container/forms, use this tag to add a list of classes to the current cell/event. Very useful if building cells yourself because inside a conditional tag you could add particular class names based on some value in a cell.


Comma-separated list of classnames to add to the current cell/event. These are not subject to any classprefixes so will always appear exactly as you write them
Default: unset

Tag: <txp:smd_cal_now>

Return the current date/time, formatted however you please. Useful for extracting parts of the current system timestamp to compare things via other conditional plugins or the <txp:smd_if_cal> tag.


The way you want the date/time represented. Use any valid strftime() string. Has full Windows support, even for those values where strftime() indicates otherwise
Default: the date format set in Basic Preferences.
If you don’t want the time to be ‘now’ you can state what time ‘now’ is! Use any standard date/time format
You may also use the codes ?day, ?month or ?year in your time string which will do one of two things:
replace the codes with the URL parameters d=, m= or y=, if they are being used
use the current day, month or year (i.e. the parts of today’s date)
Default: now! (the time at which you call the tag)
An offset into the future that you wish to apply to now
Example: 2 months. See Example 6 for a practical application of this attribute
Return either:
0: local time according to the time zone set in Basic Prefs
1: GMT time
Default: 0
An ISO language code that formats time strings suitable for the specified language (or locale) as defined by ISO 639
Default: unset (i.e. use the value as stated in TXP prefs)

Tag: <txp:smd_article_event>

When you create recurring events, they really only exist once as a single article; the repetition is a trick. Thus the built-in article tags only show the single, real articles.

This tag — similar in function to <txp:article_custom /> — allows you to list recurring articles as if they were ‘real’ articles in the database. They don’t become real articles, they are just listed as such.

Inside the tag’s form or container you can use all existing article tags to display any information you like about each ‘virtual’ article. The default value is unset unless stated otherwise.

Identical attributes to smd_calendar:


Other attributes

Restrict events to this list of article IDs
Specify your own comma-separated list of custom field clauses to the query. Separate each field from its (optional) operator and clause with a colon (alterable via param_delim).
Example: custom="custom_3:like:Lion%, custom_6:Chessington" would add AND custom_3 like 'Lion%' AND custom_6='Chessington' to the database query.
Alter the separator character(s) between field-clause items in the custom attribute.
Default: colon (:)
Comma-separated list of event types to display. Options:
Default: standard, recur, multi
Control display of spanned events:
0: any event that has a start date in the past will be omitted from the list
1: display remaining days from spanned events that began in the past
Example: use allspanned="1" if you are listing remaining performance dates from a Broadway show’s schedule that started some months ago.
Default: 0
Only show events that occur in the given YYYY-mm
Only show events with Posted dated beginning after this start date. Can be any valid date format
Only show events with Posted dates up to this end date. Can be any valid date format
Order the events by this column (case-sensitive) and sort direction (asc or desc)
Default: Posted asc
Pass each matching event to the given TXP form. Note that using a container overrides this attribute, and if you specify neither a form nor container, you will see a list of article Posted dates
Unlike article_custom, events from the smd_article_event tag may be paged using <txp:older /> and <txp:newer />. But if you wish to show an event list on the same page as a standard article list, the older/newer tags will navigate both lists simultaneously. Under this circumstance you may need to turn paging off (0). Options:
0 (off)
1 (on)
Default: 1
Begin displaying events from this numeric position, instead of from the start of the list of events
Default: 0
Inly show this many events maximum per page, i.e. the number of events to display, whether they come from one ‘real’ article or many
Default: 10
Only show this many events maximum per event
Example: if you have a weekly repeated event that lasts for four months and you set eventlimit="6" you will only see a maximum of 6 events from every article containing repetition. The range (start and end date) is determined by other plugin attributes
Default: 10
Esoteric paging feature, identical to <txp:article />
Default: same as limit
Set to 1 to perform the paging action without displaying anything. Probably useless
The HTML tag, without brackets, to wrap the list in
The HTML tag to separate each item with
The CSS class to apply to the wraptag

The smd_article_event tag process

It is worth noting that this tag executes in 3-phases:

  1. Pre-filter: all events that match type, category, section, author, status, id, and expired are extracted
  2. Time-filter: any “time-based” attributes are then applied to the above list. At this point, any extrafield, stepfield, omitfield, or skipfield are calculated to find repeated dates (up to as many as eventlimit allows or the calculation exceeds the event’s expiry time). The attributes time, month, from, and to are used to refine the filtration here
  3. Output: whatever the previous phases have left behind is subject to any paging, offset and limit you may have specified, then wrapped and displayed

Tag: <txp:smd_event_info>

Identical tag to <txp:smd_calinfo /> but for use inside <txp:smd_article_event />.


Example 1: basic calendar

You have the entire arsenal of TXP tags available to you in a calendar. Thus you can set the article’s start and end dates to the same day and set the start and end times to indicate the start and end of the event. You can then use standard <txp:posted /> or <txp:expires /> tags with various format strings to render the event’s criteria.

Similarly you can use any other TXP tags to show as much or as little detail as you like in the calendar cell.

<txp:smd_calendar section="events">
   Event: <txp:permlink><txp:title /></txp:permlink>
   <br /><txp:excerpt />
<div class="evtime">
   Start: <txp:posted format="%H:%M" />
<div class="evtime">
   End: <txp:expires format="%H:%M" />

Example 2: conditional calendar

Using the conditional tag you can take action if certain events contain particular flags. This example also shows a completely useless manner of employing <txp:smd_cal_now />.

Time is: <txp:smd_cal_now format="%T" />
<txp:smd_calendar form="evform"
     stepfield="custom_3" skipfield="custom_6"
     spanform="multis" />

In form evform:

<txp:smd_if_cal flag="recur">
<txp:else />
   <txp:permlink><txp:title /></txp:permlink>
   <txp:smd_if_cal flag="multifirst">
      <span class="right">&laquo;--</span>
   <txp:smd_if_cal flag="recurfirst">
      <span>One of many...</span>

And in form multis:

<txp:smd_if_cal flag="multi, multiprev">
<txp:smd_if_cal flag="multilast">
      <span class="left">--&raquo;</span> END <txp:title />

Notice that multifirst is tested inside the same form as standard events. This is because only continuation spanned cells are passed to the spanform; the first event of a spanned group is just like any standard event. Similarly, if you had been using recurform the first event of the recurring set would be processed in the usual form/container and every subsequent event would be passed to the dedicated form.

Example 3: classes

You could use the calendar tags to output various pieces of flag information to build your own class names. This example also demonstrates the html attribute of <txp:smd_cal_info /> to build up a query string that is passed along with an event’s category1 when a visitor clicks the anchor.

This allows your site visitors to filter events by category while retaining the ability to show the calendar for the current month/year and section they are viewing instead of dropping back to the current month/year like other calendar systems often do.

<txp:smd_calendar isoweeks="WEEK#"
     yearwidth="0,2" select="year, month"
     stepfield="custom_1" skipfield="custom_2"
     showskipped="1" expired="1">
   <span class="<txp:smd_cal_info join=" cal_" />">
      <txp:permlink><txp:title /></txp:permlink>
      <a href="?c=<txp:category1
         />&<txp:smd_cal_info type="s, year,
         month, calid" html="1" join_prefix=""
         />"><txp:category1 title="1" /></a>

What is also useful about the <txp:smd_cal_info /> tag is that if a particular value is not set it will not be included in the output.

Example 4: upcoming events

List the next 5 upcoming — recurring — events, plus any standard and spanned events, formatting them as a definition list.

<h2>Upcoming Events</h2>
<txp:smd_article_event stepfield="custom_1"
     wraptag="dl" time="future" eventlimit="5">
     <dt><txp:posted format="%B %Y" /></dt>
      <txp:posted />

If you add pagination tags you can flip through all the events; they will be displayed 10 at a time on each page (if you want to keep track of which page you are on as you flip through a calendar that is in a sidebar, add pg to the maintain attribute in your calendar).

Note the hyperlinked title shown here will jump to the ‘real’ article (the first date in the recurring set) when clicked, not to an article with a date matching the recurrence.

If you wanted to allow people to book an event, try this in your hyperlinked individual article:

 <txp:article limit="1">
  <h3><txp:title /></h3>
  <txp:body />
  <p>Please choose a date to book:</p>
  <txp:smd_article_event stepfield="custom_1"
    type="recur" id='<txp:article_id />'>
     value='<txp:posted format="%G-%m-%d"/>'>
      <txp:posted format="%m %d, $G" />

With some cunning you could even add the ‘virtual’ date that they chose in your original smd_article_event list and pass it as a URL variable to your individual article where you could read the value and pre-select the date in the select list for the vistor.

Example 5: iCal synchronisation

How about being able to output your events in iCal format so other people can sync their calendars to yours? Put this in a new Page template in its own Section:

X-WR-CALNAME:Gigs Calendar
PRODID:-//Apple Computer, Inc//iCal 1.5//EN
<txp:smd_article_event form="icsitem" time="any"
section="gigs" limit="1000">
 DTSTART:<txp:posted format="%Y%m%dT%H%i%s" />
 DTEND:<txp:expires format="%Y%m%dT%H%i%s" />
 SUMMARY:<txp:title />

That will output an iCal-formatted gig list (repeated or otherwise). If you got freaky with it and added some conditional logic inside the template you could even read in URL variables and plug them in. Thus you could link to it directly off the calendar itself, pass in the section, category or event info and have a customised iCal stream pumped out of Textpattern.

Thanks to woof for bringing the original David Emery article to my attention.

Example 6: redefining now

Using the now and offset attributes of <txp:smd_cal_now /> you can effectively set ‘now’ to be any time you like and make calculations based on a particular date.

Plugging the ?month and ?year codes in allows you to make <txp:smd_article_event /> track the calendar. So you can automatically show only the events that occur in the month the visitor is browsing via the calendar:

<txp:smd_calendar stepfield="custom_1" />
<h2>Events this month</h2>
<txp:smd_article_event stepfield="custom_1"
     from='<txp:smd_cal_now now="01-?month-?year" />'
     to='<txp:smd_cal_now now="?month-?year"
        offset="1 month" />' time="any" wraptag="ul">

Author / credits

Stef Dawson. Jointly funded by generous donators: mrdale, woof, jakob, renobird and joebaich. Originally based on mdp_calendar. All props to the original author, and of course the class upon which the calendar is based.

Source code

If you’d rather frolic in the raw code halls, you’ll need to step into the view source page.

Legacy software

If, for some inexplicable reason, you need a prior version of a plugin, it can probably be found on the plugin archive page.

Experimental software

If you’re feeling brave, or fancy skateboarding into volcanos, you can test out some of my beta code. It can be found on the plugin beta page.