Andrew M. Andrews III =
AJAX + JSON + XML Consulting & Training

Any+Time JavaScript Library: ATWidget Date/Time Picker (AJAX Calendar Widget) and ATConverter Date/String Converter

The Any+Time JavaScript Library includes an easy-to-use, easy-to-customize calendar widget (date and/or time picker) and a powerful Date/String parse/format utility.

Example ATWidget for hidden field, showing Date and
12-Hour Time option. Click any value to interact.
(Examples of popups and other variations follow.)

ATWidget is the AJAX-capable JavaScript GUI component. It is easy to add to a page and even easier to use! Unlike most date/time selection tools, nearly every field in an ATWidget control can be chosen with a single mouse click. And the wide variety of supported options make ATWidget a perfect fit where other interfaces won't work at all:

The ATWidget date/time control is attached to any input (text) field with a single line of JavaScript code. It can be placed as a popup (appearing when the user clicks the corresponding input field) or inline (always-present below the field). If used inline, the text field can be hidden so that only ATWidget is displayed (as shown here).

The appearance of the ATWidget calendar tool can be customized by modifying or supplementing the included CSS stylesheet. All labels, as well as month, weekday and era names and abbreviations, are also easy to change.

ATWidget can even be configured to use AJAX to automatically submit changes to a server (which can approve or veto the selected value), simply by specifying the server URL when the object is created. Yes, it really is that effortless!

ATConverter converts between JavaScript String and Date objects. It supports a wide range of formats—in fact, most of the fields specified by the MySQL DATE_FORMAT() function! ATConverter can be used independently, or in conjunction with ATWidget to manage the format of your date/time input field.

Any+Time uses (and is therefore compatible with) the free Prototype JavaScript Framework. The compatible Prototype version number is mentioned in the header comment in the JavaScript source code (anytime.js).

Any+Time has been tested compatible with Internet Explorer 7.0, Firefox 2.0, Safari 3.1, and Opera 9.22, and should work with any version of ECMA-262 (JavaScript, JScript, ECMAScript, etc.) and HTML/XHTML supported by Prototype.

ATWidget uses HTML anchors, with tabindex and title attributes, to maximize accessibility without a mouse.

Creative Commons License

Any+Time is $ FREE $ under the Creative Commons BY-NC-SA 3.0 License. To request a different license, please contact the author.

Instructions

Follow these easy steps to use Any+Time on your website!

1. Download

Any+Time consists of a single JavaScript source file with a single CSS stylesheet file. Both files are formatted to be human-readable, and they contain extensive comments to help you understand and modify them. Right-click on either link to save the file:

You may wish to use the compressed (unformatted, no comments) versions instead, for faster download.

Remember, you also need a compatible version of Prototype.

2. Save and Include

Save a copy of the JavaScript source and CSS stylesheet files on your web server and link to them from your HTML page. For example, if you install prototype.js, anytime.js and anytime.css in the document root directory, then add the following lines to the <head> section of the HTML page:

    <link rel="stylesheet" type="text/css" href="/anytime.css" />
    <script type="text/javascript" src="/prototype.js" ></script>
    <script type="text/javascript" src="/anytime.js" ></script>

3. Create the Input Text Field

Create your date and/or time field as a simple <input type="text"> element with a unique id attribute. You must also specify a tabindex attribute, and the next control on the page (if any) must have a tabindex at least 160 higher, to allow the widget's "buttons" to cycle in the correct order when the tab key is pressed.

Here are examples of a date-only field that uses a verbose format, and a time-only field with a Spanish label:

    English: <input type="text" id="foo" tabindex="260" size="50"
               value="Sunday, July 30th in the Year 1967 CE" /><br/>
    Español: <input type="text" id="bar" tabindex="420" value="12:34" />

4. Instantiate ATWidget

Create a new instance of ATWidget in your JavaScript code, passing it the id of the input element and any desired options. Be sure the code is executed after the text field is created, or ATWidget won't know which field you're talking about! The code to add widgets to the example fields could be:

    new ATWidget( "foo", { format: "%W, %M %D in the Year %z %E" } );
    new ATWidget( "bar", { format: "%H:%i", labelTitle: "Tiempo",
                            labelHour: "Hora", labelMinute: "Minuto" } );

Want a live demonstration? Click one of the following text fields to display the corresponding popup widget! For the first field, try choosing a year in the very distant past.

English:
Español:

The second field also demonstrates a customized style, achieved by the following CSS changes:

    <style type="text/css">
      #bar {border:3px double green;color:green}
      #Atw_bar {background-color:yellow;border:3px double green}
      #Atw_bar .AtwBtnBx {border:1px solid yellow}
      #Atw_bar .AtwBtnLnk {color:green;font-style:italic}
      #Atw_bar .AtwBody {padding-left:0px}
      #Atw_bar .AtwCurrentBx {background-color:red;border:1px solid yellow}
      #Atw_bar .AtwCurrentLnk {color:yellow}
      #Atw_bar .AtwDismissBx {background-color:white}
      #Atw_bar .AtwDismissLnk {color:red}
      #Atw_bar .AtwLbl {color:green}
      #Atw_bar .AtwTitle {background-color:red;border-bottom:none;
          color:yellow;font-family:cursive;font-size:14pt;height:30px}
    </style>

The following members may be specified as part of the options object (second argument):

askEra
If true, buttons to select the era (BCE/CE) are shown on the year selector popup, even if the format specifier does not include the era. If false, buttons to select the era are NOT shown, even if the format specifier includes the era. Normally, era buttons are only shown if the format string specifies the era.
askSecond
If false, buttons for number-of-seconds are not shown on the year selector popup, even if the format includes seconds. Normally, the buttons are shown if the format string specifies seconds.
ajaxOptions
Object to pass as Prototype's Ajax.Request  options parameter. This is only used if ATWidget option url is also provided (refer to option url).
dayAbbreviations
An array of day abbreviations to replace Sun, Mon, etc.
dayNames
An array of day names to replace Sunday, Monday, etc.
earliest
String or Date object representing the earliest date/time that a user can select. If a String is specified, it is expected to match the format specifier (refer to option format). For best results if the field is only used to specify a date, be sure to set the time to 00:00:00.
eraAbbreviations
An array of era abbreviations to replace BCE and CE. The most common replacements are the obsolete: BC and AD.
format
string specifying the date/time format (refer to following table)
labelDayOfMonth
HTML to replace the Day of Month label
labelDismiss
HTML to replace the dismiss popup button's X label
labelHour
HTML to replace the Hour label
labelMinute
HTML to replace the Minute label
labelMonth
HTML to replace the Month label
labelTitle
HTML for the title of the widget. If not specified, the widget automatically selects a title based on the format fields.
labelYear
HTML to replace the Year label
latest
String or Date object representing the latest date/time that a user can select. If a String is specified, it is expected to match the format specifier (refer to option format). For best results if the field is only used to specify a date, be sure to set the time to 23:59:59.
monthAbbreviations
An array of month abbreviations to replace Jan, Feb, etc.
monthNames
An array of month names to replace January, February, etc.
placement
One of the following strings:
"popup"
the widget appears above its input when the input receives focus, and disappears when it is dismissed. This is the default behavior.
"inline"
the widget follows the <input> and remains visible at all times. When choosing this placement, you might prefer to hide the input field (the correct value will still be submitted with the form).

For example, the date/time widget near the beginning of this page was created by the following HTML:
  <input type="text" id="ATWidgetDemo" tabindex="100" />
  <script type="text/javascript">
    new ATWidget("ATWidgetDemo",
      { format:"%Y-%m-%d %h:%i", placement:"inline" });
    $("ATWidgetDemo").hide();
  </script>
url
URL to pass to Prototype's Ajax.Request whenever the user dismisses a popup widget or selects a value in an inline widget. The input's name and value are passed as a parameter, and the onSuccess handler sets the input's value to the responseText. Therefore, the text returned by the server must be valid for the input's date/time format, and the server can approve or veto the value chosen by the user.

For example, the server for the following AJAX-enabled widget always changes the day-of-the-month to 1 after the component is dismissed, no matter what day the user actually selects:
  <input type="text" id="AjaxDemo" tabindex="580" value="Apr 1, 2008"/>
  <script type="text/javascript">
    new ATWidget("AjaxDemo",{format:"%b %e, %Y",url:"ajaxdemo.php"});
  </script>


Refer to ATWidget option ajaxOptions for information about passing options to Ajax.Request.

The following format specifiers are recognized:

specifiermeaning
%aAbbreviated weekday name (Sun...Sat)
%BAbbreviation for Before Common Era (if year<1)*
%bAbbreviated month name (Jan...Dec)
%CAbbreviation for Common Era (if year>=1)*
%cMonth, numeric (0..12)
%DDay of the month with English suffix (1st, 2nd, ...)
%dDay of the month, numeric (00...31)
%EEra abbreviation*
%eDay of the month, numeric (0...31)
%HHour (00...23)
%hHour (01...12)
%IHour (01...12)
%iMinutes, numeric (00...59)
%kHour (0...23)
%lHour (1...12)
%MMonth name (January...December)
%mMonth, numeric (00...12)
%pAM or PM
%rTime, 12-hour (hh:mm:ss followed by AM or PM)
%SSeconds (00...59)
%sSeconds (00...59)
%TTime, 24-hour (hh:mm:ss)
%WWeekday name (Sunday...Saturday)
%wDay of the week (0=Sunday...6=Saturday)
%YYear, numeric, four digits (possibly signed)
%yYear, numeric, two digits (possibly signed)
%ZYear, numeric, four digits (no sign)*
%zYear, numeric, variable length (no sign)*
%%A literal % character

The default format is "%Y-%m-%d %T".

* Note: except for those delimited by an asterisk in the table above, these are the same format fields used by the MySQL database DATE_FORMAT() function. The default format is the one used for MySQL DATETIME and TIMESTAMP data types.

Any other character in the format string appears literally in the value. Any other sequence of percent sign ("%") followed by a character is replaced by the literal character following the percent sign, except for the following MySQL specifiers not implemented by Any+Time due to lack of support in JavaScript: %f (microseconds); %j (day-of-year); %U, %u, %V and %v (week-of-year); and %X and %x (year-for-week). Do not use these format specifiers.

5. Using ATConverter

ATConverter can be used independently. The following example converts dates in ISO date/time format:

    var conv = new ATConverter({format:"%Y-%m-%dT%H:%i:%s"});
    var date = conv.parse("1990-01-06T15:00:00");
    alert( conv.format(date) );

ATConverter accepts the following options, which are the same as for ATWidget: dayAbbreviations, dayNames, eraAbbreviations, format, monthAbbreviations and monthNames.

ATConverter supports all of the same format field specifiers as ATWidget.

Check the JavaScript source code for more detailed instructions on ATConverter and ATWidget.

6. Problems? No Problem!

Minor variations in Microsoft Internet Explorer are to be expected, due to its broken box model. This will hopefully be resolved in IE8. For best results, be sure to include an appropriate <!DOCTYPE> declaration as the first line of your HTML page; for example:

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">

When using "inline" placement, XHTML and a day-of-the-month format field ("%D", "%d" or "%e"), the <input> may only appear where a <table> element is permitted (for example, NOT within a <p> element). This is because the widget uses a <table> element to arrange the day-of-the-month (calendar) buttons. Failure to follow this advice may result in a JScript "unknown error" from Internet Explorer.

When specifying the "earliest" and/or "latest" option, be certain to include a time value, even if the user is only able to select the date. The time for an "earliest" date should be 00:00:00, and the time for a "latest" date should be 23:59:59. This is because the Date objects used by the widget reflect exact moments in time, regardless of which fields are specified by the format. Failure to set the time could result in incorrect enforcement if, for example, the page is loaded at 23:59 one day, but the field not changed until 00:01 the day after!

It goes without saying that the Any+Time Library only works in browsers with JavaScript enabled. Any server-side form processing should validate every value it receives, in case JavaScript was disabled or otherwise unavailable when the form was submitted.

ATWidget uses HTML anchors, with tabindex and title attributes, to maximize accessibility without a mouse. However, if a user reports difficulty changing a date/time value using the widget (for example, due to problems with a "screen reader" or other assistive technology), ask them to disable JavaScript and carefully type the value into the input field. Again, be sure to validate the input when it is received by the server.

Remember that two-digit years ("%y") are susceptible to the Y2K problem! For best results, use four-digit or variable-length years ("%Y", "%Z" or "%z") instead.

If you experience any other problems, please contact the author.

Copyright 2008 AJAX, JSON and XML Consulting and Training by Andrew M. Andrews III. All Rights Reserved. "Andrew M. Andrews III", "AMA3" and the Tre Design are service marks of Andrew M. Andrews III. Any+Time is a trademark of Andrew M. Andrews III. Use this site at your own risk.

Reston Town Center