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.)
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:
null
, the
agenda date will be visually disabled (line-crossed); if you set it to "",
i.e. empty string, there will be no action performed but the date still looks
selectable(of course you may use other properties to create a customized disable-look).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);
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.
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.
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.
ag_year,ag_month,ag_day,ag_message,ag_action,ag_bgcolor,ag_fgcolor,ag_bgimg,ag_boxit,ag_html
.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) {
......
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 "
before storing them in the MY_AGENDAS table.
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.