Introduction

This article describes the development and usage of the attached calendar script. The calendar generated by the script can be used as a date picker, an event navigator, or simply as a dynamically generated static display. While this script has been tested with Internet Explorer 6.0 and Firefox 0.8 and 1.0, on Windows XP, I have not tested it against other browsers and operating systems. There is a known issue with Internet Explorer on Windows XP SP2; points on working around this are presented below.

Background

When I started this project, it was mainly to create a lightweight and more neatly customizable version of the ASP.NET calendar control. Although I use C# nearly exclusively these days, I come from a Java/JSP background, and still make occasional use of PHP. With this in mind, I wanted something which I could use independently of the server side scripting language being used, without compromising functionality.

There were a few objectives which I wanted to meet with this calendar:

It had to run with little or no maintenance.

It had to be simple enough for a person with little scripting experience to use.

It had to have a simple way of customizing it for multicultural/multilanguage contexts.

It had to provide a transparent fallback mechanism for non-JavaScript browsers.

Although I think I missed the "lightweight" target, I feel that the current implementation achieves all of the above objectives.

Using the code

The calendar script should be referenced like any other external JavaScript file. In order to avoid falling foul of the SP2 script blocking, make sure that you deploy the script file to the same domain as the page calling it.

To set up the calendar, you should use the constructor as shown below:

cal1 = new Calendar ("cal1", "tester", new Date());

The first argument, cname in the script, represents the name by which the script refers to the calendar instance. This should be the same as the name of the variable. (Note: I am still trying to avoid this requirement, as it is rather inelegant. Any suggestion would be appreciated.) The second argument represents the ID of the calendar; this is used by the fallback mechanism to determine which field/s the calendar should control. The last argument is the date to which the calendar will default.

Binding

In order to provide data for a form action, the calendar has to be bound to an input element in a form. This is a two step process; first, you have to give the input an ID appropriate to the calendar ID, and second, you must specify the fallback mode for it.

If you want to bind the calendar to a single text box, define an input element with an ID equal to that given to the calendar as an argument. In other words, the instance cal1 we created above would bind to an element of ID tester. Then, you should specify that the fallback mode is a single field, as described below:

cal1.fallback = cal1.fallback_single;

Creating a calendar feeding three separate fields for day, month and year requires a little more work, but not much. The fields have to be given IDs with the suffixes "_day", "_month" and "_year" respectively; our example would bind to "tester_day", "tester_month" and "tester_year". This done, set the fallback mode to multi:

cal1.fallback = cal1.fallback_multi;

Display

If you test the page at this point, nothing should appear. In order to render the calendar, specify a div element where you wish to place the calendar, and give it an id of "cal_[calendar id]_display", where [calendar id] is the ID of your calendar. In our example, the div ID will be "cal_tester_display".

To render the calendar, call the renderCalendar method, like so:

renderCalendar (cal1);

This will cause the calendar to be displayed in the div. In order to avoid the SP2 block, it might be a good idea to call this explicitly from a user event such as a button or other onclick event, rather than from a script body.

Events

To highlight event dates in your calendar, insert an array of event dates into the calendar's eventDates property, like this:

Overall, I think this is the shakiest area when it comes to configuration. I hope to revisit it soon and polish it up using JavaScript RPCs.

Points of Interest

I hope this project will be of use to others; CodeProject has been very useful to me, and I hope this contribution will, if not used directly, further the education of others; it certainly did mine. The calendar is capable of a few tricks, so please feel free to play around with the properties in the script. Most of these should be self-explanatory; however, I will be pleased to answer any pertinent questions.

Hi DimondWolfe,This script is rather old and I haven't revisited in a while, so I guess it probably has a few kinks to work out in newer browsers . I wrote an updated version for jQuery[^] - just confirmed that it also works in FF4. Hope that helps!

First off, I'd like to say great work, you've saved me much time! I've gotten most of my mods to work (including having the events show up in a predefined div, rather than as an alert), but was wondering what JS code I would need to alter to have only the calendar appear? I'd like to have it without the input fields, and simply have the "next month" and "previous month" buttons. Is this possible?

The calendar is set to require at least one fallback input field. To get rid of the input fields, set the "fallback" property to 0 (It's called fallback_single in the script) and create a hidden field to pass to it. I'm afraid you'll still have to have that field in there, even if you're not actually doing anything with it.

Can we change the way to change the month ?? I want to use "Previous month" and "Next month" button instead of "typing" the date... If we can do that, how to make the existing text box and drop down list to be hidden ?? I tried some methods I know but it just make the calendar gone.

When people click on other date, the today's date no longer selected. How can we make today's date still selected ??

Hi Ditya... sorry for the delay in replying, somehow I missed the notification email.

For your questions:- To make Saturdays count as a regular day, locate the following code in the script:

if ((currentDate.getUTCDay() == 0) || (currentDate.getUTCDay() == 6))

0 is Sunday, and 6 is Saturday - remove the condition for Saturdays to make Saturdays count as regular days.

- To avoid changing the date on click, remove the calls to selectDate in RenderDayEnabled and RenderDayEvent.

- Not sure what you mean about changing the way to change the month. You can set cal.scrollable = true to get the next and previous buttons. The calendar depends on the text boxes and drop downs, so you can't actually remove them; however I guess you could apply a display:none css class to them.

Problem is that I need to make a loop so that 28 days back from the current date are underlined. I am having a lot of problems with that, I am not sure how to add a new sub array to an already exisiting Array. I was thinking of it in terms of putting the above code into one variable and putting the one variable like this:

I think I got the event figured out to where if they click the day, it will open up a new windows with the data, I have a little work to do on the syntax of the window.open method, but I am also trying to display a dynamic webpage, here is an example:

Re. Loops: I'm not sure why you would want to loop the way you described. The javascript would end up very large. You'd probably solve it more easily using some server side technology. Drop me a message if you have any questions

Thanks for all your help, I understand the first part, I believe I was on the same track but using window.open instead, the way you suggested is definatley easier.

As for the loop I basically need it like the below code so that I have 28 new array objects inside the initial array. I, however, would not like to have 28 lines and so fourth to do this, instead I would rather have a loop that would increase the date and corresponding id number like I have below.

So I was thinking to make a variable TestDate = Test Date + new Array(Year, Month, Day, count), so that every time the loop went through it would add another new Array(Year, Month, Day, count), . So when I do the above code in my new setup I would have the following to include all of the subarrays:

cal2.eventDates = new Array(TestDate); This Test Date var would be equal to new Array(Date, Count) + new Array(Date, Count) etc...

But so far only the first "new Array(Date, Count)" works, and the rest do not. But your saying that it would be easier to use a JSP page or soemthing like that? I am not exactly sure how to interact JavaScript with that, any suggestions? Again thanks for all your help!!!

Thanks for all your help, I really appreciate it, the calendar works pretty much like I want it to, the only little thing I want to add to it is when the user clicks on a day that is underlined in the calendar (day with data), a new window appears with the data in it, but if the user goes back to the calendar page they cannot click on the same day they just clicked on without clicking off the day first, is there any easy way I can make it so that the user could click on the same day 1000 times. When the user goes back to the page they were on, the day is boldfaced, which is fine, but the user should be able to click on the day again and it bring up a file (if they accidendtally closed out of the data page).

For example the calendar object I am using has 28 days underlined in blue, in the calendar, to make an illlusion that a hyperlink is there. and there are 28 text files, 1 behind each day in an array like you showed me in a previous post. So if the user clicks a certain day that event ID will be the index of the array that holds the text files and it will open up that text file corresponding to the event ID that was clicked. If the user clicks today's date a text file will come up, showing the data the user needs, but if the user closes out of that window or tabs over to the calendar window and tries to click on the same day again, the link will not be there anymore. How can I get it so they could basically click all day on the same day and it would keep opening a file everytime they click.

You can use the window.open(url, name) function (instead of setting window.location) in the event handler, to pop a window at the location of your file. If you specify the name of the window, the browser will use the same window if you click twice; if the window is not available, it will open a new one. The text file will still get reloaded, but at least, you won't get a few thousand windows running around.

To make the current date clickable, replace the lines in calendar.js containing

Hi,
in the sample attached to this article, the styles are defined in the html header - cal_oddweek for the odd numbered weeks of the month, cal_evenweek for even numbered weeks, and so on. You can either replace the values in these classes, or modify the script so it attaches different class names to the elements. The best way to dothisis to modify the following lines in the javascript file:
<code>
// The css classes for the calendar and header
this.calendarStyle = "cal_calendar";
this.headerStyle = "cal_header";
this.headerCellStyle = "cal_cell";
this.headerCellStyleLabel = "cal_labelcell";
// The css classes for the rows
this.weekStyle = "cal_week";
this.evenWeekStyle = "cal_evenweek";
this.oddWeekStyle = "cal_oddweek";
// The css classes for the day elements
this.dayStyle = "cal_day";
this.disabledDayStyle = "cal_disabled";
this.commonDayStyle = "cal_common";
this.holidayDayStyle = "cal_holiday";
this.eventDayStyle = "cal_event";
this.todayDayStyle = "cal_today";

Hi - great calendar, just what I was looking for. I am going to use it for a website I maintain for a Sports bar. However what I am looking for is a way to do an onmouseover control for a date event that changes an image elsewhere on the same page. The image to remain when the mouse moves off the date until another date is "moused over". Maybe in the future also have a separate click event on the date to bring up a separate page.

My problem? I am not a programmer, I just dabble in things enough to get them working and while the above might be easy to do, I am pretty sure it wouldn't be easy for me! So any and all assistance gratefully received.

This should be pretty simple to do; hooking something of the sort into the onMouseOver for each date should do the trick...

xyz.src = "url of the image";

where xyz is the id of the image you are planning to modify, as in

<img src="default.gif" id="xyz" />

Of course it's not quite that straightforward. For one thing, you'd need to specify the image url somewhere so that the calendar will know what image to load for each date. I'll get back to you on this in a few hours, will hack an example to show you.

The main thing I'd look out for is the ease of use. Having this function fire on mouse over may be a bit tricky to handle for users. Having this work on click might be simpler.

Notes: create an image with id "calendar_target" in the page.the days that are marked as events will now change the image. The image will point to a file called "images/[date].gif", where date is the date on fthe given day in the form yyyymdd. So for example the image for today should be saved as "/images/2006126.gif", while one for the 25th December 2006 would be "/images/20061225.gif"

To add the event, you will need to specify a javascript array and set it in the calendar eventDates property. The best place to do this would be just after you define the calendar object and just before you call the render method to display the calendar.

As a side note, you might want to define the events in a separate file and use a server side include to put them in your own page, assuming you're not generating them from your page itself.

Now, about your question. The answer would depend on what you are using to create your pages. There is no way to create a persistent record using only html and javascript (as far as I know at least) so you'll need some sort of server side script (asp, jsp, php, or whatever). A database of any sort would also be nice, although it is possible to use a file instead and have the script read from and write to it.

The general idea would be to read the events and then use the script to write them. Now, unless you want everyone who visits your page to be able to modify the calendar, you'll also need to have some way to authenticate the user and check that the events entered are valid, and so on. The whole thing would be rather beyond the scope of the calendar itself, so I suggest you look up some other articles in codeproject and then build up your page using them. Feel free to ask if you need any further assistance

when i display the calendar sample and mouse over any day the cursor changes to cursor:text. But i notice in your style section it's listed as cursor:hand (I'm looking at style class ".cal_day"). Am I not looking at this correctly?

I was wondering whether it would be possible to change the background color of some days (of the calendar) based on data retrieved from a text file.Actually, I have a text file with appr. 100 lines. Each line contains a date (DD/MM/YYYY) and a flag (1,2,3). The two fields are separated by a ";". What I would like to do is to read the text file, load the lines in an array and then use the array to change the background of the days.

I have never used js before (mostly vb, vb.net), but I have read that it is not possible to open and read a file with js.Is there amother way to read the file, load the array and then use the calendar code to change the backgroud and show the calendar?