- Publicity: Public Only All
acs-calendar-2-procs.tcl
Library for calendar display widgets
- Location:
- packages/acs-datetime/tcl/acs-calendar-2-procs.tcl
- Created:
- 2000-11-21
- Author:
- ron@arsdigita.com
- CVS Identification:
$Id: acs-calendar-2-procs.tcl,v 1.46.2.3 2021/12/28 14:49:49 antoniop Exp $
Procedures in this file
- dt_hour_diff (public, deprecated)
- dt_midnight_p (public)
- dt_no_time_p (public)
- dt_widget_day (public, deprecated)
- dt_widget_list (public, deprecated)
- dt_widget_week (public, deprecated)
Detailed information
dt_hour_diff (public, deprecated)
dt_hour_diff -start_time start_time -end_time end_time
Deprecated. Invoking this procedure generates a warning.
24-hour times input (23:00,02:00). This gives us the num of hours of difference, taking into account that if something goes until 5:01, it is one more hour long than if it goes until 5:00 DEPRECATED: this is really something one should do leveraging existing tcl capabilities. Plain clock idioms can do the same in a more generic and reliable way.
- Switches:
- -start_time (required)
- -end_time (required)
- See Also:
- clock
- Partial Call Graph (max 5 caller/called nodes):
- Testcases:
- No testcase defined.
dt_midnight_p (public)
dt_midnight_p time
Check if a time is midnight. This might be replaced by clock idioms in the future, but is currently the way we decide e.g. if an event is an all-day event.
- Parameters:
- time (required)
- See Also:
- Partial Call Graph (max 5 caller/called nodes):
- Testcases:
- dt_midnight_p
dt_no_time_p (public)
dt_no_time_p -start_time start_time -end_time end_time
This decides whether an item is without a time, which is also our definition of an all-day event.
- Switches:
- -start_time (required)
- -end_time (required)
- Partial Call Graph (max 5 caller/called nodes):
- Testcases:
- dt_midnight_p
dt_widget_day (public, deprecated)
dt_widget_day [ -calendar_details calendar_details ] [ -date date ] \ [ -hour_template hour_template ] [ -start_hour start_hour ] \ [ -end_hour end_hour ] [ -show_nav show_nav ] \ [ -prev_nav_template prev_nav_template ] \ [ -next_nav_template next_nav_template ] \ [ -master_bgcolor master_bgcolor ] \ [ -header_bgcolor header_bgcolor ] \ [ -header_text_color header_text_color ] \ [ -header_text_size header_text_size ] \ [ -calendar_width calendar_width ] [ -day_bgcolor day_bgcolor ] \ [ -today_bgcolor today_bgcolor ] \ [ -day_text_color day_text_color ] \ [ -empty_bgcolor empty_bgcolor ] [ -overlap_p overlap_p ]
Deprecated. Invoking this procedure generates a warning.
Returns a calendar for a specific day, with details supplied by hour. Defaults to today. DEPRECATED: this proc uses hardcoded markup and is therefore difficult to style. It is also not localized. Many of the date operations happening here have now good tcl support through the clock api, which would make this code probably faster. Future reimplementations should leverage the templating system more.
- Switches:
- -calendar_details (optional)
- -date (optional)
- -hour_template (optional, defaults to
"$display_hour"
)- -start_hour (optional, defaults to
"0"
)- -end_hour (optional, defaults to
"23"
)- -show_nav (optional, defaults to
"1"
)- -prev_nav_template (optional, defaults to
"<a href="?date=[ns_urlencode $yesterday]"><img border="0" src="[dt_left_arrow]" alt="[_ acs-datetime.back_one_day]"></a>"
)- -next_nav_template (optional, defaults to
"<a href="?date=[ns_urlencode $tomorrow]"><img border="0" src="[dt_right_arrow]" alt="[_ acs-datetime.forward_one_day]"></a>"
)- -master_bgcolor (optional, defaults to
"black"
)- -header_bgcolor (optional, defaults to
"black"
)- -header_text_color (optional, defaults to
"white"
)- -header_text_size (optional, defaults to
"+2"
)- -calendar_width (optional, defaults to
"100%"
)- -day_bgcolor (optional, defaults to
"#DDDDDD"
)- -today_bgcolor (optional, defaults to
"yellow"
)- -day_text_color (optional, defaults to
"white"
)- -empty_bgcolor (optional, defaults to
"white"
)- -overlap_p (optional, defaults to
"0"
)- See Also:
- Partial Call Graph (max 5 caller/called nodes):
- Testcases:
- No testcase defined.
dt_widget_list (public, deprecated)
dt_widget_list -calendar_details calendar_details \ [ -item_template item_template ] [ -start_date start_date ] \ [ -end_date end_date ] [ -order_by order_by ] \ [ -url_template url_template ]
Deprecated. Invoking this procedure generates a warning.
create a listing widget for lists (ben) I would like to ask forgiveness from the coding gods for this proc. Right now this is a big hack to make the schedule look a lot like the SloanSpace v1.0 display. Once we have thought this through a bit more, I will generalize this proc. I promise. Please forgive me. DEPRECATED: time is up Ben. This proc uses hardcoded markup and is therefore difficult to style. It is also not fully localized. Future reimplementations should leverage the templating system more.
- Switches:
- -calendar_details (required)
- -item_template (optional, defaults to
"$item"
)- -start_date (optional)
- -end_date (optional)
- -order_by (optional)
- -url_template (optional, defaults to
"?order_by=$order_by"
)- See Also:
- Partial Call Graph (max 5 caller/called nodes):
- Testcases:
- No testcase defined.
dt_widget_week (public, deprecated)
dt_widget_week [ -calendar_details calendar_details ] [ -date date ] \ [ -large_calendar_p large_calendar_p ] \ [ -master_bgcolor master_bgcolor ] \ [ -header_bgcolor header_bgcolor ] \ [ -header_text_color header_text_color ] \ [ -header_text_size header_text_size ] \ [ -day_template day_template ] \ [ -day_header_size day_header_size ] \ [ -day_header_bgcolor day_header_bgcolor ] \ [ -calendar_width calendar_width ] [ -day_bgcolor day_bgcolor ] \ [ -today_bgcolor today_bgcolor ] \ [ -day_text_color day_text_color ] \ [ -empty_bgcolor empty_bgcolor ] \ [ -next_week_template next_week_template ] \ [ -prev_week_template prev_week_template ] \ [ -prev_next_links_in_title prev_next_links_in_title ] \ [ -fill_all_days fill_all_days ]
Deprecated. Invoking this procedure generates a warning.
Returns a calendar for a specific week, with details supplied by Julian date. Defaults to this week. To specify details for the individual days (if large_calendar_p is set) put data in an ns_set calendar_details. The key is the Julian date of the day, and the value is a string (possibly with HTML formatting) that represents the details. The variables in the templates are: - day_template: julian,day,date,pretty_date - next_week_template: - prev_week_template: DEPRECATED: this proc uses hardcoded markup and is therefore difficult to style. It is also not localized. Many of the date operations happening here have now good tcl support through the clock api, which would make this code probably faster and certainly portable (Oracle query is missing). Future reimplementations should leverage the templating system more.
- Switches:
- -calendar_details (optional)
- -date (optional)
- -large_calendar_p (optional, defaults to
"1"
)- -master_bgcolor (optional)
- -header_bgcolor (optional)
- -header_text_color (optional, defaults to
"white"
)- -header_text_size (optional, defaults to
"+2"
)- -day_template (optional, defaults to
"<!--$julian-->$day"
)- -day_header_size (optional, defaults to
"2"
)- -day_header_bgcolor (optional, defaults to
"#666666"
)- -calendar_width (optional, defaults to
"100%"
)- -day_bgcolor (optional, defaults to
"#DCDCDC"
)- -today_bgcolor (optional, defaults to
"#FFF8DC"
)- -day_text_color (optional, defaults to
"white"
)- -empty_bgcolor (optional, defaults to
"white"
)- -next_week_template (optional)
- -prev_week_template (optional)
- -prev_next_links_in_title (optional, defaults to
"0"
)- -fill_all_days (optional, defaults to
"0"
)- See Also:
- Partial Call Graph (max 5 caller/called nodes):
- Testcases:
- No testcase defined.
Content File Source
# /packages/acs-datetime/tcl/acs-calendar-procs.tcl ad_library { Library for calendar display widgets @author ron@arsdigita.com @creation-date 2000-11-21 @cvs-id $Id: acs-calendar-2-procs.tcl,v 1.46.2.3 2021/12/28 14:49:49 antoniop Exp $ } d_proc -deprecated dt_widget_week { {-calendar_details ""} {-date ""} {-large_calendar_p 1} {-master_bgcolor ""} {-header_bgcolor ""} {-header_text_color "white"} {-header_text_size "+2"} {-day_template {<!--$julian-->$day}} {-day_header_size 2} {-day_header_bgcolor "#666666"} {-calendar_width "100%"} {-day_bgcolor "#DCDCDC"} {-today_bgcolor "#FFF8DC"} {-day_text_color "white"} {-empty_bgcolor "white"} {-next_week_template ""} {-prev_week_template ""} {-prev_next_links_in_title 0} {-fill_all_days 0} } { Returns a calendar for a specific week, with details supplied by Julian date. Defaults to this week. To specify details for the individual days (if large_calendar_p is set) put data in an ns_set calendar_details. The key is the Julian date of the day, and the value is a string (possibly with HTML formatting) that represents the details. The variables in the templates are: - day_template: julian,day,date,pretty_date - next_week_template: - prev_week_template: DEPRECATED: this proc uses hardcoded markup and is therefore difficult to style. It is also not localized. Many of the date operations happening here have now good tcl support through the clock api, which would make this code probably faster and certainly portable (Oracle query is missing). Future reimplementations should leverage the templating system more. @see /doc/acs-templating/ @see /doc/acs-lang/ @see clock } { set today_date [dt_sysdate] if {$date eq ""} { set date $today_date } set current_date $date # Get information for the week db_1row select_week_info {} # Initialize the ns_set if {$calendar_details eq ""} { set calendar_details [ns_set create calendar_details] } # Loop through the days of the week set julian $sunday_julian set return_html "<table CELLPADDING=0 CELLSPACING=0 BORDER=0 width=95%>\n" # Navigation Bar append return_html [subst {<tr><td> <table cellpadding="3" cellspacing="0" border="0" width="90%" class="table-display"> <tr class="table-header" bgcolor="lavender"> <td align="center"> [subst $prev_week_template] <span style="font-family:Arial,Helvetica; size: smaller"> <b>[util_AnsiDatetoPrettyDate $sunday_date] - [util_AnsiDatetoPrettyDate $saturday_date]</b> </span> [subst $next_week_template] </td> </tr> </table></td></tr> }] append return_html [subst {<tr> <td> <table class="table-display" cellpadding="0" cellspacing="0" border="0" width="90%">}] set days_of_week {Sunday Monday Tuesday Wednesday Thursday Friday Saturday} foreach day $days_of_week { set lower_day [string tolower $day] set julian [set ${lower_day}_julian] set date [set ${lower_day}_date] set pretty_date [util_AnsiDatetoPrettyDate $date] set day_html [subst $day_template] if {$date == $today_date} { set bgcolor $today_bgcolor } else { set bgcolor $day_bgcolor } append return_html [subst {<tr><td class="cal-week" bgcolor="$bgcolor">$day_html </td> </tr> <tr> <td class="cal-week-event"> <table cellpadding="0" cellspacing="0" border="0" width="100%">}] # Go through events while {1} { set index [ns_set find $calendar_details $julian] if {$index == -1} { break } append return_html [subst { <tr><td class="cal-week-event"> <span style="font-size: smaller">[ns_set value $calendar_details $index]</span> </td></tr> }] ns_set delete $calendar_details $index } append return_html "</table></td></tr>" append return_html "</td></tr>\n" incr julian } append return_html "</table></td></tr></table>" return $return_html } d_proc -deprecated dt_widget_day { {-calendar_details ""} {-date ""} {-hour_template {$display_hour}} {-start_hour 0} {-end_hour 23} {-show_nav 1} {-prev_nav_template {<a href="?date=[ns_urlencode $yesterday]"><img border="0" src="[dt_left_arrow]" alt="[_ acs-datetime.back_one_day]"></a>}} {-next_nav_template {<a href="?date=[ns_urlencode $tomorrow]"><img border="0" src="[dt_right_arrow]" alt="[_ acs-datetime.forward_one_day]"></a>}} {-master_bgcolor "black"} {-header_bgcolor "black"} {-header_text_color "white"} {-header_text_size "+2"} {-calendar_width "100%"} {-day_bgcolor "#DDDDDD"} {-today_bgcolor "yellow"} {-day_text_color "white"} {-empty_bgcolor "white"} {-overlap_p 0} } { Returns a calendar for a specific day, with details supplied by hour. Defaults to today. DEPRECATED: this proc uses hardcoded markup and is therefore difficult to style. It is also not localized. Many of the date operations happening here have now good tcl support through the clock api, which would make this code probably faster. Future reimplementations should leverage the templating system more. @see /doc/acs-templating/ @see /doc/acs-lang/ @see clock } { if {$date eq ""} { set date [dt_sysdate] } set current_date $date # Initialize the ns_set if {$calendar_details eq ""} { set calendar_details [ns_set create calendar_details] } # Collect some statistics about the events (for overlap) for {set hour $start_hour} {$hour <= 23} {incr hour} { set n_events($hour) 0 set n_starting_events($hour) 0 } set calendar_details_2 [ns_set copy $calendar_details] for {set hour $start_hour} {$hour <= $end_hour} {incr hour} { if {$hour < 10} { set index_hour "0$hour" } else { set index_hour $hour } # Go through events while {1} { set index [ns_set find $calendar_details_2 $index_hour] if {$index == -1} { break } set item_val [ns_set value $calendar_details_2 $index] ns_set delete $calendar_details_2 $index # Count the num of events starting at this hour set n_starting_events($hour) [expr {$n_starting_events($hour) + 1}] # Diff the hours set hours_diff [dt_hour_diff -start_time [lindex $item_val 0] -end_time [lindex $item_val 1]] # Count the num of events at the hours of operations for {set i 0} {$i <= $hours_diff} {incr i} { set the_hour [expr {$hour + $i}] set n_events($the_hour) [expr {$n_events([expr {$the_hour - $i}]) + 1}] } } } # the MAX num of events set max_n_events 1 for {set hour $start_hour} {$hour <= $end_hour} {incr hour} { if {$max_n_events < $n_events($hour)} { set max_n_events $n_events($hour) ns_log debug "BMA-DEBUG-CAL: Setting max_n_events to $max_n_events" } } # Select some basic stuff, sets day_of_the_week, yesterday, tomorrow vars db_1row select_day_info {} set return_html "" if {$show_nav} { set prev_nav [subst $prev_nav_template] set next_nav [subst $next_nav_template] append return_html "<table border=0 cellspacing=0 cellpadding=0 width=$calendar_width><tr class=\"table-header\"><th> $prev_nav $day_of_the_week $next_nav </th></tr> </table>" } # Loop through the hours of the day append return_html "<table border=0 cellpadding=0 cellspacing=0 width=$calendar_width><tr><td><table cellpadding=1 cellspacing=0 border=0 width=100%> " # The items that have no hour set hour "" set next_hour "" set start_time "" set odd_row_p 0 set display_hour [subst {<img border="0" align="center" src="/resources/acs-subsite/diamond.gif" alt="[_ acs-datetime.All_day]">}] append return_html [subst { <tr class="odd"><td class="center" align="left" width="60" nowrap><span style="font-size: smaller;">[subst $hour_template]</span></td> <td colspan="$max_n_events"><span style="font-size: smaller">}] # Go through events while {1} { set index [ns_set find $calendar_details "X"] if {$index == -1} { break } if {$overlap_p} { append return_html "[lindex [ns_set value $calendar_details $index] 2]<br>" } else { append return_html "[ns_set value $calendar_details $index]<br>\n" } ns_set delete $calendar_details $index } append return_html "</span> </td></tr>" for {set hour $start_hour} {$hour <= $end_hour} {incr hour} { set next_hour [expr {$hour + 1}] if {$hour < 10} { set index_hour "0$hour" } else { set index_hour $hour } # display stuff if {$hour >= 12} { set ampm_hour [expr {$hour - 12}] set pm 1 } else { set ampm_hour $hour set pm 0 } if {$ampm_hour == 0} { set ampm_hour 12 } if {$ampm_hour < 10} { set display_hour "$ampm_hour" } else { set display_hour "$ampm_hour" } append display_hour ":00 " if {$pm} { append display_hour "pm" } else { append display_hour "am" } if { $odd_row_p } { set class "odd" set odd_row_p 0 } else { set class "even" set odd_row_p 1 } set display_hour [subst $hour_template] append return_html "<tr class=\"$class\"><td class=\"center\" align=left width=\"60\" \"nowrap\"><nobr><span style=\"font-size: smaller\">$display_hour</span></nobr></td>\n" set n_processed_events 0 # A flag to force completion of the row set must_complete_p 0 # Go through events while {1} { set index [ns_set find $calendar_details $index_hour] if {$index == -1} { break } incr n_processed_events if {$overlap_p} { set one_item_val [ns_set value $calendar_details $index] set hour_diff [dt_hour_diff -start_time [lindex $one_item_val 0] -end_time [lindex $one_item_val 1]] set start_time $hour # Calculate the colspan if {$n_processed_events == $n_starting_events($hour)} { # This is the last one, make it as wide as possible if {$hour_diff > 0} { set colspan 1 set must_complete_p 1 } else { # HACK set colspan 1 set must_complete_p 1 #set colspan [expr {$max_n_events - $n_events($hour) + 1}] } } { # Just make it one set colspan 1 } append return_html "<td valign=top rowspan=[expr {$hour_diff + 1}] colspan=$colspan><span style=\"font-size: smaller\">[lindex $one_item_val 2]</span></td>" } else { append return_html "[ns_set value $calendar_details $index]<br>\n" } ns_set delete $calendar_details $index } if {$n_processed_events == 0 || ($n_events($hour) < $max_n_events && $must_complete_p)} { if {$n_events($hour) == 0 || $n_events($hour) == $n_processed_events} { append return_html "<td colspan=\"[expr {$max_n_events - $n_events($hour)}]\" class=\"$class\"> </td>" } else { for {set i 0} {$i < $max_n_events - $n_events($hour)} {incr i} { append return_html "<td colspan=\"1\" class=$class> </td>" } } } append return_html "</tr>\n" } append return_html "</table> </td></tr> </table>" return $return_html } d_proc -deprecated dt_widget_list { {-calendar_details:required} {-item_template {$item}} {-start_date ""} {-end_date ""} {-order_by ""} {-url_template {?order_by=$order_by}} } { create a listing widget for lists (ben) I would like to ask forgiveness from the coding gods for this proc. Right now this is a big hack to make the schedule look a lot like the SloanSpace v1.0 display. Once we have thought this through a bit more, I will generalize this proc. I promise. Please forgive me. DEPRECATED: time is up Ben. This proc uses hardcoded markup and is therefore difficult to style. It is also not fully localized. Future reimplementations should leverage the templating system more. @see /doc/acs-templating/ @see /doc/acs-lang/ } { # Check for zero size if {[ns_set size $calendar_details] == 0} { return "<i>No Items</i>" } # The title if {$start_date eq "" && $end_date eq ""} { #This used to be All Items but that was just taking up space and not adding value so now we assume All Items and only give a title if its something else. - Caroline@meekshome.com set title "" } if {$start_date eq "" && $end_date ne ""} { set $pretty_end_date [lc_time_fmt $end_date "%x"] set title "[_ acs-datetime.Items_until]" } if {$start_date ne "" && $end_date eq ""} { set title "Items starting [util_AnsiDatetoPrettyDate $start_date]" } if {$start_date ne "" && $end_date ne ""} { set title "Items from [util_AnsiDatetoPrettyDate $start_date] to [util_AnsiDatetoPrettyDate $end_date]" } set return_html "<b>$title</b><p>" # Prepare the templates set real_order_by $order_by set order_by "item_type" set item_type_url [subst $url_template] set order_by "start_date" set start_date_url [subst $url_template] # Create the header append return_html [subst { <table class="table-display" border="0" cellspacing="0" cellpadding="2"> <tr class="table-header"> <th>Day of Week</th> <th><a href="[ns_quotehtml $start_date_url]">Date</a></th> <th>Start Time</th> <th>End Time</th> }] if {$real_order_by ne "item_type"} { append return_html [subst {<th><a href="[ns_quotehtml $item_type_url]">Type</a></th>}] } append return_html "<th>Title</th></tr>\n" # initialize the item_type so we can do intermediate titles set old_item_type "" set flip 0 # Loop through the events, and add them foreach item [ns_set values $calendar_details] { lassign $item date start_time end_time weekday item_type item_details # Adjust the display of no-time items if {[dt_no_time_p -start_time $start_time -end_time $end_time]} { set start_time "--" set end_time "--" } # Do we need a title? if {$real_order_by eq "item_type" && $item_type != $old_item_type} { if {$item_type eq ""} { set item_type_for_title "(No Item Type)" } else { set item_type_for_title $item_type } append return_html [subst {<tr class="table-title"><td colspan="5"><b>$item_type_for_title</b></td></tr>}] set flip 0 } set old_item_type $item_type if {$flip % 2 == 0} { set z_class odd } else { set z_class even } append return_html " <tr class=$z_class><td>$weekday</td><td>$date</td><td>$start_time</td><td>$end_time</td>" if {$real_order_by ne "item_type"} { append return_html "<td>$item_type</td>" } append return_html "<td>$item_details</td></tr>\n" incr flip } append return_html "</table> <!-- End of dt_widget_list --->" return $return_html } # # Additional Utility Procs # d_proc -public dt_midnight_p { time } { Check if a time is midnight. This might be replaced by clock idioms in the future, but is currently the way we decide e.g. if an event is an all-day event. @see dt_no_time_p } { if {$time eq "00:00" || $time eq ""} { return 1 } if {[regexp {00:00 *[aA][mM]} $time the_match]} { return 1 } if {[regexp {12:00 *[aA][mM]} $time the_match]} { return 1 } if {[regexp {[0-9]+-[0-9]+[0-9]+ (0?)0:0(0?)} $time the_match]} { return 1 } if {[regexp {[0-9]+-[0-9]+ (0?)0:0(0?)} $time the_match]} { return 1 } return 0 } d_proc -public dt_no_time_p { {-start_time:required} {-end_time:required} } { This decides whether an item is without a time, which is also our definition of an all-day event. } { # Compare times and make sure it's midnight on both if {[dt_midnight_p $start_time] && [dt_midnight_p $end_time]} { return 1 } else { return 0 } } d_proc -deprecated dt_hour_diff { {-start_time:required} {-end_time:required} } { 24-hour times input (23:00,02:00). This gives us the num of hours of difference, taking into account that if something goes until 5:01, it is one more hour long than if it goes until 5:00 DEPRECATED: this is really something one should do leveraging existing tcl capabilities. Plain clock idioms can do the same in a more generic and reliable way. @see clock } { set start_hour [string trimleft [string range $start_time 0 1] 0] set end_hour [string trimleft [string range $end_time 0 1] 0] set end_minutes [string range $end_time 3 4] # Special case when the hour is exact if {$end_minutes eq "00" } { return [expr {$end_hour - $start_hour - 1}] } else { return [expr {$end_hour - $start_hour}] } } # Local variables: # mode: tcl # tcl-indent-level: 4 # indent-tabs-mode: nil # End: