Setting up agendas & holidays

We've already known that the 3rd parameter in the name & id of the calendar tag denotes a file named agenda.js. This parameter is optional. The calendar can work without it, only that there will be no holidays or events showing. The agenda.js, once defined, will provide all agendas as well as the holidays setting to the calendar engine.

Before we go further with the agenda, let's take another look at the calendar tag, as following.

<iframe width=174 height=189 name="gToday:normal:agenda.js" id="gToday:normal:agenda.js" src="iflateng.htm" scrolling="no" frameborder="0">
<ILAYER><LAYER name="gToday:normal:agenda.js" src="nflateng.htm"> </LAYER></ILAYER>
</iframe>

One thing need to be pointed out earlier is that the file doesn't have to be named as agenda.js. You may actually use any cgi program to generate this file on-the-fly, e.g. ASP, JSP or PHP, so that you can take advantage of it and retrieve whatever events from your backend server or database. We'll discuss about it later in this tutorial.

The agenda.js file usually has 3 parts - fAddEvent functions, fHoliday function and additional helper functions used by fHoliday to support calculations. (The helper functions can also be moved into the plugins.js.)

What is an agenda?

An agenda is just a special day that you want to render it differently in the calendar, like appointments, meetings and/or other daily events. You may give them specific font colors, background colors, text tooltips, or even images and customized html code. All you need to do is to append a line in the agenda.js for each daily event you got. e.g.

fAddEvent(year, month, day, message, action, bgcolor, fgcolor, bgimg, boxit, html);

The parameters are detailed as following:

Note: There is an important option called gAgendaMask in the theme-name.js file. It determines which parameter will be masked out - which one in use which one not. So be sure to check it before adapting your agendas and holidays, all just set it all to -1.

Later, if you want to get rid of an event, you may simply call:

fRemoveEvent(year,month,day);

What is a holiday?

A holiday, a.k.a. recurring/batch event, is nothing but a special agenda that will recur from time to time. Therefore, we made a function to define them more efficiently, as following:

function fHoliday(y,m,d) {
  var r=fGetEvent(y,m,d); // get agenda event.
  if (r) return r;

  if (m==1&&d==1)
    r=[" Jan 1, "+y+" \n Happy New Year! ", "", "steelblue"];
  }

  return r; // if r is null, the engine will just render it as a normal day.
}

Once defined, the calendar engine will call it each time it rendering the date cell. So if you have a lot of similar events, or want to show the same agenda across a period of time, i.e. weeks or months, using the fHoliday() to return an agenda template is much viable than making tons of fAddEvent() calls. The plugin in range picker demo is a good example in reality.

This function should return an array as agenda template in the following format or a null value if nothing special.

[message, action, bgcolor, fgcolor, bgimg, boxit, html]

In the above sample, we take the following logic -- first look up for the event of date [y,m,d]. If we found one, simply return it to the engine because we think the event created by the fAddEvent is more important.

Of course, we can easily make the code continue to check holidays and merge the result of both together if we like. Or we may choose holidays over agendas by checking the holiday first. Anyway, it's all up to you since this function is totally under your control.

Additional date calculations

In addition to do the simple comparison of year and month, you could use much more sophisticated formulas to check out the non-regular holidays like Easter, Thanksgiving or whatever holiday in your culture. There are so many standard calculations on the internet that can be used directly here.

Simply implement them in javascript functions here and then call them from within the fHoliday function to verify against the date passed in.

Please check the agenda.js of Hello World Demo for a quick example.

Retrieving agenda events from backend data source

Ever thought about making your agenda events manageable by using a backend server/database? No kidding, it's not only possible but always simple with CalendarXP.

Here we'll show you how to do it with JSP. And it's almost the same with ASP, PHP or other cgi techniques, you may easily figure it out.

  1. Suppose that you have got a table named "MY_AGENDAS" in your database, and you have already defined a datasource named "myDataSource" (you should have set up db user/password in the datasource).
  2. Suppose there are 10 columns in table "MY_AGENDAS" in accordance with the agenda format, as following: ag_year,ag_month,ag_day,ag_message,ag_action,ag_bgcolor,ag_fgcolor,ag_bgimg,ag_boxit,ag_html.
  3. Build a JSP file named agenda.jsp as following:

    <%@ page contentType="text/javascript" %>
    <% // The above JSP code set the generated page to be recognized as a javascript source. %>

    <% java.sql.Connection conn=null;
    try {
    // Establish database connection
    javax.naming.Context ctx = new javax.naming.InitialContext();
    javax.sql.DataSource ds = (javax.sql.DataSource)ctx.lookup("myDataSource");
    conn = ds.getConnection();

    // Execute SQL and get a result set
    java.sql.Statement stmt = conn.createStatement();
    java.sql.ResultSet rs = stmt.executeQuery("SELECT * FROM MY_AGENDAS");

    // Loop through the result set to generate multiple fAddEvent() functions
    while (rs.next()) {
    %>

    fAddEvent(<%=rs.getString("ag_year")%>,<%=rs.getString("ag_month")%>,<%=rs.getString("ag_day")%>,
    "<%=rs.getString("ag_message")%>",
    <% if (rs.getString("ag_action")==null) out.print("null");
    else out.print("\""+rs.getString("ag_action")+"\""); %>,
    <% if (rs.getString("ag_bgcolor")==null) out.print("null");
    else out.print("\""+rs.getString("ag_bgcolor")+"\""); %>,
    <% if (rs.getString("ag_fgcolor")==null) out.print("null");
    else out.print("\""+rs.getString("ag_fgcolor")+"\""); %>,
    <% if (rs.getString("ag_bgimg")==null) out.print("null");
    else out.print("\""+rs.getString("ag_bgimg")+"\""); %>,
    <% if (rs.getString("ag_boxit")==null) out.print("null");
    else out.print(rs.getString("ag_boxit")); %>,
    <% if (rs.getString("ag_html")==null) out.print("null");
    else out.print("\""+rs.getString("ag_html")+"\""); %>
    );

    <% }

    // Close db connection and error handling
    rs.close();
    stmt.close();
    } catch (Exception e) {
    System.out.pringln("Service Error: "+e);
    } finally {
    if (conn!=null)
    try { conn.close() } catch (Exception ignore) {};
    }
    %>

    // put other javascript functions from the original agenda.js file to following
    function fHoliday(y,m,d) {
    ...
    }

    function popup(url,framename) {
    ......

  4. Place agenda.jsp in your JSP server, suppose the absolute URL path is /myweb/agenda.jsp. Change the 3rd parameter in the name&id of the calendar tag, as following:
    <iframe width=174 height=189 name="gToday:normal:/myweb/agenda.jsp" id="gToday:normal:/myweb/agenda.jsp" src="iflateng.htm" scrolling="no" frameborder="0">
    <ilayer><layer name="gToday:normal:/myweb/agenda.jsp" src="nflateng.htm">     </layer></ilayer>
    </iframe>

That's all. Now all the agenda events will be loaded directly from your backend database table MY_AGENDAS.

Note: The ag_html should NOT contain double-quotes. You must escape them, if any, as &quot; before storing them in the MY_AGENDAS table.

Share agendas among multiple calendars

Sometimes when you have more than 1 calendar on the same web page, you might need to share the agenda source among them. Since version 7.0 this can be done by setting the agenda parameter in the calendar tag to "share[<context-name>]" instead of "agenda.js". In addition, the gbShareAgenda should be set to true. The following outlookTwin theme tag is a good example:

<TABLE border="0" cellspacing="0" cellpadding="0"><TR><TD>
<iframe width=150 height=141 name="gToday:outlookleft:agenda.js:gfFlat_1" id="gToday:outlookleft:agenda.js:gfFlat_1" src="iflateng.htm" scrolling="no" frameborder="0" >
<ILAYER><LAYER name="gToday:outlookleft:agenda.js:gfFlat_1" src="nflateng.htm"> </LAYER></ILAYER>
</iframe>
</TD>
<TD>
<iframe width=150 height=141 name="[gToday[0],gToday[1]+1]:outlookright:share[gfFlat_1]:gfFlat_2" id="[gToday[0],gToday[1]+1]:outlookright:share[gfFlat_1]:gfFlat_2" src="iflateng.htm" scrolling="no" frameborder="0" >
<ILAYER><LAYER name="[gToday[0],gToday[1]+1]:outlookright:share[gfFlat_1]:gfFlat_2" src="nflateng.htm"> </LAYER></ILAYER>
</iframe>
</TD></TR></TABLE>

Note that the 3rd parameter of the second calendar tag is share[gfFlat_1], which means to share the agenda loaded by gfFlat_1. Should the agenda get changed by any run-time scripts both calendars would always get the same update automatically. All you need to do is to call the fRepaint() afterwards to reveal the change to the calendar panel.

Another advantage of sharing is that the agenda.js will be loaded only once, no matter how many calendar tags are embedded on the same page. It could save a lot if you had a huge agenda database.

The sharing can also happen between PopCalendarXP and FlatCalendarXP, if you are using both.

 


Copyright © 2001-2003 CalendarXP.net, Liming Weng