A Small Calendar Utility For Reference

Posted December 7, 2006 at 3:18 PM

Tags: ColdFusion, Javascript / DHTML

I created a rather small calendar utility for use during project management meetings. We usually brain storm a project and use the Windows date/time calendar (in the icon tray) to think out our time estimates. The problem is that calendar sucks and only has one month at a time (and moving from month to month is a pain). My small calendar utility, written in ColdFusion with some Javascript, displays a year's worth of calendars and allows the user to click and highlight a single time span.

Feel free to use it if you like:

http://www.bennadel.com/util/calendar

If anyone is interested in the code that goes behind this, it's fairly small.

Action Script

 Launch code in new window » Download code as text file »

  • <cfscript>
  •  
  • // Get the current month.
  • REQUEST.ThisMonth = CreateDate(
  • Year( REQUEST.Environment.DateTime.Now ),
  • Month( REQUEST.Environment.DateTime.Now ),
  • 1
  • );
  •  
  •  
  • // Create an array of months.
  • REQUEST.Months = ArrayNew( 1 );
  •  
  • // Add a date for each month to the array. Right now, we are going
  • // to be using one month previous to this one, plus 11 months going
  • // forward. This should give us just over a year going forward.
  • for (intI = -1 ; intI LTE 12 ; intI = (intI + 1)){
  •  
  • ArrayAppend(
  • REQUEST.Months,
  • DateAdd( "m", intI, REQUEST.ThisMonth )
  • );
  •  
  • }
  •  
  •  
  • </cfscript>

Java Script Code

 Launch code in new window » Download code as text file »

  • <script type="text/javascript">
  •  
  • // These are the global variables neede to keep track of
  • // the calendar and to provide faster lookup via indexing.
  • var objStartDay = null;
  • var objEndDay = null;
  • var arrDays = new Array();
  • var objToday = null;
  •  
  •  
  • // This loads the global properties based on the calendar.
  • function InitCalendars(){
  • var objHolder = document.getElementById( "calendars" );
  • var arrTBody = objHolder.getElementsByTagName( "tbody" );
  • var arrTD = null;
  • var intI, intJ;
  •  
  • // Loop over tbodys and get their tds.
  • for (intI = 0 ; intI < arrTBody.length ; intI++){
  •  
  • // Get all the TDs.
  • arrTD = arrTBody[ intI ].getElementsByTagName( "td" );
  •  
  • // Loop over all the TDs to init.
  • for (intJ = 0 ; intJ < arrTD.length ; intJ ++){
  •  
  • InitTD( arrTD[ intJ ] );
  •  
  • }
  •  
  • }
  •  
  • }
  •  
  •  
  • // This initialized each TD within the calendar days.
  • function InitTD( objTD ){
  • // Set the TD collection index.
  • objTD.dayIndex = arrDays.length;
  •  
  • // Add this TD to the collection.
  • arrDays[ arrDays.length ] = objTD;
  •  
  • // Store the original class name.
  • objTD.baseClassName = objTD.className;
  •  
  • // Check to see if this is today.
  • if (objTD.className == "today"){
  • objToday = objTD;
  • }
  •  
  • // Set onclick handler.
  • objTD.onclick = function(){
  • SetDay( this );
  • }
  • }
  •  
  •  
  • // This is the onClick handler for each calendar day. It is
  • // used to set the start and end days of the selected day span,
  • // then it renders the calendar.
  • function SetDay( objTD ){
  •  
  • // We can only set a day that is NOT an other month. If this
  • // an other day, just return out.
  • if (objTD.className == "othermonth"){
  • return;
  • }
  •  
  • // Check to see if we if this is the day one.
  • if (objTD == objStartDay){
  •  
  • // Set the start day to be the end day.
  • objStartDay = objEndDay;
  •  
  • // Turn off end day.
  • objEndDay = null;
  •  
  • } else if (objTD == objEndDay){
  •  
  • // Turn off the end day.
  • objEndDay = null;
  •  
  • } else {
  •  
  • // We are turning ON a day. Check to see if there is an
  • // existing start and end day.
  • if (objStartDay && objEndDay){
  •  
  • // Both days already exist. We need to alter the
  • // way the selection exists. Check to see the
  • // indexes.
  • if (objTD.dayIndex < objStartDay.dayIndex){
  •  
  • // Expanding back.
  • objStartDay = objTD;
  •  
  • } else {
  •  
  • // We are going beyong the end day OR we are
  • // going somewhere in the middle of the
  • // existing range. Either way, when we do that,
  • // we are always going to change the END day,
  • // not the Start day.
  • objEndDay = objTD;
  •  
  • }
  •  
  • } else if (objStartDay){
  •  
  • // Check to see if the new TD is less than or
  • // greater than the current start day.
  • if (objStartDay.dayIndex < objTD.dayIndex){
  •  
  • objEndDay = objTD;
  •  
  • } else {
  •  
  • objEndDay = objStartDay;
  • objStartDay = objTD;
  • }
  •  
  • } else {
  •  
  • // We will never have JUST an end day. Set this to
  • // the start day.
  • objStartDay = objTD;
  •  
  • }
  •  
  • }
  •  
  •  
  • // Render the calendar with the new time span.
  • RenderCalendar();
  •  
  • }
  •  
  •  
  • // This renders the calendar and turns the days on or off
  • // depending on where they fall in any selected time span.
  • function RenderCalendar(){
  • var intDay = null;
  •  
  • // Loop over all the days in the collection.
  • for (intDay = 0 ; intDay < arrDays.length ; intDay++){
  •  
  • // We cannot do anything to other month days. If this
  • // is an other month day, just continue the loop.
  • if (arrDays[ intDay ].className == "othermonth"){
  • continue;
  • }
  •  
  • // Check to see if we have both start and end day.
  • if (
  • objStartDay &&
  • objEndDay &&
  • (objStartDay.dayIndex <= arrDays[ intDay ].dayIndex) &&
  • (objEndDay.dayIndex >= arrDays[ intDay ].dayIndex)
  • ){
  •  
  • // This is a selected day.
  • arrDays[ intDay ].className = (
  • ( (arrDays[ intDay ] == objToday) ? "today" : "" ) +
  • "selected"
  • );
  •  
  • } else if (
  • (arrDays[ intDay ] == objStartDay) ||
  • (arrDays[ intDay ] == objEndDay)
  • ){
  •  
  • // This is a selected day.
  • arrDays[ intDay ].className = (
  • ( (arrDays[ intDay ] == objToday) ? "today" : "" ) +
  • "selected"
  • );
  •  
  • } else {
  •  
  • // This is NOT a selected day. Turn off.
  • arrDays[ intDay ].className = arrDays[ intDay ].baseClassName;
  •  
  • }
  •  
  • }
  •  
  • }
  •  
  • </script>

Calendar Display Code

 Launch code in new window » Download code as text file »

  • <div id="calendars">
  •  
  • <!--- Loop over the months in the array. --->
  • <cfloop
  • index="intI"
  • from="1"
  • to="#ArrayLen( REQUEST.Months )#"
  • step="1">
  •  
  • <cfsilent>
  •  
  • <!--- Get the pointer to the current date. --->
  • <cfset dtThisMonth = REQUEST.Months[ intI ] />
  •  
  • <!--- Get the starting day. --->
  • <cfset dtStartDay = DateAdd(
  • "d",
  • -(DayOfWeek( dtThisMonth ) - 1),
  • dtThisMonth
  • ) />
  •  
  • <!--- Get the ending day. --->
  • <cfset dtEndDay = (DateAdd( "m", 1, dtThisMonth ) - 1) />
  •  
  • <!--- Stretch it to the end of the week. --->
  • <cfset dtEndDay = DateAdd(
  • "d",
  • (7 - DayOfWeek( dtEndDay )),
  • dtEndDay
  • ) />
  •  
  •  
  • <!--- Get today's date. --->
  • <cfset dtToday = Fix( REQUEST.Environment.DateTime.Now ) />
  •  
  • </cfsilent>
  •  
  • <table width="100%" border="0" cellspacing="2" cellpadding="0" class="calendarmonth">
  • <thead>
  • <tr>
  • <td colspan="7">
  • #MonthAsString( Month( dtThisMonth ) )# #Year( dtThisMonth )#
  • </td>
  • </tr>
  • </thead>
  • <tbody>
  • <cfsilent>
  • <cfsavecontent variable="strMonthCode">
  •  
  • <tr>
  •  
  • <!--- Loop over the days of the month. --->
  • <cfloop index="dtDay" from="#dtStartDay#" to="#dtEndDay#" step="1">
  •  
  • <td class="<cfif (dtDay EQ dtToday)>today<cfelseif (Month( dtDay ) EQ Month( dtThisMonth ))>thismonth<cfelse>othermonth</cfif>">
  • #Day( dtDay )#
  • </td>
  •  
  • <cfif (
  • (DayOfWeek( dtDay ) EQ 7) AND
  • (dtDay NEQ dtEndDay)
  • )>
  • </tr>
  • <tr>
  • </cfif>
  •  
  • </cfloop>
  •  
  • </tr>
  •  
  • </cfsavecontent>
  • </cfsilent>
  •  
  • <!--- Output code with as little white space as possible. --->
  • #strMonthCode.ReplaceAll( ">\s+", ">" ).ReplaceAll( "\s+<", "<" )#
  • </tbody>
  • </table>
  •  
  • <!--- Flush for user feedback. --->
  • <cfflush />
  •  
  • </cfloop>
  •  
  • </div>
  •  
  • <!--- Initialize the Calendar javascript. --->
  • <script type="text/javascript">
  • InitCalendars();
  • </script>

CSS Code

 Launch code in new window » Download code as text file »

  • table.calendarmonth {
  • margin-bottom: 20px ;
  • }
  •  
  • table.calendarmonth td {
  • border: 1px solid #999999 ;
  • cursor: default ;
  • padding: 5px 10px 5px 10px ;
  • }
  •  
  • table.calendarmonth thead td {
  • background-color: #F0F0F0 ;
  • border-bottom-width: 2px ;
  • font-size: 12px ;
  • font-weight: bold ;
  • text-align: center ;
  • }
  •  
  • table.calendarmonth td.today {
  • background-color: #FEEAB7 ;
  • border-color: #333333 ; /* #E4A705 ; */
  • font-weight: bold ;
  • }
  •  
  • table.calendarmonth td.thismonth {}
  •  
  • table.calendarmonth td.othermonth {
  • background-color: #EAEAEA ;
  • border-color: #999999 ;
  • color: #AAAAAA ;
  • }
  •  
  • table.calendarmonth td.selected {
  • background-color: #FFE8E1 ;
  • border-color: #FF3333 ;
  • /* color: #FA3E0A ; */
  • }
  •  
  • table.calendarmonth td.todayselected {
  • background-color: #FFB8A4 ;
  • border-color: #FF3333 ;
  • font-weight: bold ;
  • }

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Permalink  |  Other Searches  |  Print Page



Learning ColdFusion 9 - ColdFusion 9 tutorials, samples, examples, demos

Reader Comments

Dec 13, 2006 at 6:13 PM // reply »
16 Comments

It's delicious!
http://del.icio.us/psenn


Dec 13, 2006 at 6:55 PM // reply »
6,371 Comments

Awesome :) Glad you like it. Please feel free to suggest any changes you want to it. Someone already suggested dragging for creating time span.


Post Comment  |  Ask Ben

Recent Blog Comments
Nov 7, 2009 at 5:53 PM
Ask Ben: Javascript String Replace Method
You can find here an advanced function that prepared with javascript replace function. This can make the first letters of words, sentences, lines and whatever you define automatically: http://www.m ... read »
Andrew Neely
Nov 7, 2009 at 4:56 PM
A Moment That Touched Me - The Fountainhead
Ben, Glad you enjoyed the podcast. Yeah, the Tank Riot guys can get really chatty during the episodes, but that's part of the charm of it for me. They've covered everything from Nichola Tesla to Cha ... read »
Nov 7, 2009 at 4:43 PM
Building A Fixed-Position Bottom Menu Bar (ala FaceBook)
Is it possible to make some more MenĂ¼`s ? ... read »
Jill
Nov 7, 2009 at 11:40 AM
How To Unformat Your Code (Like A Pro)
Derek, I think you might be right - sweet! Thanks for the link :) ... read »
Nov 7, 2009 at 11:25 AM
How To Unformat Your Code (Like A Pro)
I think it would be way easier to just use this http://www.logichammer.com/html-formatter/ He just released v3 and it rocks. ... read »
Jill
Nov 7, 2009 at 7:58 AM
How To Unformat Your Code (Like A Pro)
LMAO - this was pretty funny! I have to admit - I also love to reformat code so I can read it. My boss used to tell me to leave my OCD at home. Now I don't feel so bad after reading everyone else' ... read »
Nov 6, 2009 at 10:10 PM
How To Unformat Your Code (Like A Pro)
The timing of this post is just uncanny. I spent the last 15-20 minutes manually un-formatting my "Ben Nadel" style code within a CFC of mine. I was really digging the readability a few weeks ago, bu ... read »
Roe
Nov 6, 2009 at 5:11 PM
Passing Arrays By Reference In ColdFusion - SWEEET!
ArraySort also reorders the results of these java obj's ... read »