The Any+Time™ JavaScript Library includes a highly-customizable datepicker/ timepicker (calendar) and a powerful Date/String parse/format utility.
NEW!
Any+Time™
Version 3 is now
compatible!
(Version 2 for
is still available!)
AnyTime.widget() creates a JavaScript date/time picker with many unusual features and options:
DATE/TIME OPTIONS:
STYLING OPTIONS:
PROGRAMMER-FRIENDLY:
USABILITY FEATURES:
A single line of JavaScript code is all you need to add a date/time picker
to any <input> field! Choose between a pop-up
(appearing when the corresponding field receives focus) or
always-present widget (with either a visible or hidden field).
Use AnyTime.Converter to parse a String into a Date, or convert a Date to a String. Many format options are supported—in fact, most of the fields specified by the MySQL DATE_FORMAT() function!
Any+Time™ uses (and is therefore compatible with) the free jQuery JavaScript Library. The compatible jQuery version number is mentioned in the header comment in the JavaScript source code (anytime.js). An older version (2.x), based on Prototype, is still available below.
AnyTime.widget() has been tested compatible with Chrome 3.0, Firefox 3.0, Internet Explorer 8.0, Opera 10.10 and Safari 4.0, and should work with any version of ECMA-262 (JavaScript, JScript, ECMAScript, etc.) and HTML/XHTML supported by jQuery.
Any+Time™ follows WIA-ARIA Authoring Practices 1.0 for Date Picker keyboard interaction as closely as possible, to maximize accessibility without a mouse. Use Tab to navigate between the date and time sections, and arrows to navigate between time-selection buttons.
Any+Time™ is $ FREE $ under the Creative Commons BY-NC-SA 3.0 License. Please contact the author for a commercial license tailored to your specific needs!
Follow these easy steps to use Any+Time™ on your website!
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 jQuery.
Version 2.x uses the Prototype JavaScript Framework (prototype.js) instead of jQuery. This older version is still available:
(Not all of the features and behaviors described on this page are available in the older version.)
Save a copy of the JavaScript source and CSS stylesheet files
on your web server, remove the last line from the
JavaScript file, and reference both files in your HTML page.
For example, if you install jquery.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="/jquery.js" ></script>
<script type="text/javascript" src="/anytime.js" ></script>
For proper formatting, the <link> element must appear
before the <script> elements!
Create your date and/or time field as a simple
<input type="text"> element with a unique
id attribute.
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" size="50"
value="Sunday, July 30th in the Year 1967 CE" /><br/>
Español: <input type="text" id="bar" value="12:34" />
Call AnyTime.widget() 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 AnyTime.Widget won't know which field you're talking about! The code to add widgets to the example fields could be:
<script type="text/javascript">
AnyTime.widget( "foo",
{ format: "%W, %M %D in the Year %z %E", firstDOW: 1 } );
AnyTime.widget( "bar",
{ format: "%H:%i", labelTitle: "Tiempo",
labelHour: "Hora", labelMinute: "Minuto" } );
</script>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.
The first field specifies that the week begins with Monday.
The second field 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 .AtwBtn {border:1px solid yellow;color:green;
font-style:italic}
#Atw_bar .AtwBody {padding-left:0px}
#Atw_bar .AtwCurrentBtn {background-color:red;
border:1px solid yellow;color:yellow;}
#Atw_bar .AtwDismissBtn {background-color:white;color:red}
#Atw_bar .AtwFocusBtn {border:1px solid green}
#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):
$.ajax()
method whenever the user dismisses a popup widget or selects a value in
an inline widget. The input's name (or id) and
value are passed to the server (appended to ajaxOptions.data,
if present), and the "success" 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 must either echo or correct 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" value="Apr 1, '10"/>
<script type="text/javascript">
AnyTime.widget( "AjaxDemo",
{ ajaxOptions: { url: "ajaxdemo.php" },
baseYear: 2000,
format: "%b %e, '%y" } );
</script>"%y" format
specifier is used.
By default, the MySQL convention
that two-digit years are in the range 1970 to 2069 is used.
The most common alternatives are 1900 and 2000.00:00:00.
Refer to the following demo.
<input> is "hidden" (the widget appears
in its place). This actually sets the border, height, margin, padding
and width of the field as small as possible, so it can still get focus.
If you try to hide the field using traditional techniques (such as
setting display:none), the widget will not behave correctly.
This option should not used with
placement:"inline",
or the popup will seem to appear from nowhere if the user tabs to
the hidden field.
"popup""inline" <input type="text" id="ATWidgetDemo" />
<script type="text/javascript">
AnyTime.widget( "ATWidgetDemo",
{ format: "%Y-%m-%d %H:%i:%s (%E)",
hideInput: true,
placement: "inline" } );
</script>The following format specifiers are recognized:
| specifier | meaning |
|---|---|
%a | Abbreviated weekday name (Sun...Sat) |
%B | Abbreviation for Before Common Era (if year<1)* |
%b | Abbreviated month name (Jan...Dec) |
%C | Abbreviation for Common Era (if year>=1)* |
%c | Month, numeric (0..12) |
%D | Day of the month with English suffix (1st, 2nd, ...) |
%d | Day of the month, numeric (00...31) |
%E | Era abbreviation* |
%e | Day of the month, numeric (0...31) |
%H | Hour (00...23) |
%h | Hour (01...12) |
%I | Hour (01...12) |
%i | Minutes, numeric (00...59) |
%k | Hour (0...23) |
%l | Hour (1...12) |
%M | Month name (January...December) |
%m | Month, numeric (00...12) |
%p | AM or PM |
%r | Time, 12-hour (hh:mm:ss followed by AM or PM) |
%S | Seconds (00...59) |
%s | Seconds (00...59) |
%T | Time, 24-hour (hh:mm:ss) |
%W | Weekday name (Sunday...Saturday) |
%w | Day of the week (0=Sunday...6=Saturday) |
%Y | Year, numeric, four digits (possibly signed) |
%y | Year, numeric, two digits (possibly signed) |
%Z | Year, numeric, four digits (no sign)* |
%z | Year, 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 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.
AnyTime.Converter can be used independently. The following example converts dates in ISO date/time format:
var conv = new AnyTime.Converter({format:"%Y-%m-%dT%H:%i:%s"});
var date = conv.parse("1990-01-06T15:00:00");
alert( conv.format(date) );AnyTime.Converter accepts the following options, which are the same as for AnyTime.widget(): baseYear, dayAbbreviations, dayNames, eraAbbreviations, format, monthAbbreviations and monthNames.
AnyTime.Converter supports all of the same format field specifiers as AnyTime.widget().
Check the JavaScript source code for more detailed instructions on AnyTime.Converter and AnyTime.widget().
The following example uses AnyTime.Converter to support a button that uses jQuery to set the field to the current time. It also demonstrates the askEra, earliest and latest options, as well as a button that uses jQuery to clear the field:
<input type="text" id="nowDemoInput" size="22" />
<input type="button" id="nowDemoNowButton" value="now" />
<input type="button" id="nowDemoClearButton" value="clear" />
<script type="text/javascript">
var nowDemoFormat = "%Y-%m-%d @ %H:%i:%s";
var nowDemoConv = new AnyTime.Converter({format:nowDemoFormat});
$("#nowDemoNowButton").click( function(e) {
$("#nowDemoInput").val(nowDemoConv.format(new Date())); } );
$("#nowDemoClearButton").click( function(e) {
$("#nowDemoInput").val(""); } );
AnyTime.widget( "nowDemoInput",
{ askEra: true,
earliest: nowDemoConv.parse("-0240-05-25 @ 00:00:00"),
format: nowDemoFormat,
latest: nowDemoConv.parse("2061-07-28 @ 23:59:59") } );
</script>
A few people have requested the ability to use a button to display the widget,
but that would be redundant because the widget automatically appears when the
corresponding <input> gets focus!
Another occasional request is to allow users to type a value directly into the
<input> field. Such behavior would have a negative impact on
usability: not only does the widget make it easy to select the appropriate
date/time, it also protects the user from entering a value in the wrong format!
In addition, navigation keys (such as arrows) are used by the widget to select
values, and would behave inappropriately for data entry. Therefore, although it
is possible to hack the widget to permit typing in the field
(simply remove the call to event.preventDefault() at the end of the
key method), doing so is not recommended!
Minor variations in Microsoft Internet Explorer are to be expected
(especially in versions prior to IE8, due to its broken box model).
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
placement:"inline",
XHTML and a day-of-the-month
format specifier
("%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.
Be careful to place all <link rel="stylesheet"> and
<style> elements before the
<script> elements, or WebKit-based browsers
(Apple Safari and Google Chrome) might not format the widget correctly
(symptoms include extremely-tall widgets and mis-placed time buttons).
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
(refer to the preceding demo).
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!
Only use the hideInput
option to hide the <input> associated with a widget.
Traditional techniques (such as setting display:none)
will cause the widget to behave incorrectly.
It should go without saying that Any+Time™ 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.
Any+Time™ follows WIA-ARIA Authoring Practices 1.0 for Date Picker keyboard interaction as closely as possible, 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.
The baseYear option
can also be helpful in situations where "%y" is required.
The JavaScript source file includes an intrusive alert() call on
the last line, to discourage hot-linking to this server. When you download
the file, be sure to remove the last line to eliminate annoying messages
when your HTML page is loaded!
If you experience any other problems, please contact the author.
I'd love to show the world how you are using Any+Time™ on your website! Please let me know your URL and I'll be happy to mention it here.
Check back soon for a list of sites that show Any+Time™ in action!
I'd also appreciate if you'd help others find the library, either by linking to this page, or giving this script the best rating at one or more of the following websites:
Both positive feedback and constructive criticism are also appreciated (please contact the author).