Gossip: Chas 'n' Dave to headline rock festival

Put this in your diary and smoke it

n: smd_calendar | v: 0.42c | d: 2301 | f: /

Plugin documentation follows this short message from our sponsor ;-)

If you like my code and deem it worthy, feel free to show your appreciation with something from my UK Amazon wish list (or US) or donate to the Stef Dawson community coding pot by following the Donate button below to PayPal. Thanks!

Plugin list buttonDownload buttonCompressed download button

smd_calendar

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

Features

  • Full/mini cal by month, with optional iso week
  • Nav: next/prev month or month/year dropdown. Year range can be from first/last article or +/- N years in either direction
  • One article = one event, native to Textpattern: Posted date = the date it appears in the calendar (unless overridden)
  • Filter events by category / section / author / status / time or expiry
  • Custom field to specify event frequency (1 week / 10 days / 3 months / etc)
  • Custom fields for in/exclusions (a list of dates on which that event is (re)scheduled/cancelled/omitted)
  • Multi-day spanned events based on the article’s expiry
  • Display future, expired or sticky events
  • Holidays on a per-calendar basis
  • Each event can be passed to a form/container so you can build it your way. Spanned and/or recurring events can be sent to a separate form. Or send the entire cell to a form
  • Conditional tests for flags and dates so you can build your own logic
  • Table-, row-, cell-, and event-level classes for indicating different scenarios; custom classes can be defined
  • Tags to display recurring events ; event/calendar characteristics ; or the current date/time

Author / credits

Stef Dawson. Jointly funded by generous donators: mrdale, woof, jakob, renobird and joebaich. Based originally on mdp_calendar. All props to the original author, and of course the class upon which the calendar is based. And not forgetting our awesome Textpattern devs who continue to push this CMS to the stars.

Installation / Uninstallation

Requires Textpattern 4.0.7+

Download the plugin from either textpattern.org, or the software page, paste the code into the Textpattern Admin -> Plugins pane, install and enable the plugin. 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 with each cell containing one or more events. Before diving into the tags there’s a little bit of nomenclature to grasp:

  • calid : you may put more than one calendar on a page: each can be uniquely referenced with a calendar ID
  • cell : a specific day on the calendar in a particular month/year
  • event : an article. It’s best to use a dedicated section for events to keep things neater, but you can display events from more than one section if you wish. 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
  • 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 (hols)
  • event flag : each cell can contain one or more events. Events can either be standard, they can recur, they can span more than one day (multi), dates can be unscheduled or omitted (cancel / omit) from the calendar, or extra dates can be added
  • class level : (explored in the classlevels attribute). Each flagged cell can be given a CSS class based on its flag name(s). The class names are simply each flag name prefixed with the value given in the classprefixes attribute. Such classes:
    • appear in a cell, so you can style the whole cell
    • appear on each event, so you can style particular types of event
    • may be ‘copied’ from the event to the cell itself, so you can style the whole cell based on the events it contains

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.

It’s also worth bearing in mind the date caveats that may well bite you.

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 don’t need the ?month or ?year because they can only occur monthly, and will only show the event on the given first/last 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 reaching 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 are then just 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.

If you run a theatre web site that has a 3-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.

Notes:

  • 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 exclusive on any date (e.g. 2009-Mar-10+ => 2009-Mar-15 is illegal)

Holidays

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. Note that events without a year occur on the same date every year, whereas ones with a year will only occur on that specific date.

Once your dates are defined you 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 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.

<txp:smd_calendar />

Put this tag wherever you want your calendar to appear. Use the following attributes to control its output and use the style attributes to determine how to apply styles to the various events and cells.

Main attributes

  • size : calendar size, large or small. Functionally there isn’t much between them. Default: large
  • time : show past, future, or any event. Default: any
  • expired : hide (0) or show (1) expired events. Leave blank to use the Textpattern Advanced Pref ‘Publish expired articles’
  • firstday : the 1st day of the week to show in the calendar. 0=Sunday, 1=Monday … 6=Saturday. Default: 0
  • dayformat : the way in which the day names are rendered. ABBR (the default) shows the days as Mon, Tue, Wed, etc or FULL renders their full names. Alternatively, supply any valid strftime() codes to use that instead. Locale-specific names are returned.
    You can hard-code your own day names; write each item as a comma separated list surrounded by curly brackets. If you wanted two-letter German week days you could use: dayformat="{So,Mo,Di,Mi,Do,Fr,Sa}". The first day in the list must represent Sunday or things will break
  • monthformat : the way in which the month names are rendered. FULL (the default) shows the full month names or ABBR renders their abbreviated names. Alternatively, supply any valid strftime() codes to use that instead. Locale-specific names are returned.
    You can hard-code your own month names; write each item as a comma separated list surrounded by curly brackets. If you wanted single-letter month names you could use: 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
  • select : use a select dropdown for rapid access to weeks, months or years instead of seeing just the names. Default: unset, but you may make a list from either week / month or year (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. For example: select="week:WEEK#, year:<:>" would render a select list with entries that might look like this: WEEK#15 <2009>
  • selectbtn : by default, the select dropdowns will auto-submit when they are changed. If you prefer a dedicated submit button, give the text you wish to appear on the button here. The button has a fixed class of smd_cal_input
  • isoweeks : 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 replacement codes {week}, {month}, {year} or {isoyear} in your markup to insert the relevant info.
    Example: isoweeks="wk, #{week}" will render ‘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 spec. Default: unset
  • status : events in this list of status are published. Default: live
  • category : filter events by this list of categories. Default: unset
  • section : filter events by this list of sections. Default: unset
  • author : filter events by this list of author login names. Default: unset
  • realname : filter events by this list of author Real Names (note: adds one extra query). Default: unset
  • showall : if your calendar appears on the front page and you have not used the section attribute the calendar only shows events from sections that have their On front page radio button set. Use showall="1" to show all events from all sections on front page calendars
  • id : the HTML ID to apply to the table that holds the calendar. This is the value of the URL variable calid. Default: unset
  • navid : the HTML ID to apply to the prev/next/month/year navigation form. Default: unset
  • navarrow : comma-separated pair of items you want to appear as prev/next arrows in the calendar. Default: &#60;, &#62;
  • month : start the calendar on this month from 1 (January) to 12 (December). 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
  • week : 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
  • year : 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
  • yearwidth : a comma-separated list dictating how many years your calendar spans. The default (0) uses the earliest (posted) event in the section as the earliest year, and the latest (modified or posted, whichever is greater) event as the latest year. You will not be permitted to navigate the calendar outside this range.
    To widen the range for example yearwidth="2,4" will subtract 2 whole years from the earliest event and add 4 whole years to the latest event. If you specify a single number, that value will be used to expand the range equally in both directions.
    If you add ‘c’ to either value the current year is used instead of the earliest or latest event, e.g. yearwidth="2,4c" will subtract 2 years from the earliest event and add 4 whole years to today’s date
  • remap : 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. Rename the w, m, & y variables, for example: remap="w:wk, y:yr"
  • form : use this Textpattern form to process each event. If the 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)
  • spanform : render 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
  • recurform : render recurring events differently to standard events. The first event of a recurring set is not passed to recurform
  • cellform (only on large calendars) : use this 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
  • stepfield : the 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
  • omitfield : the ID (not name) of a field that contains a list of dates on which this event is to be omitted
  • skipfield : the ID (not name) of a field that contains a list of dates on which this event is cancelled
  • extrafield : the 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)
  • extrastrict : any dates in extrafield automatically appear on the calendar, but you may choose to restrict new dates from appearing after the event’s expiry date by setting extrastrict="1". Default: 0
  • showskipped : show (1) or hide (0) cancelled events on the calendar. Default: 0
  • showspanned : show (1) or hide (0) spanned events on the calendar. Default: 1
  • datefields : the IDs (not names) of up to two fields from which posted and expiry date stamps may be given. 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
  • holidays : 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
  • holidayflags : permit certain event flags to be scheduled on holidays. Default: standard but others may be listed as well. Choose from standard, recur or multi
  • 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. Thus, 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. This allows you to always link to a valid article/event. 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). Note that if more than one event occurs in the cell, the link will only be to the first event the plugin finds
  • maintain : keep track of the current state of the URL when navigating the calendar using the next/prev or month/year select lists. Items that you want to preserve should be comma-separated. Choose from calid, section, category, author, article, pg or your own URL variable. Default: calid.
    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. If you wish to maintain state yourself or do something exotic, empty this attribute first to avoid weirdness
  • nameval : add your own name/value pairs to the calendar’s URL. e.g. 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
  • static : 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
  • gmt : currently unused, pending review
  • lang : currently unused, pending review

Style attributes

Once you have tweaked your basic calendar as described above you can style it using these attributes:

  • classlevels : classes can be applied to events, cells, or both. You may also promote (i.e. copy) all event-level classes that occur in a day to the cell level so you can colour the cell based on the events that it contains. Use any of event, cell, or cellplus (for copying unique event classes to the cell). Note you should not use cell and cellplus together because the latter overrides the former. Default: cell, event
  • classprefixes : a 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 : the class name of the calendar table itself. Default: unset
  • rowclass : the class name of each table row. Default: unset
  • cellclass : the class name of each table cell. Default: unset
  • emptyclass : the class name of any cells that don’t contain a day number (i.e. the blank cells at the start and end of a month). Default: empty
  • isoweekclass : the class name of each cell containing an iso week. Default: week
  • navclass : the 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
  • myclass : the 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
  • eventclasses : a comma-separated list of items to add as classes to each event (each prefixed with the event prefix). It defaults to category so it adds the Category1 and 2 names as class identifiers to each event.
    If you wish to extend or alter this, give a list of fields that you want to apply to the event (e.g. 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 returns both Category1 and Category2 (if set); gcat will return the current ‘global’ category (if filtering by category); author returns the author ID (if filtering by author); section gives the current section
  • eventwraptag : the (X)HTML tag, without its brackets, to wrap each event with. Default: span
  • mywraptag : the (X)HTML tag, without its brackets, to wrap around both month + year dropdown select lists and submit button (it wraps the lot, combined). 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.

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 — in addition to your usual markup and Textpattern tags — you may also insert any of the following ‘replacements’ to have the relevant value inserted at that place in the cell:

  • {day} : current day (as a number from 1 to 31)
  • {weekday} : current weekday as a word in the local language, or from your dayformat list
  • {week} : current iso week number
  • {month} : current month (as a number from 1 to 12)
  • {monthname} : month name in the local language, or from your monthformat list
  • {year} : current year (4 digits)
  • {shortyear} : current year (2 digits)
  • {isoyear} : current iso year (4 digits)
  • {shortisoyear} : current iso year (2 digits)
  • {events} : all events for the day
  • {standard} : only standard events
  • {recurfirst} / {recur} : the chosen type of recurring event
  • {allrecur} : all recurring events for the day
  • {multifirst} / {multi} / {multiprev} / {multilast} : the chosen type of multi event
  • {allmulti} : all multi events for the day
  • {cancel} : only cancelled events
  • {extra} : only extra events

Differences between large and small calendars

Not a lot! But there are some subtleties:

  • cellform cannot be used on a small calendar
  • By default, no events are placed in the small calendar. You can add them yourself if you wish because you can use the same form/container mechanism as the large calendar
  • 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

Aside from that they’re pretty much identical.

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.

Attributes

  • flag : the cell or event flag(s) you want to test, each separated by a comma. Choose from: event, standard, recurfirst, recur, multifirst, multilast, multi, multiprev, cancel, omit, extra, hols, today, or the special flag SMD_ANY which will trigger if the cell or event contains any of the above. Default: unset
  • calid : the calendar ID you wish to check for a match. Default: unset
  • year : the year the current cell falls in. Default: unset
  • isoyear : the iso year the current cell falls in. Default: unset
  • month : the month number (1-12) that the current cell falls in. Default: unset
  • week : the iso week number that the current cell falls in. Default: unset
  • day : the day number the current cell falls in. Default: unset
  • logic : whether you want to check if all tests you nominated are true in the current cell (logic="and") or at least one of the tests is true (logic="or"). Default: or

‘And’ logic is good 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 (e.g. day="<15")
  • <= tests if attribute is less than or equal to the given value (e.g. month="<=5")
  • ! tests if attribute is not the given value (e.g. day="!15")

Tag: <txp:smd_cal_info />

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

Attributes

  • type : the type(s) of information you want to return, each separated by a comma. Choose from: flag, calid, (iso)year / month / week / day, s (current section) / category / author (or realname), article (id of the currently viewed article), or 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) but if, say, you wanted category1 to be known as the_cat you could write <txp:smd_cal_info type="catgeory:the_cat" html="1" />. You would then see ?the_cat=<category1 name>
  • join : 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
  • join_prefix : the string you want to put in front of the first item in the returned list. If you do not specify this attribute it defaults to SMD_AUTO which 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
  • html : If set to 1, returns not only the values you specified but their URL variable names as well, giving you the entire string as a valid set of URL parameters which can be added to an anchor. It overrides the join attribute and sets it to an ampersand. Default: 0.
    This attribute 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
  • escape : escape HTML entities such as <, > and & for page validation purposes. Set to escape="" to turn it off. Default: html

Tag: <txp:smd_cal_class />

Inside your 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.

Attributes

  • name : a 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

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.

Attributes

  • format : the way you want the date/time represented. Use any valid strftime() string. Defaults to the date format you set in Basic Prefs
  • now : if you don’t want the time to be, umm, ‘now’ you can state what time ‘now’ is! Use any standard date/time format. Default: the time at which you call the tag.
    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)
  • offset : an offset into the future that you wish to apply to now. e.g. 2 months. See Example 6 for a practical application of this attribute
  • gmt : return either local time (0) according to the time zone set in Basic Prefs, or GMT time (1). Default: 0
  • lang : 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 Textpattern prefs)
  • Tag: <txp:smd_article_event />

    When you create 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 see recurring articles as if they were ‘real’ articles in the database. Inside the tag’s form or container you can use all existing article tags to display any information you like about each ‘virtual’ article.

    Attributes

    • stepfield : same as smd_calendar
    • skipfield : same as smd_calendar
    • omitfield : same as smd_calendar
    • extrafield : same as smd_calendar
    • datefields : same as smd_calendar
    • allspanned : normally, any event that has a start date in the past will be omitted from the list. When dealing with spanned events, you may wish to show remaining days in a Broadway show’s schedule even though the event started some months ago. Set allspanned="1" to do this. Default: 0
    • type : the types of event to display. Default: standard, recur, multi
    • section : restrict the events to a list of sections. Default: unset
    • category : restrict the events to a list of categories. Default: unset
    • author : restrict the events to a list of author login names. Default: unset
    • realname : restrict the events to a list of author Real Names (note: adds one extra query). Default: unset
    • id : restrict the events to a list of article IDs. Default: unset
    • status : restrict the events to this list of article status. Default: live
    • expired : definitively hide (0) or show (1) expired events. Leave blank to use the Textpattern Advanced Preference ‘Publish expired articles’
    • time : only show events in this time frame. Choose from any, future or past. Default: any
    • month : only show events that occur in the given YYYY-mm. Default: unset
    • from : only show events from this start date. Can be any valid date format. Default: unset (i.e. all dates)
    • to : only show events up to this end date. Can be any valid date format. Default: unset (i.e. all dates)
    • sort : order the events by this column. The most useful value is the default: Posted asc
    • form : pass each matching event to the given Textpattern form. Default: unset. Note that using the container overrides this attribute, and if you specify neither a form nor container, you will see a list of article posted dates
    • paging : unlike article_custom, events from the smd_article_event tag may be paged using <txp:older /> and <txp:newer />. 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 so you may need to turn paging on (1) or off (0). Default: 1
    • offset : begin displaying events from this position, instead of from the start of the list of events. Default: 0
    • limit : only 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
    • eventlimit : only show this many events maximum, per event. So 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
    • pageby : esoteric paging feature, identical to <txp:article />. Default: same as limit
    • pgonly : set to 1 to perform the paging action without displaying anything. Probably useless. Default: unset
    • wraptag : the (X)HTML tag without brackets to wrap the list in. Default: unset
    • break : the (X)HTML tag to separate each item with. Default: unset
    • class : the CSS class to apply to the wraptag. Default: unset

    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

    Date gotchas

    If there was one global time zone the world would be simpler. Sadly, we all live in different places and the Internet Beat hasn’t really taken off. Even more sadly, certain people in power decree that twice a year some countries must alter their clocks to Save Daylight.

    Textpattern does its best to shield you from this mayhem by allowing you to specify your locale, time offset, and when DST applies in your time zone (not forgetting the time zone of your server if it happens to be nowhere near you). And therein lies the rub.

    For a calendar system, when you say an event is going to occur at 8pm in six months’ time, pesky Daylight Savings may then be in effect and your event will appear an hour ‘off’ (it may look wrong in the admin interface as well as in your calendar, depending on the settings).

    Also, if your server or your office is relocated and you have to adjust time zone, all your beautifully crafted dates will be shifted. They’re not actually changed in the database unless you edit an article and re-save it, but they appear to have shifted because Textpattern is trying to shield you from time bureaucracy in a world gone mad.

    Unfortunately there is little we can do about this at the moment until the way dates are handled in Textpattern (or the world!) is changed. But there are some settings that you can play with to try and make sense of it all. Namely the gmt attribute in any of Textpattern’s date-based tags such as <txp:posted /> and <txp:expires />. Or try using your own datefields. Sometimes fiddling with that and the time zone/DST flags will help. Other times you’ll get in a right old mess.

    If all that fails, the conditional tag may be able to help you compare dates and apply different attributes depending on the day of the year. Failing that, just use GMT and refuse to observe DST :-)

    Examples

    Example 1

    The beauty of the plugin is that you have the entire arsenal of Textpattern tags available to you if you choose to use a form. 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 Textpattern tags to show as much or as little detail as you like in the calendar cell.

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

    Example 2

    Using the conditional tag you can take action if certain events contain particular flags. This example also show 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:permlink>(RECUR)</txp:permlink>
    <txp:else />
       <txp:permlink><txp:title /></txp:permlink>
       <txp:smd_if_cal flag="multifirst">
          <span class="right">&laquo;--</span>
       </txp:smd_if_cal>
       <txp:smd_if_cal flag="recurfirst">
          <span>One of many...</span>
       </txp:smd_if_cal>
    </txp:smd_if_cal>
    

    And in form multis:

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

    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

    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>
       </span>
    </txp:smd_calendar>
    

    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

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

    That lists the next 5 upcoming — recurring — events, plus any standard and spanned events, formatting them as a definition list. 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 display the ‘real’ article when clicked. If you wanted to allow people to book an event on your individual article, try this:

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

    With some cunning you could even add the ‘virtual’ date that they chose in your original 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 for the vistor.

    Example 5

    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:

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

    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

    Using the now and offset attributes of <txp:smd_cal_now /> you can 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">
    <li><txp:permlink><b><txp:title/></b></txp:permlink></li>
    </txp:smd_article_event>
    

    Experimental software

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

    Legacy software

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

    Stef's insanity

    Stef demonstrates there isn't much hope for humanity