How the Calendar Works
Home How the Calendar Works Calendar Examples Calendar Files

A Brief History of the JavaScript Event Calendar

The core concept of displaying a single month's calendar on-demand, in an HTML table, with embedded events, came from a JavaScript example that I found on the 'net.  It was limited to the 12 months of the current calendar year, allowed you to step a single month at a time (no jumping directly to a month), had the JavaScript source code embedded in the current HTML page, and was rather difficult to maintain events (it required editing an array of strings, one for each month, with each event description preceded by the day number and a delimiter character).

I undertook a major re-write of the original code, including the following:

bulletI moved the core code into an external .JS source file, for better organization and improved performance (it doesn't need to be re-loaded each time the HTML page is refreshed).
bulletI added the ability to jump directly to a month, using a drop-down selection list.
bulletI made the calendar capable of handling ANY range of months, rather than just January - December of the current year.
bulletI decided to use a SPARSE ARRAY to hold all of the event information.  The date is the index into the array (in YYYYMMDD format), and the value stored is the HTML-formatted text string describing that day's event(s).
bulletI wrote a function, DefineEvent( ), that adds an event to the array.  It automatically handles the concatenation of multiple events on the same day.   You pass the following parameters to DefineEvent( ) and it builds the HTML string for you:
bulletThe event date (YYYYMMDD).
bulletA description of the event.
bulletAn optional URL, if you want the description to be a clickable hyperlink to a more detailed description.
bulletAn optional image file URL, if you want to display an image with the event description.
bulletThe width of the image.
bulletThe height of the image.

(Including image width and height of images makes the HTML page load and display faster.)

bulletI changed the hard-coded colors to variables so that they can be configurable as desired.
bulletI changed the hard-coded highlighting of every Sunday to a variable so that any day of each week (e.g., Saturday) can be highlighted.

Meanwhile, because I was working on a calendar for my synagogue, I began to search for ways to easily include Jewish holidays and other information in the calendar.  I didn't want to build that functionality into the JavaScript code; it made more sense to me to include them in the event list.  The challenge was to find a way to automatically generate an event list containing Jewish holidays etc.

Again, I found what I needed on the 'net: a marvelous Jewish calendar utility.  It produces an ASCII list of dates and event descriptions. so I wrote a simple filter (available on my download page) to translate the list into JavaScript calls to the DefineEvent( ) function.  It would then be easy to copy and paste these calls into my HTML page, or better yet, simply save t hem as a .JS file and reference it from my calendar page.

How to Use the Calendar Script

You will need to add two small things to your HTML page, and you'll have a fully functional calendar.

The first addition is a directive to include the external JavaScript program that does all of the work.  Just add the following to your HTML file.  It can go anywhere BEFORE the point where you want to display the calendar.  It does NOT need to be between the <html> and </html> tags, so if you wish you can conveniently place it at the VERY TOP of your HTML file.

<script src="calendar.js"></script>

(You need to have the CALENDAR.JS program on the web server, in the directory where your HTML file is.  You can get the CALENDAR.JS file from my download page.)

Then, at the exact location where you want the calendar to appear, include the following:

<script language="JavaScript">
<!--
Calendar( );
// -->
</script>

The first line indicates the beginning of an in-line JavaScript program. The second line is a tricky way to make sure that older versions of browsers (that don't understand JavaScript) don't "blow up"; they'll simply ignore the rest of the script.  The third line is the important one: it displays the calendar.   The fourth line is another trick for "Java-impaired" browsers, and the fifth line ends the script program.

By calling the Calendar( ) function without first defining any events, and without overriding any of the default configuration settings, you get a calendar with the following characteristics:

bulletit runs from January through December of the current year;
bulletits regularly highlighted "special day" is Sunday;
bulletit highlights the special day in red and the current day (today) in green;
bulletthe calendar background is light yellow;
bulletthere are no events on any of the days!

(To actually see how this looks, study my first example.)

How the Calendar Knows What Month to Display

When you display the calendar it shows the current month.  When you click on one of the hyperlinks (to step to the previous month, to the next month, or to jump to any month in the drop-down list), that month is displayed.  It is important to understand how this works.

The Calendar( ) function defined in the CALENDAR.JS file examines the URL string for the current page.  If it finds a querystring value in the form ?YYYYMM it will display that month.  Otherwise, it will display the current month.  The hyperlinks simply direct the client browser back to the current page, with an explicit month in the URL string.

For example, if your page is called "mycalendar.html," and your web site lives under "www.mydomain.com," a user who visits http://www.mydomain.com/mycalendar.html will see the calendar for the current month.  Clicking on a hyperlink for, say, February 2003 will redirect the client's browser to http://www.mydomain.com/mycalendar.html?200302.    It is important to be aware of this, especially if you need to include other values in the URL string.

How to Define Events

The CALENDAR.JS file that you include in your HTML page contains a function called DefineEvent( ) that you can call in your page prior to calling Calendar( ) to display the calendar.

For example, I can include my birthday and my anniversary for 2003 as follows:

<script language="JavaScript">
<!--
DefineEvent(20030705, "Kevin's <big><font color=red>44th</font></big> birthday", "http://www.ilsen.net", "images/birthday.gif", 62, 50);
DefineEvent(20031130, "Kevin and Barbara's Anniversary", "", "", 0, 0);
Calendar( );
// -->
</script>

Notice that you call DefineEvent( ) for each event, passing in the parameters as defined above.  You can define the events in any order you wish.

The event description can include embedded HTML tags for formatting.  For example, you can set the font size, color, or other attributes (bold, blink, etc.).  Don't forget to use a closing </> tag for each tag that you use!

If you wish, you can include a hyperlink and/or an image.  The hyperlink URL and image path will be relative to the current HTML page, so if you like to keep your images in a special subdirectory, remember to include the subdirectory in the image reference.

Recall that the default behavior of the calendar is to allow access to January - December of the current year.  Each time you add an event, the range is automatically expanded to include the month in which the event occurs.  Thus, if the code above is processed anytime during 2002, the resulting range will be January 2002 - November 2003.  If it is processed anytime during 2004, the resulting range will be July 2003 - December 2004.  And if it processed anytime during 2003, the resulting range will remain January 2003 - December 2003.

(It is easy to override the range after you have defined the events.)

(To actually see how this looks, study my second example.)

How to Use External Files to Define Events

If you have a lot of events, and you regularly maintain/update the list, and would rather NOT edit your HTML code each time you need to make a change, you can easily put all of your event definitions in a separate file.  In fact, you can use MULTIPLE external files, one for each type of event.

For example, on my synagogue's web page, I set up two event files, one containing the "standard" Jewish holidays etc., and the other containing specific events for my synagogue.  To illustrate the point, here are abbreviated versions:

HEVENTS.JS
DefineEvent(19980211, "Tu B'Shvat", "", "", 0, 0);
DefineEvent(19980312, "Purim", "", "", 0, 0);
DefineEvent(19980410, "Erev Pesach", "", "", 0, 0);
DefineEvent(19980411, "Pesach I", "", "", 0, 0);
DefineEvent(19980412, "Pesach II", "", "", 0, 0);
DefineEvent(19980423, "Yom HaShoah", "", "", 0, 0);
DefineEvent(19980531, "Shavuot I", "", "", 0, 0);
DefineEvent(19980601, "Shavuot II", "", "", 0, 0);
DefineEvent(19980802, "Tish'a B'Av", "", "", 0, 0);
DefineEvent(19980921, "Rosh Hashana 5759", "", "", 0, 0);
DefineEvent(19980922, "Rosh Hashana II", "", "", 0, 0);
DefineEvent(19980930, "Yom Kippur", "", "", 0, 0);
DefineEvent(19981005, "Sukkot I", "", "", 0, 0);
DefineEvent(19981006, "Sukkot II", "", "", 0, 0);
DefineEvent(19981012, "Shmini Atzeret", "", "", 0, 0);
DefineEvent(19981013, "Simchat Torah", "", "", 0, 0);
DefineEvent(19981213, "Chanukah: 1 Candle", "", "images/menorah.gif", 52, 52);
DefineEvent(19981214, "Chanukah: 2 Candles", "", "images/menorah.gif", 52, 52);
DefineEvent(19981215, "Chanukah: 3 Candles", "", "images/menorah.gif", 52, 52);
DefineEvent(19981216, "Chanukah: 4 Candles", "", "images/menorah.gif", 52, 52);
DefineEvent(19981217, "Chanukah: 5 Candles", "", "images/menorah.gif", 52, 52);
DefineEvent(19981218, "Chanukah: 6 Candles", "", "images/menorah.gif", 52, 52);
DefineEvent(19981219, "Chanukah: 7 Candles", "", "images/menorah.gif", 52, 52);
DefineEvent(19981220, "Chanukah: 8 Candles", "", "images/menorah.gif", 52, 52);
DefineEvent(19981221, "Chanukah: 8th Day", "", "", 0, 0);

 

EVENTS.JS
DefineEvent(19981101, "Religious School<BR>Parents' Night<BR>and Book Fair", "", "", 0, 0);
DefineEvent(19981103, "Book Fair", "", "", 0, 0);
DefineEvent(19981107, "Jr. Cong.", "services.htm", "", 0, 0);
DefineEvent(19981108, "Book Fair", "", "", 0, 0);
DefineEvent(19981113, "Religious School<BR>Gimel/Dalet<BR>Kabbalat Shabbat<BR>and Dinner", "", "", 0, 0);
DefineEvent(19981114, "Tot Shabbat", "services.htm", "", 0, 0);
DefineEvent(19981117, "Kosher Food Co-Op<BR>Order Date", "", "", 0, 0);
DefineEvent(19981118, "Sisterhood<BR>Aerobics Night", "", "", 0, 0);
DefineEvent(19981121, "Family Service", "services.htm", "", 0, 0);
DefineEvent(19981122, "Brotherhood breakfast", "", "", 0, 0);
DefineEvent(19981128, "Breakfast<BR>or brunch with<BR>college kids", "", "", 0, 0);
DefineEvent(19981213, "<strong>First Light Celebration<BR>4:00 PM - 6:00 PM</strong>", "", "", 0, 0);

// Scheduled adult ed classes (link to adulted page)
DefineEvent(19981105, "Basic Hebrew Reading Class", "adulted.htm", "", 0, 0);
DefineEvent(19981112, "Basic Hebrew Reading Class", "adulted.htm", "", 0, 0);
DefineEvent(19981119, "Basic Hebrew Reading Class", "adulted.htm", "", 0, 0);
DefineEvent(19981115, "Kashrut in the 90s Class", "adulted.htm", "", 0, 0);
DefineEvent(19981122, "Kashrut in the 90s Class", "adulted.htm", "", 0, 0);
DefineEvent(19981102, "Introduction to Talmud Class", "adulted.htm", "", 0, 0);
DefineEvent(19981109, "Introduction to Talmud Class", "adulted.htm", "", 0, 0);
DefineEvent(19981121, "Spirituality at Sunset Class", "adulted.htm", "", 0, 0);
DefineEvent(19981219, "Spirituality at Sunset Class", "adulted.htm", "", 0, 0);
DefineEvent(19981204, "Ask the Rabbi<BR>(6:15 Services)", "adulted.htm", "", 0, 0);

To include all of the events in these two external files, use the following lines in your HTML page:

<script src="hevents.js"></script>
<script src="events.js"></script>
<script language="JavaScript">
<!--
Calendar( );
// -->
</script>

(To actually see how this looks, study my third example.)

How to Override the Default Configuration Settings

In addition to containing all of the source code for the Calendar( ) and DefineEvent( ) functions, the CALENDAR.JS file defines several variables and initializes them to default values.  By overriding these defaults just before you call Calendar( ), you can alter the appearance of the calendar to suit you tastes.

Variable Default Description
SpecialDay 1 Day of the week to highlight.  1 = Sunday (default), 2 = Monday, . . . 7 = Saturday.  To disable day-of-week highlighting, set SpecialDay=0 or SpecialDay=-1.
FontSize 5 Font size for the calendar day numbers.  Can be between 1 and 7; 1 is smallest, 7 the largest.
ColorBackground "ffffcc" Color for the background of the calendar.  Hexadecimal color numbers may be used (RRGGBB) or color names (which might be implemented differently by different browsers).  Be sure to enclose in quotes!
ColorSpecialDay "red" Color for highlighting the special day of the week.
ColorToday "green" Color for highlighting today's date.
ColorEvent "blue" Color for highlighting each defined event.
FirstMonth With no events defined, FirstMonth defaults to January of the current year (e.g., 199801) and LastMonth defaults to December of the current year (e.g., 199812).  Each time you call DefineEvent( ), the values are adjusted if necessary so that the range includes the month in which the event occurs.   It is sometimes desirable to override the automatic values; for example, if you only have events in November 1998 and December 1998, and you don't want to include January - October, set FirstMonth=199811 (after all calls to DefineEvent( ) are made).
LastMonth

(For an illustration, study my second example.)

How to Use the JEC.EXE Filter

If you have a large number of events to define, the syntax of the DefineEvent( ) function can become tedious.  You can download my filter program that transforms a plain ASCII list of events into a series of calls to DefineEvent( ).

JEC is a DOS program (no, really; I'm not kidding!) that reads "standard input" and writes "standard output."  The input is a series of events, one per line, in the following format:

M/D/YYYY Description

JEC produces output as a series of calls to DefineEvent( ), one per line, in the following format:

DefineEvent(YYYYMMDD, "Description", "", "", 0, 0);

For example:

1/1/1999 New Year's Day
7/4/1999 Independence Day
11/25/1999 Thanksgiving

If you have this information in a file (for example, EVENTS.TXT) and you tell JEC to process the file, it will produce the following output:

DefineEvent(19990101, "New Year's Day", "", "", 0, 0);
DefineEvent(19990704, "Independence Day", "", "", 0, 0);
DefineEvent(19991125, "Thanksgiving", "", "", 0, 0);

You can use the DOS command syntax to have JEC automatically write this information to a file.  For example, the following command runs JEC, taking its input from a file called EVENTS.TXT and writing its output to a file called EVENTS.JS:

JEC <EVENTS.TXT >EVENTS.JS

At this point you could edit the EVENTS.JS file if desired, to add hyperlinks and/or images in the DefineEvent( ) calls.

How to Create Events with the HEBCAL Program

The JEC filter program is very useful if you are using Danny Sadinoff's Hebcal Program to generate events from the Jewish calendar.  The default output format of HEBCAL happens to be the exact input format for which JEC was designed.  For example, running HEBCAL with the following syntax:

HEBCAL 12 1998

produces the following results:

12/13/1998 Chanukah: 1 Candle
12/14/1998 Chanukah: 2 Candles
12/15/1998 Chanukah: 3 Candles
12/16/1998 Chanukah: 4 Candles
12/17/1998 Chanukah: 5 Candles
12/18/1998 Chanukah: 6 Candles
12/19/1998 Rosh Chodesh Tevet
12/19/1998 Channukah: 7 Candles
12/20/1998 Rosh Chodesh Tevet
12/20/1998 Channukah: 8 Candles
12/21/1998 Channukah: 8th Day
12/29/1998 Asara B'Tevet

Using the DOS "pipe" command syntax, you can send the output from HEBCAL directly into JEC, and from there save it in a file called, for example, HEVENTS.JS:

HEBCAL 12 1998 | JEC >HEVENTS.JS

The HEVENTS.JS file would contain:

DefineEvent(19981213, "Chanukah: 1 Candle", "", "", 0, 0);
DefineEvent(19981214, "Chanukah: 2 Candles", "", "", 0, 0);
DefineEvent(19981215, "Chanukah: 3 Candles", "", "", 0, 0);
DefineEvent(19981216, "Chanukah: 4 Candles", "", "", 0, 0);
DefineEvent(19981217, "Chanukah: 5 Candles", "", "", 0, 0);
DefineEvent(19981218, "Chanukah: 6 Candles", "", "", 0, 0);
DefineEvent(19981219, "Rosh Chodesh Tevet", "", "", 0, 0);
DefineEvent(19981219, "Channukah: 7 Candles", "", "", 0, 0);
DefineEvent(19981220, "Rosh Chodesh Tevet", "", "", 0, 0);
DefineEvent(19981220, "Channukah: 8 Candles", "", "", 0, 0);
DefineEvent(19981221, "Channukah: 8th Day", "", "", 0, 0);
DefineEvent(19981229, "Asara B'Tevet", "", "", 0, 0);

HEBCAL accepts various command line options (refer to the HEBCAL documentation); any options that you specify will affect the selection of events that are passed through JEC.   For example, you can choose to suppress or include Rosh Chodesh, candlelighting times, standard holidays, yahrzeits, etc.

Using these tools, it is possible to take much of the manual editing out of the process of creating the calendar.  You can be even more creative; for example, run one pass of HEBCAL and JEC to produce a file of standard holidays, and a separate pass to produce just the candlelighting times (in a separate file!).  Then edit the .JS file containing the candlelighting times, and use global search and replace to insert a candlesticks image reference, width, and height on all of the lines (replacing the "", 0, 0 at the end of each line).  Then run a third pass to produce just the names of the parshiyoth, and again use global search and replace to insert a Torah scroll image reference!  By creating separate JS files using HEBCAL and JEC, you can let your editor do more of the work for you.

Credits

Although I was not able to find a ready-made calendar that was EXACTLY what I was looking for, I did stumble across an EXCELLENT first draft, along with a large number of other free JavaScript samples, on a site called Cut-n-Paste JavaScript. (Unfortunately, that site is no longer available.)

Tackling the arcane details of the Jewish calendar and its relationship to the Gregorian calendar that rules our lives was something I hoped to avoid.  Just when I thought I would have to dive into the code, I found a tremendous implementation - Danny Sadinoff's Hebcal Program.   Among its other versatile features, this remarkable little program can generate a list of events paired with their Gregorian dates.  The events include the Jewish holidays, Rosh Chodesh, days of the omer, names of the parshiyoth, Shabbat, havdalah, and holiday candlelighting times (based on your location), as well as yahrzeits.  By default it generates the dates for the current year, but it can be directed to do any year or any month or even any individual day.