In this post in the developerWorks forum, Andy Herlihy is asking about how to create a small calendar that can be embedded into an existing intranet website. As Carl Tyler points out, Andy could simply use Dojo.
However, this is a good example to show some jQuery combined with the power of IBM Lotus Domino. Lets’ break it down into a few smaller steps.
The first one is to create a Domino web agent that will take the current date and build a calendar for that month. There will be no links or javascript code in the HTML generated, just plain HTML code, with some id attributes to make it easy to address different cells later.
The next step is to create a very simple webpage, with some Javascript to load jQuery and set up the calendar to detect clicks. The clicks will cause another call to the Domino server, this time to a view using RestrictToCategories to only get the entries for the specified date. The entries are returned as HTML and through jQuery they are displayed in a div on the webpage. We also want to add a little bit of CSS to make the calendar pretty. The CSS also lives on the HTML page.
Finally we create the view, it’s associated view template form and a form to create some entries that we can use for testing.
Let’s look at the code. First the Domino web agent. It should be pretty self explanatory:
%REM Agent WebCalendar Created Nov 26, 2012 by Karl-Henry Martinsson/Deep-South Description: Returns HTML for a calendar for current month %END REM Option Public Option Declare Sub Initialize '*** Used to get URL params Dim session As New NotesSession Dim webform As NotesDocument Dim urlstring As String Dim urlarr As Variant Dim urlvaluename As Variant Dim urldata List As String Dim webservername As String '*** Agent specific Dim startDate As NotesDateTime Dim endDate As NotesDateTime Dim i As Integer Dim j As Integer Dim startweekday As Integer Dim thisMonth As Integer Dim currDate As Double Dim cellclass As String Set webform = session.DocumentContext '*** Calculate path for this database, for image/icon file references later webservername = webform.GetItemValue("Server_Name")(0) '*** Remove leading "OpenAgent" urlstring = StrRight(webform.Query_String_Decoded(0),"&") If urlstring <> "" Then '*** Get all params passed to agent urlarr = Split(urlstring,"&") For i = LBound(urlarr) To UBound(urlarr) urlvaluename = Split(urlarr(i),"=") urldata(urlvaluename(0)) = urlvaluename(1) Next If IsElement(urldata("date")) = False Then urldata("date") = Format$(Now(),"mm/dd/yyyy") End If Else urldata("date") = Format$(Now(),"mm/dd/yyyy") End If '*** Get first and last date of current month Set startDate = New NotesDateTime(Format$(urldata("date"),"mm/01/yyyy")) Set endDate = New NotesDateTime(startdate.DateOnly) Call endDate.AdjustMonth(1) Call endDate.AdjustDay(-1) currDate = CDbl(CDat(startDate.DateOnly)) startweekday = Weekday(Cdat(startDate.Dateonly)) '*** HTML header Print "Content-type: text/html" ' & CRLF Print |<table class="calendar">| '*** Create calendar header with weekdays Print |<tr><td colspan=7 class="labelMonthYear">| + Format$(CDat(startDate.DateOnly),"mmmm yyyy") + |</td></tr>| Print |<tr class="calendarHeader">| Print |<td>S</td><td>M</td><td>T</td><td>W</td><td>T</td><td>F</td><td>S</td>| Print |</tr>| '*** Build rows for the weeks For i = 1 To 6 Print |<!-- Start row | & i & | -->| Print |<tr class="calendarRow" id="calendarRow| & i & |">| For j = 1 To 7 If j < startweekday And i = 1 Then Print |<td class="emptyCell"></td>| ' Blank cell before dates ElseIf currDate >= CDbl(CDat(startDate.DateOnly)) And currDate <= CDbl(CDat(endDate.DateOnly)) Then cellclass = "calendarCell" If j = 1 Then cellclass = cellclass + " sundayCell" End If If j = 7 Then cellclass = cellclass + " saturdayCell" End If Print |<td class="| + cellclass + |" id="| + Format$(CDat(currDate),"yyyy-mm-dd") + |">| Print Day(CDat(currDate)) ' Day number Print |</td>| currDate = currDate + 1 Else Print |<td class="emptyCell"></td>| ' Blank cell after dates End If Next Print |</tr>| Print |<!-- End row | & i & | -->| Print "" If currDate >= CDbl(CDat(endDate.DateOnly)) Then Exit For End If Next Print |</table>| End Sub
I am setting the id attribute on the cells to the date in yyyy-mm-dd format, and I will also use that in the categorized view that will later use. Using ISO 8601 for dates have several advantages, in our case particular because we don’t have to worry about the / character that will mess up the URL to the Domino view we will call later.
I also use class attributes on the cells, so CSS can be used to easily format the calendar.
Next we create the web page where we will insert the calendar and also display the entries for any selected day. We load jQuery from Googles CDN, and after the DOM is fully loaded by the browser, we make an ajax call to the Domino server and get the HTML of the calendar back.
After the calendar is retrieved, we use jQuery to trigger a Javascript function on click on any date cell. The code will detect the id of the cell, which just happens to be the date, and then performs another ajax call to teh Domino server, this time to the view to return all entries for the selected date. The data returned is then inserted into a div.
<!doctype html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Calendar Test</title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script> </head> <script> // The following function is executed after page is fully loaded $(document).ready(function () { var remoteURL = "http://www.texasswede.com/test/calendar.nsf/WebCalendar?OpenAgent"; var viewURL = "http://www.texasswede.com/test/calendar.nsf/CalendarView?OpenView"; // Load the calendar HTML from our Domino server using ajax $.get(remoteURL, function(data) { // Update div with id 'ajaxCalendar' with HTML calendar from server $("#ajaxCalendar").html(data); // Set all calendar cells to trigger on click $(".calendarCell").each( function(i) { // Get the id (i.e. selected day) of the cell clicked var id = $(this).attr("id"); $(this).click( function() { // Call view on Domino server and return entries for selected day $.get(viewURL, { RestrictToCategory: id }, function(data) { // Put list of entries in viewData div $("#viewData").html(data); }); }); } ); }); }); </script> <style> td.calendarCell { border: 1px dotted black; height: 30px; width: 30px; text-align: center; vertical-align: middle; } td.emptyCell { background-color: #EFEFEF; height: 30px; width: 30px; } td.sundayCell { background-color: #DDDDDD; color: #DD0000; } td.saturdayCell { background-color: #DDDDDD; } .labelMonthYear { font-family: Arial; font-size: 12pt; text-align: center; } </style> <body> <div id="ajaxCalendar"></div> <br> <div id="viewData"></div> </body> </html>
What’s left to do to get this all to work is to create the following Domino design elements:
- A form to use for entering calendar data. I called it “Calendar Entry”, and just put two fields on it, ‘CreatedDate’ (computed for display, using @Now) and ‘Title’ (text field).
- A view called ‘CalendarView’, with two columns. The first one is categorized and is displaying the created date in yyyy-mm-dd format, while the second one is displaying the title field and adding an HTML line break after. The view is set to treat content as HTML.
- A form called ‘$$ViewTemplate for CalendarView’, set to treat form as HTML. The form only contains an embedded view element, pointing to ‘CalendarView’, and it is set to return data as HTML as well.
This is the formula I used in the first column of the ‘CalendarView’ view:
y:= @Year(CreatedDate); m:= @Month(CreatedDate); d:= @Day(CreatedDate); yyyy:=@Text(y); mm:=@If(m<10;"0";"") + @Text(m); dd:=@If(d<10;"0";"") + @Text(d); yyyy + "-" + mm + "-" + dd
And this is what it looks like when finished:
This is just one example of how you can combine Domino (agents, views and forms) with jQuery in order to integrate Domino based data into your web applications.
Happy coding!
If you’re looking for a really nice UI, try the fullCalendar jQuery plugin. Then all you would need is an agent, view, etc to produce JSON that the calendar reads. It’s actually very nice looking and very easy to work with.