The Zapatec DHTML Calendar Reference Manual

Contents

    1  Overview
        1.1  How does The Calendar work?

    2  Quick startup
        2.1  Installing a popup calendar
        2.2  Installing a flat calendar
            2.2.1  Flat calendar with multiple days
        2.3  Zapatec.Calendar.setup in detail

    3  The Calendar object overview
        3.1  Creating a calendar
        3.2  Order Matters
        3.3  Caching the Calendar object
        3.4  Callback functions

    4  The DHTML Calendar object API reference
        4.1  Calendar constructor
        4.2  Useful member variables (properties)
        4.3  Public methods
            4.3.1  Calendar.create
            4.3.2  Calendar.callHandler
            4.3.3  Calendar.callCloseHandler
            4.3.4  Calendar.hide
            4.3.5  Calendar.setDateFormat
            4.3.6  Calendar.setTtDateFormat
            4.3.7  Calendar.setDateStatusHandler
                Calendar.setDateStatusHandler and disabling times
            4.3.8  Calendar.show
            4.3.9  Calendar.showAt
            4.3.10  Calendar.showAtElement
                Vertical alignment
                Horizontal alignment
                Default values
            4.3.11  Calendar.setDate
            4.3.12  Calendar.setFirstDayOfWeek
            4.3.13  Calendar.parseDate
            4.3.14  Calendar.setRange

    5  Side effects

    6  Credits

1  Overview

The Zapatec DHTML Calendar provides your site’s end-users with an easy-to-use, versatile, and interactive way to select the date and time. The Calendar can be set up to pop up ("popup version") on user action or remain on the screen all the time ("flat version" great for blogging!). The Calendar works in many different browsers including Internet Explorer, Mozilla, Opera 7, Firefox, Safari, and Konqueror. The DHTML Calendar is the best choice for ensuring that your site’s visitors can use your form or application because of this cross-browser compatibility.

You can find the latest info and version at the Calendar in the products section of Zapatec’s home page at

http://www.zapatec.com

1.1  How does The Calendar work?

The Calendar employs DHTML (dynamic HTML) for a combination of an easily customizable application and an attractive, simple, end-user experience. DHTML refers to the combination of Hyper Text Markup Language (HTML), Cascading Style Sheets (CSS), JavaScript and Document Object Model (DOM). DOM is a set of interfaces that glues the other three together. In other words, DOM allows dynamic modification of an HTML page through a program. The Calendar’s programming and modifications are in JavaScript, and its appearance is customized with Cascading Style Sheets (CSS).

Using DOM calls, the program dynamically creates a <table> element that contains a calendar for the given date and then inserts it in the document body. It then shows this table at a specified position. Usually the position is related to some element in which the date needs to be displayed/entered, such as an input field.

The layout and colors of the calendar are controlled by CSS attributes. By assigning a certain CSS class to the table we can control the look of the calendar. To change the colors, backgrounds, rollover effects and other CSS properties, you can change the CSS file—modification of the program itself is not necessary.

2  Quick startup

First you have to include the needed scripts and style-sheet. Make sure you do this in your document’s <head> section. Make sure you put the correct paths to the scripts.

<style type="text/css">@import url(calendar-win2k-1.css);</style>
<script type="text/javascript" src="utils.js"></script>
<script type="text/javascript" src="calendar.js"></script>
<script type="text/javascript" src="lang/calendar-en.js"></script>
<script type="text/javascript" src="calendar-setup.js"></script>

2.1  Installing a popup calendar

Now suppose you have the following HTML:

<form ...>
  <input type="text" id="data" name="data" />
  <button id="trigger">...</button>
</form>

You want the button to popup a calendar widget when clicked? Just insert the following code immediately after the HTML form:

<script type="text/javascript">
  Zapatec.Calendar.setup(
    {
      inputField  : "data",         // ID of the input field
      ifFormat    : "%m %d, %Y",    // the date format
      button      : "trigger"       // ID of the button
    }
  );
</script>
<noscript>
<br/>
	This page uses a <a href='http://www.zapatec.com/products/prod1'> 
	Javascript Calendar </a>, but your browser does not support Javascript. 
<br/>
Either enable Javascript in your Browser or upgrade to a newer version.
</noscript>

The Calendar.setup function, defined in calendar-setup.js, takes care of "patching" the button to display a calendar when clicked. The calendar is by default in single-click mode and linked with the given input field, so that when the end-user selects a date it will update the input field with the date in the given format and close the calendar.

By looking at the example above we can see that the function Calendar.setup receives only one parameter: a JavaScript object. Further, that object can have lots of properties that tell to the setup function how would we like to have the calendar. For instance, if we would like a calendar that closes at double-click instead of single-click we would also include the following: singleClick:false.

For a list of all supported parameters please see the section 2.3.

2.2  Installing a flat calendar

You can configure a flat calendar, using the same Calendar.setup function. First, you should have an empty element with an ID. This element will act as a container for the calendar. It can be any block-level element, such as DIV, TABLE, etc. We will use a DIV in this example.

<div id="calendar-container"></div>

Then there is the JavaScript code that sets up the calendar into the "calendar-container" DIV. The code can occur anywhere in HTML after the DIV element.

<script type="text/javascript">
  function dateChanged(calendar) {
    // Beware that this function is called even if the end-user only
    // changed the month/year.  In order to determine if a date was
    // clicked you can use the dateClicked property of the calendar:
    if (calendar.dateClicked) {
      // OK, a date was clicked, redirect to /yyyy/mm/dd/index.php
      var y = calendar.date.getFullYear();
      var m = calendar.date.getMonth();     // integer, 0..11
      var d = calendar.date.getDate();      // integer, 1..31
      // redirect...
      window.location = "/" + y + "/" + m + "/" + d + "/index.php";
    }
  };

  Zapatec.Calendar.setup(
    {
      flat         : "calendar-container", // ID of the parent element
      flatCallback : dateChanged           // our callback function
    }
  );
</script>
<noscript>
<br/>
	This page uses a <a href='http://www.zapatec.com/products/prod1'> 
	Javascript Calendar </a>, but your browser does not support Javascript. 
<br/>
Either enable Javascript in your Browser or upgrade to a newer version.
</noscript>

2.2.1  Flat calendar with multiple days

You can set up a flat calendar where the user can choose multiple days just as you can a popup calendar. But how do you tell the calendar to submit the dates? With a popup calendar you click on the close button. With a flat calendar you need to call the submitFlatDates method of the calendar. The following code shows setting up the calendar.

var flatCalObj = Zapatec.Calendar.setup({
flat        : "flatcalMultiDays", // ID of the parent element
flatCallback: flatCallback,
align       : "BR",
showOthers  : true,
//sortOrder : "desc", //default is "asc"ending; or remove comment to 
//sort in "desc"ending order; or "none" to NOT sort the multiple dates.
multiple    : MA // pass the initial or computed array of multiple dates 
//to be initially selected
});

and you can fetch the dates using

<input type="button" value="Submit" id='button7' 
onClick="flatCalObj.submitFlatDates();" name="button7">

When the user clicks on the Submit button the onclick will call submitFlatDates on the flatCalObj calendar object. The calendar will then call the callback with the array of dates.

2.3  Zapatec.Calendar.setup in detail

Below is the complete list of properties interpreted by Zapatec.Calendar.setup. All of them have default values, so you can pass only those that you would like to customize. Regardless, you must pass at least one of inputField, displayArea or button, for a popup calendar, or flat for a flat calendar. Otherwise you will get a warning message saying that there is nothing to setup.

3  The Calendar object overview

You can set up a fully functional Calendar with the function presented in the previous section.

This advanced section will give you the information you need to add functionality and customize the calendar even further.

The file calendar.js implements the functionality of the calendar. Almost all functions and variables are embedded in the JavaScript object "Calendar".

You can instantiate a Calendar object by calling the constructor with the following code: var cal = new Calendar(...). We will discuss the parameters later. After creating the object, the variable cal contains a reference to the Calendar object. You can use this reference to access further options of the calendar, for instance:

cal.weekNumbers = false; // do not display week numbers
cal.showsTime = true;    // include a time selector
cal.setDateFormat("%Y.%m.%d %H:%M"); // set this format: 2003.12.31 23:59
cal.setDateStatusHandler(function(date, year, month, day) {
	
  // verify date and return true if it has to be disabled
  // "date" is a JS Date object, but if you only need the
  // year, month and/or day you can get them separately as
  // next 3 parameters, as you can see in the declaration
  if (year == 2004) {
    // disable all dates from 2004
    return true;
  }
  return false;
});

3.1  Creating a calendar

The Calendar is created by following some of the same steps as are found in section 2. While you can skip optional (marked "opt") steps if you’re happy with the defaults, using the order outlined below will make it easier for you to customize and avoid errors.

  1. Instantiate a Calendar object. Details about this in section 4.1.

  2. opt   Set the weekNumbers property to false if you don’t want the calendar to display week numbers.

  3. opt   Set the showsTime property to true if you want the calendar to also provide a time selector.

  4. opt   Set the time24 property to false if you want the time selector to be in 12-hour format. Default is 24-hour format. This property only has effect if you also set showsTime to true.

  5. opt   Set the range of years available for selection (see section 4.3.14). The default range is [1970..2050].

  6. opt   Set the getDateStatus property. You should pass here a function that receives a JavaScript Date object and returns true if the given date should be disabled, false otherwise (details in section IGNORE).

  7. opt   Set a date format. Your handler function, passed to the calendar constructor, will be called when a date is selected with a reference to the calendar and a date string in this format.

  8. Create the HTML elements related to the calendar. This step actually puts the calendar in your HTML page. You simply call Calendar.create(). You can give an optional parameter if you want to create a flat calendar (details in section 4.3.1).

  9. opt   Initialize the calendar to a certain date, from the input field, or a default date that is application specific.

  10. Show the javascript calendar (details in section 4.3.8).

3.2  Order Matters

Two things happen when you create a Calendar. First, you create the JavaScript object. Second, the HTML elements that actually let you see and manipulate the Calendar are created.

When we instantiate the Calendar, we in effect create the JavaScript object. We configure properties and create the HTML elements that will provide the end-user with a visible, interactive UI. The function Calendar.create described in section 4.3.1, is responsible for creation of the HTML element, and with it you can create pop up or flat Calendars.

Some properties will not work unless they are set before creating the HTML elements. One example is weekNumbers. WeekNumbers is true by default. If you do not want the Calendar to display the week numbers, you must set this to false. If you set the value to false after calling the calendar.create file, however, it will not work. Calling the calendar.create creates the HTML elements (tables, cells, etc.) and it will create the table based on your property values. So, if weekNumbers falls after the calendar.create is called, your calendar will still display the table elements required for the week number because it didn’t see the information to leave it out (a value of false ahead of time. For this reason the order of the steps above is important.

The order of actions also matters when you want to show the calendar. The "create" function does create the HTML elements, but they are initially hidden (have the style "display: none") unless the calendar is a flat calendar which should always be visible in the page. Obviously, the Calendar.show function should be called after calling Calendar.create.

3.3  Caching the Calendar object

Suppose the end-user has popped up a calendar and selects a date. The calendar then closes. What is really happening?

The Zapatec.Calendar.setup function caches the JavaScript object. It does this by checking the global variable window.calendar and if it is not null it assumes it is the created Calendar object. When the end-user closes the calendar, our code will only call "hide" on it, therefore keeping the JavaScript object and the HTML elements in place.

Caching the calendar improves speed, specifically when you have several calendars on one pages, and when the user opens and closes the same calendar several times.

3.4  Callback functions

The calendar uses callback functions as a way to tell that a date is selected; it has to update an input field or go to a certain URL when a date is clicked in flat mode.The Calendar object has no awareness of an input field and it does not know where to redirect the browser when a date is clicked in the flat calendar.

The calendar object calls the callback when a particular event is triggered, and your code is responsible for handling it from there. For a general-purpose library, this is the best model for making a truly reusable widget.

The calendar supports the following user callbacks:

4  The DHTML Calendar object API reference

4.1  Calendar constructor

var calendar = Calendar(firstDayOfWeek, date, onSelect, onClose);

Parameters are as follows:

The onSelect event

Assuming you have a input field with an id "myInputField", here is a typical implementation of this function:

function onSelect(calendar, date) {
  var input_field = document.getElementById("myInputField");
  input_field.value = date;
};

date is displayed in the format selected with calendar.setDateFormat (see section 4.3.5). This code simply updates the input field. If you want the calendar to be in single-click mode then you should also close the calendar after you updated the input field. Here’s the updated version:

function onSelect(calendar, date) {
  var input_field = document.getElementById("myInputField");
  input_field.value = date;
  if (calendar.dateClicked) {
    calendar.callCloseHandler(); // this calls "onClose" (see above)
  }
};

Note that this function is called when the user clicks inside the calendar. We check the member variable dateClicked and only hide the calendar if it’s true. If this variable is false it means that no date was actually selected, but the user only clicked to change the month/year using the navigation buttons or the menus. We do not want to hide the calendar in that case.

The onClose event

This event is triggered when the calendar should close. It should hide or destroy the calendar object—the calendar itself just triggers the event, but it won’t close itself.

A typical implementation of this function is the following:

function onClose(calendar) {
  calendar.hide();
  // or calendar.destroy();
};

4.2  Useful member variables (properties)

After creating the Calendar object you can access the following properties:

4.3  Public methods

4.3.1  Calendar.create

This function creates the different HTML elements that are needed to display the calendar. You should call it after setting the calendar properties.

calendar.create(); // creates a popup calendar
  // -- or --
calendar.create(document.getElementById(parent_id)); // makes a flat calendar

The function creates a popup or a flat calendar. If the "parent" argument is present (it should be a reference—not ID—to an HTML element) then a flat calendar is created and it is inserted in the given element.

At any moment, given a reference to a calendar object, we can check the boolean member variable isPopup to see if it’s a popup or a flat calendar:

if (calendar.isPopup) {
   // this is a popup calendar
} else {
   // this is a flat calendar
}

4.3.2  Calendar.callHandler

This function calls the first user callback (the onSelect handler) with the required parameters.

4.3.3  Calendar.callCloseHandler

This function calls the second user callback (the onClose handler). It is useful when you want to have a "single-click" calendar—just call this in your onSelect handler, if a date was clicked.

4.3.4  Calendar.hide

Call this function to hide the calendar. The calendar object and HTML elements will not be destroyed, thus you can later call one of the show functions on the same element.

4.3.5  Calendar.setDateFormat

This function configures the format in which the calendar reports the date to your "onSelect" handler. Call it like this:

calendar.setDateFormat("%y/%m/%d");

It receives only one parameter, the required format. In addition to special characters, you can insert spaces, commas, tabs and other constant characters. The special characters are the following:

%a abbreviated weekday name
%A full weekday name
%b abbreviated month name
%B full month name
%C century number
%d the day of the month ( 00 .. 31 )
%e the day of the month ( 0 .. 31 )
%H hour ( 00 .. 23 )
%I hour ( 01 .. 12 )
%j day of the year ( 000 .. 366 )
%k hour ( 0 .. 23 )
%l hour ( 1 .. 12 )
%m month ( 01 .. 12 )
%M minute ( 00 .. 59 )
%n a newline character
%p "PM" or "AM"
%P "pm" or "am"
%S second ( 00 .. 59 )
%s number of seconds since Epoch (since Jan 01 1970 00:00:00 UTC)
%t a tab character
%U, %W, %V the week number
%u the day of the week ( 1 .. 7, 1 = MON )
%w the day of the week ( 0 .. 6, 0 = SUN )
%y year without the century ( 00 .. 99 )
%Y year including the century ( ex. 1979 )
%% a literal % character

All three specifiers %U, %W, %V currently implement the same week number algorithm, as defined by ISO 8601: "Week 01 is the week that has the Thursday in the current year, which is equivalent to the week that contains the fourth day of January. Weeks start on Monday."

4.3.6  Calendar.setTtDateFormat

uses the same format as Calendar.setDateFormat, but refers to the format of the date displayed in the "status bar" when the mouse is over some date.

4.3.7  Calendar.setDateStatusHandler

Sets the callback for disabling and customizing specific dates and times. You need to write the callback that will return a boolean or a string. If the return value is (true the date is disabled and the user cannot click on it. If it is false) it is available for clicking.

If the returned value is a string then the given date will gain an additional CSS class, namely the returned value. You can use this to highlight some dates in some way. Note that you are responsible for defining the CSS class that you return. If you return string that contains "disabled" the date will be disabled, just as if you returned true. This provides you with custom ways to display disabled dates.

Here is a simple scenario that shows what you can do with this function. The following should be present in some of your styles, or in the document head in a STYLE tag (but put it after the place where the calendar styles were loaded):

.special { background-color: #000; color: #fff; }

And you would use the following code before calling Calendar.create():

// this table holds your "special" days, so that we can automatize
// things a bit:
var SPECIAL_DAYS = {
    0 : [ 13, 24 ],             // "special days" in January
    2 : [ 1, 6, 8, 12, 18 ],    // "special days" in March
    8 : [ 21, 11 ],             // "special days" in September
   11 : [ 25, 28 ]              // "special days" in December
};

// this function returns true if the passed date is special
function dateIsSpecial(year, month, day) {
    var m = SPECIAL_DAYS[month];
    if (!m) return false;
    for (var i in m) if (m[i] == day) return true;
    return false;
}

// this is the actual date status handler.  Note that it receives the
// date object as well as separate values of year, month and date, for
// your confort.
function dateStatusHandler(date, y, m, d) {
    if (dateIsSpecial(y, m, d)) return "special";
    else return false;
    // return true above if you want to disable other dates
}

// configure it to the calendar
calendar.setDateStatusHandler(dateStatusHandler);

The above code adds the "special" class name to some dates that are defined in the SPECIAL_DAYS table. Other dates will simply be displayed as default, enabled.

Calendar.setDateStatusHandler and disabling times

You can disable specific times as well as dates using the setDateStatusHandler.

function timeOutOfRange(date, year, month, day, hours, minutes) {
	if (date.getDay() == 0) { //No Sunday
		return true;
	}
	if (typeof(hours) != "undefined") {
		if (date.getDay() == 6) {
			//only allow 11AM to 5PM on Saturday
			if (hours < 17 && hours >= 11) {
				return false;
			} else {
				return true;
			}
		}

		//on saturdays allow
		if (date.getDay() == 5) {
			//only allow 8AM to 9:45PM on Friday
			if (hours > 21 || hours < 8) {
				return true; //not within the hours
			}

			if (hours != 21) {
				return false; //within the hours
			}

			//hours = 21
			if (minutes <= 45) {
				return false;
			} else {
				return true;
			}
		}

	}
	return false;
}

Zapatec.Calendar.setup({
inputField     :    "sel9",     // id of the input field
singleClick    :     false,     // require two clicks to submit
ifFormat       :    '%a, %b %e, %Y [%H:%M]',     // format of the input field
ampm           :     false,
showsTime      :     true,     // show time as well as date
button         :    "button9",  // trigger button
dateStatusFunc :    timeOutOfRange,
floating       :    true
});

The calendar calls the callback timeOutOfRange on two events, when the date changes, and when the time changes. To see which check it is, see if the hours variable is defined. In the above example the user is limited to 11AM - 5PM on Saturdays and 8AM to 9:45 PM on Friday.

Sometimes the user could end up in a time that’s not permited. This can happen when the calendar first start up. For instance let’s say the user clicks on the calendar on Saturday at 6PM. This can also happen when the user switches days and the time was allowed on the old day but not on the new one. For instance the user scrolls the time to 8PM on a Monday and changes the day to Saturday.

In both cases the calendar automatically scrolls to the first permissable time in 5 minute increment. So if the current time is 9:42PM on a Saturday and you click on the above calendar it will set the time to 11:02 AM.

4.3.8  Calendar.show

Call this function do show the calendar. It basically sets the CSS "display" property to "block". It doesn’t modify the calendar position.

This function only makes sense when the javascript calendar is in popup mode.

4.3.9  Calendar.showAt

Call this to show the calendar at a certain (x, y) position.

calendar.showAt(x, y);

The parameters are absolute coordinates relative to the top left corner of the page, thus they are page coordinates not screen coordinates.

After setting the given coordinates it calls Calendar.show. This function only makes sense when the calendar is in popup mode.

4.3.10  Calendar.showAtElement

This function is useful if you want to display the calendar near some element.

calendar.showAtElement(element, align);

where element is a reference to your element (for instance it can be the input field that displays the date) and align is an optional parameter, of type string, containing one or two characters. For instance, if you pass "Br" as align, the calendar will appear below the element and with its right margin continuing the element’s right margin.

Align may contain one or two characters. The first character dictates the vertical alignment relative to the element, and the second character dictates the horizontal alignment. If the second character is missing, it will be assumed "l" (the left margin of the calendar will be at the same horizontal position as the left margin of the element).

The characters given for the align parameters are case sensitive. This function only makes sense when the calendar is in popup mode. After computing the position, it uses Calendar.showAt to display the calendar as specified.

Vertical alignment

The first character in "align" can take one of the following values:

Horizontal alignment

The second character in "align" can take one of the following values:

Default values

If the "align" parameter is not set the calendar defaults to "Br".

4.3.11  Calendar.setDate

Sets the Calendar to the date passed in the parameter. This parameter needs to be a JavaScript Date object. If the calendar is visible the new date is displayed immediately.

calendar.setDate(new Date()); // go today

4.3.12  Calendar.setFirstDayOfWeek

Changes the first day of week. The parameter has to be a numeric value ranging from 0 to 6. Pass 0 for Sunday, 1 for Monday, ..., 6 for Saturday.

calendar.setFirstDayOfWeek(5); // start weeks on Friday

4.3.13  Calendar.parseDate

Use this function to parse a date given as string and to move the calendar to that date.

The algorithm tries to parse the date according to the format that was previously set with Calendar.setDateFormat; if that fails, it still tries to get a valid date.

calendar.parseDate("2003/07/06");

4.3.14  Calendar.setRange

Sets the range of years that are allowed in the calendar.

calendar.setRange(1970, 2050);

5  Side effects

The <strong> DHTML calendar </strong> code was intentionally embedded in an object to make it have as few as possible side effects. There are some side effects. This following is a list of the side effects;

  1. The global variable window.calendar is initially set to null. This variable is used by the calendar code, especially when doing drag & drop for moving the calendar.

  2. The JavaScript Date object is modified. We add some properties and functions that are useful to our calendar. It made more sense to add them directly to the Date object than to the calendar itself.

    1. Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31);

    2. Date.SECOND = 1000 /* milliseconds */;

    3. Date.MINUTE = 60 * Date.SECOND;

    4. Date.HOUR = 60 * Date.MINUTE;

    5. Date.DAY = 24 * Date.HOUR;

    6. Date.WEEK = 7 * Date.DAY;

    7. Date.prototype.getMonthDays(month) — returns the number of days of the given month, or of the current date object if no month was given.

    8. Date.prototype.getWeekNumber() — returns the week number of the date in the current object.

    9. Date.prototype.equalsTo(other_date) — compare the current date object with other_date and returns true if the dates are equal. It ignores time.

    10. Date.prototype.print(format) — returns a string with the current date object represented in the given format. It implements the format specified in section 4.3.5.

6  Credits

The Zapatec DHTML Calendar is a commercial version of the open source calendar written by Mihai Bazon.

Last modified: Friday, March 31st, 2006 3:37:48pm