Story
I needed to revamp our campus calendar and found a great css/javascript calendar callout implementation while browsing Squared Eye's UI gallery (soon to become Pattern Tap). I wanted to do a similar implementation, highlighting the individual event, instead of the whole day.
My Version
Here is the visual end result of my calendar callout:
The date (or date span) appears in the header with a close button. The event name, time, details, link and location are included in the box. At the bottom there is a permalink to the event in case people want to link directly to the Event information. Click here to see the live implementation. (Note: the calendar was still not live at time of blog article publication)
ASP.NET Implementation
I implemented this through a combination of the ASP.NET calendar control, some Ajax call backs, and the jQuery Javascript library. I'll try to cover the basics of the implementations and point out the pitfalls I had to overcome below.
The events are show in the calendar day through implementing the DayRender event of the ASP.NET Calendar Control. I loop through the events, add them to a string builder and then output that string into the control.
...
For Each dayEvent In events
…
myString.AppendFormat("<div id=""" & myEvent_ID & "_" & e.Day.DayNumberText & _
""" class=""event""><a href=""javascript: showEvent(" & myEvent_ID & _
",'top','" & rightOrLeft & "', " & _
e.Day.DayNumberText & ")"" class=""e"">" & DisplayedLink & _
strDisplayedCalName & DisplayedTimeRange & "</a>{0}</div>", strEditLInk)
Next
'Write the Event Info to the cell
e.Cell.Controls.Add(New LiteralControl(myString.ToString()))
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
You can see that I have not included all my code, but you can see that each event is surrounded by an anchor tag that called the showEvent() javascript function. This function passes a unique identifier of the event, how to display the box (e.g. top, bottom, left, right) and then the day number (needed to included day number because some events span multiple days with the same event number. The day tells the javascript function which event in the UI to show the call out next to.
Javascript Functions
Here is the showEvent() function
function showEvent(id, posV, posH, day)
{
$('.event').attr("class","event");
$('.eventDetail').hide();
$('#' + id + '_' + day).attr("class","event eventSelected");
var myClass = 'eventDetail';
if (posV == "bottom") { myClass = myClass + " bottom"; } else { myClass = myClass + " top"; }
if (posH == "left") { myClass = myClass + " left"; } else { myClass = myClass + " right"; }
$.ajax({
type: "GET",
url: "callbacks/ajaxcalendar.aspx?cmd=showEvent&id=" + id,
success: function(htmlContent) {
$('#' + id + '_' + day).append("<div id='hover_" + id + "_" +
day + "' class='" + myClass + "'>" + htmlContent + "</div>");
}
});
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
First thing it is resets the classes. This has the effect of closing another callout box if one is currently open. Then the currently selected callout is selected (given the class "eventSelected"). Additional classes are added to the event to tell the box where to render in relationship to the event.
The event id is then used to make an ajax callback to get the details of the event (this prevents a large amount of data having to be loaded into the DOM on page_load()).
To close the call out there is a very simple call that resets all the classes on the event objects.
function closeEvent()
{
$('.event').attr("class","event");
$('.eventDetail').hide();
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
CSS
The CSS if very important in this implementation because it controls how the callouts are displayed. An interesting bug I ran into while working on this is the IE 6/7 z-index bug that has been exceptionally well documented by Aleksandar Vacić.
Here is the important CSS
.event { position: relative; z-index: 1; font-family: Arial, Verdana; font-size: 9pt; line-height: normal; font-weight: normal; margin: 0; padding:0; }
.eventSelected { color: #fff; background-color: #b22222; z-index: 2; }
.eventSelected a { color: #fff; }
.eventDetail { position: absolute; width: 290px; border: 5px solid #b22222; color: #333; background: #fff; z-index: 999; }
.eventDetail .eventContent { padding: 10px; }
.eventSelected .eventDetail .eventContent a { color: #b22222; }
.eventDetail .eventHeader { background-color: #b22222; padding:0 0 6px 0; color: #fff;}
.eventDetail .eventHeader a { display: block; float: right; }
.eventDetail .eventFooter { text-align: right; margin: 5px 0 0 0; padding: 0; }
.eventDetail h1 { margin: 0; padding: 5px 0 5px 0; font-size: 1.4em; line-height: normal;}
.eventDetail h2 { margin: 0; padding: 0; font-size: 1.2em;}
.eventDetail h1 IMG { border: 0; padding: 0 5px 0 0; }
.top { top: 0; }
.right { right: -300px; }
.bottom { bottom: 0px; }
.left { left: -300px; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
You can see that the z-index of event and eventSelected needs to be set differently. This compensates for the IE6/IE7 z-index bug, ensuring that the event detail does show on the top of future events.
That's about the scope of it. Please post any questions or comments you have.
Special thanks to Matthew Smith of Squared Eye who advised me on the layout.
Technorati Tags:
ASP.NET,
Calendar Control,
jQuery
Recent comments
10 weeks 5 days ago
10 weeks 5 days ago
11 weeks 6 hours ago
12 weeks 5 days ago
12 weeks 6 days ago
12 weeks 6 days ago
16 weeks 23 hours ago
16 weeks 4 days ago
16 weeks 6 days ago
17 weeks 11 hours ago