A Small Calendar Utility For Reference
Posted December 7, 2006 at 3:18 PM by Ben Nadel
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
- <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
- <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
- <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
- 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 ;
- }
Reader Comments
It's delicious!
http://del.icio.us/psenn
Awesome :) Glad you like it. Please feel free to suggest any changes you want to it. Someone already suggested dragging for creating time span.



