http://www.dynarch.com/projects/calendar
Doc:
This is the documentation of the new Dynarch Calendar (“JSCal2”). Note that it is not compatible with our old calendar project. The new calendar has less predefined ways to setup, and rather focuses on an extensive API that you can use to do what you want. Because it's a lesson I've learned that you can't please everybody, so it's better to provide lots of features so that people can please themselves. ;-)
Unzip the archive and copy the "src
" subdirectory into a path such that you can access jscal2.js using the following URL:
(i.e. the “src” directory should become “JSCal2” in the document root of your website).
Here is a sample <head>
section that loads the base CSS file, a color theme and the required JS files:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <link rel="stylesheet" type="text/css" href="/JSCal2/css/jscal2.css" /> <link rel="stylesheet" type="text/css" href="/JSCal2/css/border-radius.css" /> <link rel="stylesheet" type="text/css" href="/JSCal2/css/gold/gold.css" /> <script type="text/javascript" src="/JSCal2/js/jscal2.js"></script> <script type="text/javascript" src="/JSCal2/js/lang/en.js"></script> </head>
jscal2.css
is essential and defines a minimal skin. You can optionally include border-radius.css
to add round corners in browsers that support it (Firefox, Safari and Chrome) and load an additional color theme if you like (gold/gold.css
).
The required JavaScript files that you need to load are jscal2.js
and at least one language file (for example en.js
).
Also note the DOCTYPE line. It is important for older versions of Internet Explorer to enter “standards mode”. IE8 should work fine without it.
Calendar.setup(args)
simply constructs a new calendar and is equivalent to calling new Calendar(args)
. args
is a JavaScript hash that can have the following properties:
animation
— defaults to true
unless browser is IE6 (defaults to false
in IE6). If you pass true
then it will force animation in all browsers (including IE6), if you pass false
then it will disable animation.cont
— container element (for inline calendar, not popup). Pass the ID of an element to contain the calendar (or reference to that DOM element if you have it).bottomBar
— boolean, default true
. If you pass false then the bottom bar containing the “Today” button won't be displayed.date
— default date for the calendar. This determines the month/year that the calendar will initially display. See also selection
below.fdow
— first day of week. Default is defined in the language file. Pass 0 for Sunday, 1 for Monday etc.min
— the minimum (oldest) date that the calendar allows for selection.max
— same as minimum, but limits on the right side.reverseWheel
— default false
. Pass true
here if you want to reverse the direction of the mouse wheel movement.selectionType
- default Calendar.SEL_SINGLE
. Pass Calendar.SEL_MULTIPLE
if you want to allow multiple dates selection.selection
— the initial date selection for the calendar. By default, the selection is empty. See the Selection object for more details.weekNumbers
— default false
. Pass true
to display the week numbers column.checkRange
— default false
. When you want to allow range selection but prevent one from selecting disabled dates (see the disabled
argument below) you should pass this true
, and the calendar will check each date.align
— default alignment, for popup calendars. See the popup method for details on the format of align
.inputField
— an ID or reference to an <input>
element that the calendar will automatically update. Only for popup calendars.trigger
— an ID of a <button>
element (in fact any element type) that should trigger the popup calendar (the calendar hooks on the “onclick” event).dateFormat
— the format of the date to be displayed in the input field. See the Calendar.printDate function for information on the format.opacity
— default 1 if browser is IE, 3 otherwise. Specifies the level of “opacity effects” to do in animation. IE is quite slow with this. Specify 0 for no opacity, or 1, 2 or 3 for increasing levels of “eye candyness”.titleFormat
— the format of the title bar. By default this is "%b %Y"
which means it displays the short month name and full year. See Calendar.printDate.showTime
— default false
. If you enable this the calendar will display a time selector. You can pass true
to enable 24h time selector, or pass 12
to enable the am/pm time selector.timePos
— the position of the time selector in the bottom bar. By default this is "right"
. Pass "left"
if you want the time selector to the left of the “Today” button.time
— initial time to display in the time selector. This is an integer in the form "HHMM"
— for example if you want the calendar to display 9:45 pm, pass 2145
. By default the calendar will use the current time, adjusted to a multiple of minuteStep
.minuteStep
— the increment/decrement step for the minute field. By default this is set to 5 minutes.onSelect
— a callback of your own that will be called when the selection changes. See the selection object.onChange
— a callback that will be called when the calendar changes position (month and/or year).onTimeChange
— a callback that will be called when the time is changed in the time selector. It will get two arguments: reference to the calendar, and the new time (in integer representation i.e. 2145
for 9:45 pm).disabled
— a callback that will be called to determine additional disabled dates. See disabling dates.dateInfo
— a callback that will be called to get additional information about a date, such as a special CSS class name to add to it, or a tooltip to display when it is hovered. See highlight special dates and date tooltips.onFocus
— a callback that will be called when the calendar receives focus.onBlur
— will be called when the calendar loses focus.All arguments are optional. However, you should provide one of cont
(for inline calendars) or trigger
for popup calendars, or else provide your own code to display a popup calendar. We'll see how this can be done later.
For example here is how we created the calendar on the front page:
<table style="float: left; margin: 0 1em 1em 0"><tr><td> <!-- element that will contain the calendar --> <div id="calendar-container"></div> <!-- here we will display selection information --> <div id="calendar-info" style="text-align: center; margin-top: 0.3em"></div> </td></tr></table> <script type="text/javascript">//<![CDATA[
Calendar.setup({ cont : "calendar-container", weekNumbers : true, selectionType : Calendar.SEL_MULTIPLE, selection : Calendar.dateToInt(new Date()), showTime : 12, onSelect : function() { var count = this.selection.countDays(); if (count == 1) { var date = this.selection.get()[0]; date = Calendar.intToDate(date); date = Calendar.printDate(date, "%A, %B %d, %Y"); $("calendar-info").innerHTML = date; } else { $("calendar-info").innerHTML = Calendar.formatString( "${count:no date|one date|two dates|# dates} selected", { count: count } ); } }, onTimeChange : function(cal) { var h = cal.getHours(), m = cal.getMinutes(); // zero-pad them if (h < 10) h = "0" + h; if (m < 10) m = "0" + m; $("calendar-info").innerHTML = Calendar.formatString("Time changed to ${hh}:${mm}", { hh: h, mm: m }); } });
//]]></script>
Unlike inline calendars, a popup calendar isn't displayed at all times, but it pops up whenever it's needed, such as when the user presses a “select date” button. In popup mode you'll normally want to use the SEL_SINGLE
(default) selection type, though it's perfectly possible to use multiple selection.
Here's an example of how to create a popup calendar:
<input id="calendar-inputField" /><button id="calendar-trigger">...</button> <script> Calendar.setup({ trigger : "calendar-trigger", inputField : "calendar-inputField" }); </script>
onSelect
event handlerYou can supply a callback that gets triggered when the selection changes. For example, you might have noticed that the calendar doesn't disappear when you select a date in “popup” mode. Here's how we could make it disappear:
Here is the code that I used for the example above:
Calendar.setup({ inputField : "calendar-field", trigger : "calendar-trigger", onSelect : function() { this.hide() } });
Why doesn't it just close without us needing to add the onSelect
handler? Because not everyone wants it to close—therefore, the new calendar just lets you define the behaviour by writing your own event handler.
Each calendar object, as returned by Calendar.setup(args)
or new Calendar(args)
, contains a "selection
" property. This is an object that you can use to query, clear or reset the current selection.
See the documentation of Selection object.
You can disable dates in two ways. First off, you can use the min and max arguments to the constructor in order to limit the period that the calendar will allow selection in. Example:
|
The above calendar allows selection between 8 April and 25 December 2009. Here's the code that we used:
Calendar.setup({ cont: "sample1", min: 20090408, max: 20091225 });
You can also disable individual dates by supplying a callback function which receives a JS date object and returns true if that date must be disabled, orfalse otherwise. Here's an example which disables all Fridays:
|
Here is the code for the sample above:
Calendar.setup({ cont: "sample2", disabled: function(date) { if (date.getDay() == 5) { return true; } else { return false; } } });
You can write anything you want in the disabled()
handler—just try to make it fast enough, as it will be called many times within milliseconds when the calendar is displayed. Here's one more example, suppose you have in your database a list of dates that should be disabled, just convert them to numeric value and build up a hash table, then your disabled()
handler can very conveniently return true for them:
|
var DISABLED_DATES = { 20090502: true, 20090505: true, 20090510: true, 20090511: true }; Calendar.setup({ cont : "sample3", disabled : function(date) { date = Calendar.dateToInt(date); return date in DISABLED_DATES; } });
The calendar has a feature that allows you to highlight certain dates, or display tooltips when certain dates are hovered. To use this you need to provide a function (using the dateInfo
constructor argument) that receives a JavaScript Date object. It can return null
(or undefined
) if the date isn't special, or a hash containing either or both of the following properties:
klass
— CSS class name to append to that daytooltip
— a tooltip to display when that date is hoveredHere is an example that highlights 7 and 8 May 2009 in red, week 18..24 May 2009 in green and my birthday with a white background every year.
|
We got that with the code below:
var DATE_INFO = { 20090507: { klass: "highlight", tooltip: "That was yesterday" }, 20090508: { klass: "highlight", tooltip: "And this is TODAY" } }; function getDateInfo(date, wantsClassName) { var as_number = Calendar.dateToInt(date); if (String(as_number).indexOf("0308") == 4) { // my birthday :-p return { klass: "birthday", tooltip: "Happy birthday dear me!" }; } if (as_number >= 20090518 && as_number <= 20090524) return { klass : "highlight2", tooltip : "<div style='text-align: center'>%Y/%m/%d (%A)" + "<br />In the green week</div>" // formatted by printDate }; return DATE_INFO[as_number]; }; var cal = Calendar.setup({ cont : "sample4", fdow : 1, date : 20090501, dateInfo : getDateInfo // pass our getDateInfo function });
It's up to you how you write this function. In the sample above we showed how we can use an external variable (DATE_INFO
) that holds the klass and tooltips, as well as converting the date to a number and easily check that it's within a certain interval (to highlight “the green week”). For my birthday I used a hack—convert the date to a string and check that it ends in "0308" (so it will match March 8, any year). The following CSS is included in this page:
.highlight { color: #f00 !important; font-weight: bold } .highlight2 { color: #090 !important; font-weight: bold } .birthday { background: #fff; font-weight: bold } .birthday.DynarchCalendar-day-selected { background: #89f; font-weight: bold }
Assuming you went through the above and read the basics of Selection object you should know enough to use this calendar to full potential. For completeness, following where is detalied API documentation.
Moves the calendar to the given date's year/month (this doesn't change the selection!). If you pass true for animated (default is false) and if animation wasn't disabled through the constructor, then it will animate the switch.
Returns true if the given date (a JavaScript Date object) can be selected.
Shows or hides the menu.
Refreshes the calendar body, title and year input field. If noBody is true then it will not refresh the body. This is used internally, see the next one if you need to redraw the calendar.
Redisplays the whole calendar. You need to call this if you set certain arguments at run time (i.e. min, max, disabled, dateInfo, etc.). You don't need to call it if you modify the selection as it is refreshed automatically.
Sets a new language for the calendar. Pass the language code. More info in internationalization.
Moves focus to the calendar. After you call this, the calendar handles keyboard.
Removes focus from the calendar.
Only for popup calendars. Shows the calendar at the given (x, y) position, optionally animated if animated is true and animation was not disabled through constructor.
Only for popup calendars. Hides the calendar.
You want to use this instead showAt() in order to display the calendar near a certain element. anchor is a reference to a DOM element, or the ID of an element where the calendar is anchored. align is optional (if not given, the one passed to constructor is used, which defaults to "Bl/ / /T/r
".
The align decides where is the calendar displayed in relation to the given anchor element. It is formed of 5 parts joined by "/", in the following order:
Each of them can contain one or two characters. For example, "Bl" means put it completely to the bottom, and at the left (this actually means right-aligned!) to the anchor. See the DlPopup object in DynarchLIB for a comprehensive description of what the alignment characters mean. For the calendar, the significance is pretty much the same except for centering characters ("c"). The calendar uses a "C" for centering horizontally, and "M" for centering vertically; as this ambiguity now no longer exists, you can pass these characters in any order.
You can use this function to setup a single (popup) calendar instance for multiple input fields. See a simple demo. Call this against a calendar object and pass the ID (or a reference) to the trigger button, the input field and the date format as string.
For a calendar configured to display the time selector, this function returns the currently selected time as an integer (hours * 100 + minutes). For example, if 9:45 pm is selected, this method returns 2145
. See also getHours() and getMinutes() below.
Sets the currently selected time. The time
argument is in the same integer format. nohooks
is optional (default false
). If specified true
then this method will not call the onTimeChange
hooks. If unspecified or false
the onTimeChange
hooks will be called two arguments: a reference to the calendar object, and the new time as integer.
Returns the currently selected hour as an integer (0 .. 23). Note that this method will return hours in 24h format regardless if the calendar is currently set in "12h" mode (i.e. when showTime
== 12).
Returns the currently selected minute as an integer (0 .. 59).
Sets the hour in the time selector. The argument must be an integer (0 .. 23).
Sets the minutes in the time selector. The argument must be an integer (0 .. 59). Note that this method does not force m
to a multiple of minuteStep
.
Adds a handler for the given event. As of this writing, event can be "onSelect
" and "onChange
". Note that multiple handlers can exist for an event and they will be called in the order they were registered.
Update: new events added in version 1.5: "onTimeChange
", "onFocus
" and "onBlur
".
Removes the given func handler from the list of registered hooks for the given event.
The following functions can be used globally, without a reference to a Calendar
object.
Expects a JavaScript Date object in date and returns the numeric representation. For example, for May 8 2009 it will return 20090508.
Takes a “numeric date value” and returns a JavaScript Date object. It's the reverse of Calendar.dateToInt()
.
Takes a JavaScript Date object in date and a format specifier and returns a string converting the following:
%a
— abbreviated weekday name%A
— full weekday name%b
— abbreviated month name%B
— full month name%C
— the century number%d
— the day of the month (range 01 to 31)%e
— the day of the month (range 1 to 31)%H
— hour, range 00 to 23 (24h format)%I
— hour, range 01 to 12 (12h format)%j
— day of the year (range 001 to 366)%k
— hour, range 0 to 23 (24h format)%l
— hour, range 1 to 12 (12h format)%m
— month, range 01 to 12%o
— month, range 1 to 12%M
— minute, range 00 to 59%n
— a newline character%p
— PM or AM%P
— pm or am%s
— UNIX time (number of seconds since 1970-01-01)%S
— seconds, range 00 to 59%t
— a tab character%W
— week number%u
— the day of the week (range 1 to 7, 1 = MON)%w
— the day of the week (range 0 to 6, 0 = SUN)%y
— year without the century (range 00 to 99)%Y
— year with the century%%
— a literal '%' characterThis function tries to parse a meaningful date from dateString
and return a JavaScript Date object. In ambiguous situations (i.e. 3-4-2009
) it needs to know if the first digit is the month or the date, which is what monthFirst
is for. Examples:
alert(Calendar.parseDate("3-4-2009", true)); // Mar 04 2009 alert(Calendar.parseDate("3-4-2009", false)); // Apr 03 2009
This function is very forgiving about the format and tries really hard to make up a full date. If it cannot find the year, it will use the year in today
. Same goes for the month. It also supports named months, rather than numeric (in such case there is no ambiguity so monthFirst
is ignored).
A simple templating facility. str is a string template, which can contain variables, like this:
"Hello ${first_name} ${last_name}"
The values for the variables are given in prop. Here's an example:
alert(Calendar.formatString("Hello ${first_name} ${last_name}", { first_name: "John", last_name: "Doe" })); // displays "Hello John Doe"