DataCalendar

The DataCalendar is a combination of DateChooser and DataGrid. Like the DateChooser, the DataCalendar displays a standard calendar with controls to navigate to another month and year. And like the DataGrid, the cells of the DataCalendar display data.

Also similar to the DataGrid, the DataCalendar uses itemRenderers – either the default ones I’ve included with the package, or ones you create. The image below shows an example using custom itemRenderers and skins.

A long time ago I helped a friend of mine who owns a nightclub write an application which lets her booking manager create an online calendar of the bands performing at her nightclub. The central part of this application is the calendar which displays the bands playing each night, along with any notes and ticket information. I wrote all of that using PHP and I’ve been meaning to, over the years, write it again in Flex. The only thing holding me back was the calendar.

The DateChooser is fine to pick dates, but you cannot display anything other than the date in the calendar. The DataGrid is also fine but I needed something a bit more flexible. So I finally sat down, planned it out, and came up with the DataCalendar.

See a demo of DataCalendar here

The demonstration is of the nightclub booking tool. The information is stored in XML files and is available for the months of Dec 2007 through Feb 2008; I haven’t modified the program to create new months, but feel free to experiment with the code on your own.

Screen shot of the BookingTool

View Documentation

In hindsight, you can probably do this with the DataGrid. Once I had it planned I wanted to see it through, but if you wanted to do something similar with the DataGrid, I believe you could.

Source Code

These ZIP files are Flex 3 Beta 3 project archives.

DataCalendar Flex Library. This is the source to the DataCalendar control and supporting classes.
Test Application. This is the source to the test applications, including the BookingTool (above).

DataProvider

To use the DataCalendar you need a special data provider. I had toyed around with using the conventional ArrayCollection and XMLListCollection classes, but the more I thought about how someone would use this control, the more I thought I needed something specialized. When you look at a calendar, what do you see? Dates, right? And wouldn’t it make sense to orient the data to the dates of the calendar?

My first thought was to include the day of the month as one of the fields: {day:18, value:"Tim’s Birthday"}, {day:4, value:"Big Meeting"}, and so forth. The problem with this is that you have to repeatedly search through the collection for the information on a particular day. In this example, the information for the 4th comes after the information for the 18th. I could do a one-time pass and create a mapping, but that seemed like too much work and could have issues with data binding events.

Instead, I created the DataCalendarDataProvider class. The class implements ICollectionView, but it allows data to be assigned by day. For instance:

var januaryData:DataCalendarDataProvider = new DataCalendarDataProvider();
januaryData.addItemAt( 18, {value:"Tim's Birthday});
januaryData.addItemAt( 4, {value:"Big Meeting"});

The DataCalendarDataProvider class allocates 32 slots – slot 0 is not used – so each slot corresponds to a day of the month.

Certain properties such as sort and functions such addItem() do not make sense for a calendar, so those will throw exceptions if used.

Layout

The calendar is a grid of 7 columns and 6 rows (to accomodate those months which require 6 weeks, eg. March 2008). Regardless of the width, the DataCalendar makes all of the week day columns the same size. If you specify an explicit height the DataCalendar also makes all of the week rows the same height. However, if you do not specify a height, then the DataCalendar will allow each week row’s height to be different from the others, using the content of the day cells to determine a week row’s maximum height.

Renderers

I wanted this control to be as flexible as possible, so I gave it the ability to use itemRenderers. There are several renderers you can change:

itemRenderer: This is the renderer for the contents of a day cell. The default (DataCalendarItemRenderer) renderer takes the contents and displays it in a Text field. The BookingTool demonstration uses a complex itemRenderer. You can also add video and audio. Imagine showing the most popular YouTube™ video for each day of the month.
todayRenderer: This renderer displays the indicator for the day cell representing the current date. The default renderer simply displays the DataCalendarTodaySkin.
dayNumberRenderer: This renderer displays the date in the day cell. The default (DataCalendarDayNumberRenderer) displays the numerals for the date in the upper right corner of each day cell.
dayNameRenderer: This renderer displays the name of the day of the week across the top of each week day column. The default is DataCalendarDayNameRenderer.

Skins

I also wanted the control to have a great deal of flexability when it came to its look, so there are also a number of skins you can change:

DataCalendarDayNameSkin: the skin used for the background of the week day names.
DataCalendarDayNumberSkin: the skin used for the background of the dates for each day of the month (day cell).
DataCalendarSkin: the skin used for the background and border of the DataCalendar control.
DataCalendarTodaySkin: the skin used to show the indicator for the current day.

Version 2.0

Of course, once you finish a project you think about things you’d like to add or change. I may never get to this, but I can think of some "enhancement requests":

  • Scrolling like the DataGrid. That is, keep the DataCalendar’s title area and day names fixed in place and just scroll the day cells.
  • Selecting by day of the week. This would allow you to select all of the Mondays, for instance.
  • Adding itemEditor capability. This might make the BookingTool even easier to use.
  • Starting the week on some day other than Sunday. A typical business week begins Monday, for example.
  • Items which span rows or columns. For example, a vacation over a long weekend.

18 Responses to DataCalendar

  1. Steve says:

    Could you clarify the process to edit/update the skins from the included FLAs? The Import Skin Artwork says Flash should use a SWC while Illustrator uses a SWF. Since the project includes a FLA on presumes you used Flash but there’s no SWC and exporting Skins.swc from flash then attempting to import to FB3b3 – finds no symbols to import.

    thx much for such a nice, heavily commented project.

    –steve…
    ————–
    I didn’t use the artwork import feature of FB3 at all. All I did was create a Flash file with symbols in its library and set those symbols to export on the first frame of the SWF. Then I embedded them using Embed syntax.

    So you should not be importing them.

  2. Your “Stack” components, any chance on an update for them allowing for better skinning control?

    Currently I have modified the StackBase.as to use a Button as a header and use the toggle and selected properties. Do you think this is o.k? why do you have a seperate class for the StackHeaderButton and not just use the Button.as?

    Cheers
    Gareth.

  3. Steve says:

    Thankx for the reply Peter….I _thought it was supposed to be that easy…that’s how I tried on the first pass but when it didn’t work I dug thru a few .pdfs (flexbuilder3_sdext_docs_121207-1.pdf) where they document the import.

    In any event…I’ve re-tried your steps…working off the archived files I open Skins.fla in CS3 (v 9.0), double check that ‘Export on 1st frame’ setting, and publish. Flex tosses this error:

    Unable to transcode …/DataCalendarTestApp/src/assets/Skins.swf. DataCalendarTestApp/src/assets Examples.css line 43 1202306506313 139
    —————
    Peter: I’ll have to look into this and I don’t see where the problem could be.

  4. Craig Hollabaugh says:

    will this work in FB2? I haven’t made the jump yet. Thanks.
    ———
    Peter: I don’t see why not. There’s nothing intrinsically “Flex 3” about it as far as I know.

  5. Josh says:

    Any thoughts on how to go about moving calendar events by way of drag and drop? (for an admin)
    —————
    Peter: This is a good question. You’d have to implement this within the DataCalendar and use the DragManager. Detect a mouse down+move and tell the DragManager to create a proxy. Then listen for a mouse up event. I’d have to do a little research to see if there is a better way, but that’s the idea.

  6. Josh says:

    I just got your calendar working in Cairngorm, with the ability to drag the calendar events around, it’s a bit rough, but very cool. Cheers.

  7. Daniele says:

    Hi Peter,
    there are 2 small bugs in dayNames and abbreviatedDayNames set functions.
    here is the code
    if( value.length != 12 ) {
    throw new Error(“There must be exactly 7 entries in the abbreviatedDayNames array”);
    return;
    }

    It should be if( value.length != 7 ) {

  8. Daniele says:

    Hi Peter,
    i would like to set the text and the tooltip of next and previous buttons. How can i do that?

  9. Peter Ent says:

    Thanks for finding those!

  10. Daniele says:

    Hi peter,
    i would like to set the text of next/previous buttons (month navigation). I have seent there are no public properties to do that.How can i add 2 more properties/methods?

  11. Peter Ent says:

    This is a little complex for a note, but all you need to do is follow the same pattern for setter and getters: create backing variables (eg, _nextButtonLabel) and setter/getter functions (eg, get nextButtonLabel():String and set nextButtonLabel(value:String):void). Have the setter functions set their backing variables and call invalidateProperties.

    In commitProperties, copy the backing store variable’s to the buttons’ label properties.

    The buttons are part of the DataCalendarControlArea class.

  12. Peter Ent says:

    You can set the toolTips for those buttons in the DataCalendarControlArea class.

  13. Nico says:

    Hi peter, is it possible to add an alternating item background style for the data calendar and customize the data calendar cell header?Can you give me sono “hints” about implementing that?Thanks

  14. Peter Ent says:

    It has been a very long time since I looked at this code. I suggest you look at the place where the calendar is being generated which, I think, determines the rows. You could add a Sprite to the control and use that to color the background.

  15. Mansoor Achire says:

    Could you please send me an example of cell item renderer with flex graph. Thanks Mansoor

  16. Linus Graybill says:

    Great work, thanks so much for your contribution. I’m wondering if you have any suggestions on how to approach creating a week-view using this component. I’m looking to create a static seven-day week calendar and I’m wondering if it would be possible by extending this component. Thanks!

  17. Peter Ent says:

    That’s a complex application and out of the scope of the article. Adding the chart is simple enough since charts are just flex components and can be used for itemRenderers. However, the data for the chart must be part of the data for the record, which makes this complex.

  18. Peter Ent says:

    Honestly, it has been a while since I’ve looked at this code. But as I recall, the calendar generation code is very specific about building a month view. What you can try is making a new class for the week view and then seeing what function names overlap with the month view. When you have a list of common functions, create an interface with those functions, make both the calendar and week views implement that interface, then whenever your code references a view, use the interface as the type so your code can support both views without being specific. Then later, if you want a day view, you just write that and implement that same interface.