Here are all kinds of tips and tricks that will help you greatly in mastering and enjoying PopCalendarXP. Please come to visit our web site http://www.calendarxp.net from time to time and you will find more interesting stuff.
Simply append the calendar engine tag to the bottom of your webpage and call
gfPop.fPopCalendar(dateCtrl)
from your script, which will pop-up
a beautiful picker under the "dateCtrl".
Please check out the HelloWorld Tutorial for more details.
Create an empty directory, put the engine files in. Then go inside the themes
directory and pick up a theme you like, copy all files of the theme to the
directory just created. Finally, if you want to add agendas, you may start
with the agenda.js
in the HelloWorld demo, using it as a template
to create your own.
It's quite straightforward, please check out the Tutorials for more details and samples.
If you are upgrading from within the same major version, e.g. from 6.0 to 6.1, all you need is to copy the new engine files to overwrite the old ones. That's all, there is no need to change your production page or any theme options. It's quite easy and painless.
If you want to upgrade across major versions, e.g. from 5.2 to 6.0, then in addition to replacing the engine files you may also need to migrate the old theme options to the new theme if you want to keep your old theme working. Most of the time you don't need to change anything in your web page unless it is explicitly required by the new version in its release notes.
PopCalendarXP comes with great themes optimized for English environment. But it's quite simple to localize them since all text strings are stored externally in either the theme files or the agenda file. All you need is to open them with a text editor like notepad and replace the English strings with your own language strings, then modify the css file to use corresponding font families.
If your page was generated dynamically by ASP server and you saw rectangles
instead of normal fonts in Netscape 4.x, please set the http charset header
to "" by using Response.Charset=""
in your
asp page. This header has to be set before anything else.
If your page aims to support multiple languages(i18n), please follow the instructions in the i18n tutorials to create a simple i18n framework.
Simply set the following options in the theme-name.js file.
Note: When gsSplit is set to empty string, like above, settings of gbPadZero and giMonthMode will be ignored and the engine will render the format as if gbPadZero were set to
var gsSplit=""; // separator of date string.
var giDatePos=2; // date format sequence 0: D-M-Y ; 1: M-D-Y; 2: Y-M-D
var gbPadZero=true; // whether to pad the digits with 0 in the left when less than 10.
var giMonthMode=0; // month format 0: digits ; 1: full name from gMonths; >2: abbreviated name
var gbShortYear=false; // year format true: 2-digits; false: 4-digits
true
and giMonthMode to 0
.
Depending on the cgi service you are using the solution might be a little different. The basic idea is to make your cgi service produce the agenda.js dynamically, e.g. from a JSP or ASP. We had it detailed in the "Setting up agendas & holidays" tutorial.
There are 2 files involved in a theme that control the look of the calendar
- theme-name.js
& theme-name.css
. They are all
self-documented and you may use any text editor to fulfill the change.
The following example changes the background color of all the calendar cells to red (except Sundays) and the whole calendar to blue:
var gcCalBG="blue"; // calendar bg color
var gcCellBG="red"; // default cell bg color
var gcSatBG=null; // Saturday bg color, use default if set to null
var gcSunBG="#00ff00"; // Sunday bg color
Go to the theme-name.css
file and find the .CalCell
class, change the value of ruletext-align
to left
, center
or right
. To align it vertically, you'll have to turn it into
a table cell first by adding a CSS2 display
rule to both .CalCell
and .CellAnchor
and specify a vertical-align
rule afterwards:
.CalCell {...; text-align:center; display:table;}
.CellAnchor {...; display:table-cell; vertical-align:middle;}
For example, you want to perform the alert() function.
fOnChange()
callback plugin in
the plugins.js
file, as following:
function fOnChange(y,m,d) {
if (d>0) alert([y,m,d]+' will be selected.');
return false; // return true to cancel the change.
}
fAfterSelected()
callback
plugin in the plugins.js
file, as following: function fAfterSelected(y,m,d) {
alert([y,m,d]+' has been selected.');
}
gsAction
option
in the theme-name.js
file, as following:
var gsAction="alert([y,m,d]+' has been
selected.');";
Note you may also use pre-defined popup()
function (in plugins.js) to open up any URL in the current window or a new window. e.g.
function fAfterSelected(y,m,d) {
popup('http://www.calendarxp.net', '_top');
}
Or even startup your email client by using "mailto". e.g.
function fAfterSelected(y,m,d) {
popup('mailto:who@email.address?subject=hello there', '_blank');
}
It's a known issue for IE on Mac and Konqueror. To workaround, you may set the margin and padding of the <body> tag in your page to 0. e.g.
<style type="text/css">BODY {margin:0; padding:0}</style>
Another way is to take advantage of the gPosOffset
theme option
by setting it as following:
var gPosOffset=(IE&&MAC)||KO3?[12,14]:[0,0];
It means the calendar engine will offset the popup position 12 pixels righter and 14 pixels lower if it's running inside IE on Mac or Konqueror.
There is an option in the theme-name.js file called gPosOffset
that controls the offset. Say if you want to adjust the pop-up position by
10 pixels higher in browsers other than Netscape 4.x, you need to set it as
var gPosOffset=[0, NN4?0:-10];
Since version 8.2 you can also pass the offset data directly into the fPopCalendar()
call so as to offset the popup position on-the-fly. Please check the HelloWorld tutorial for details.
There is an option in the theme-name.js file called gbFixedPos
.
Simply set it to true
and then set the value of gPosOffset
to the static coordinates of the popup position. Note this setting may be overriden by the posOffset
parameter of the fPopCalendar()
.
Simply change the #outerTable
CSS style in the theme-name.css
file. Since version 7.0 the style of iframe calendar tag no longer contains
any border style properties.
Note: NN4 doesn't support outside border, it can only have the table
border set by gsOuterTable
in theme-name.js
file.
The calendar panel size is set initially by the width
and height
properties of <iframe> tag. If these 2 values are not matching the actual
size, the calendar engine will try to detect the real size after a short delay
specified by giResizeDelay
option. The incorrect initial size
problem will happen when the browser is not rendering DHTML faster enough
so that the document is not ready upon the size checking time.
Try increasing giResizeDelay
a bit. But don't set it too large because it will bring in visible delay.
Another solution is to adjust the width
and height
of the calendar tag to be the correct initial sizes.
Make sure the giCellWidth
is set larger enough. Try increasing
it 10 pixels a time until you see everything back normal. It's a NN4 bug triggered
when extra stuff stretching the top or bottom section too much wider than
the total width of date cells. Making the top and/or bottom sections shorter
could be another solution.
Please check the gAgendaMask
option in your theme settings.
Make sure the mask value is properly set. The agenda property will be masked
out if the relevant bit value is not set to -1
.
There are 3 factors that determine which month will be shown when the calendar pops up for the very first time.
1st, if the associated form date object's value is a valid date, then that date will be selected and shown up.
2nd, otherwise if the gdSelect
option is set to a valid date,
then the calendar will come up with it.
3rd, if none of the above applies, the calendar will show up with the month
set by the default-month
parameter in the name & id properties
of the calendar tag. No date gets selected.
In the 3rd situation, for example, if you set the name&id of the calendar
tag to "[2002,10]:normal:agenda.js"
, the calendar will
then start on Oct 2002. Or you may choose "[gToday[0],gToday[1]+1]:normal:agenda.js"
so that it will always show the next month up.
After the first pop-up, the calendar will remember the selected date.
Quite simple, all you need is to put 2 lines of code to the top of fHoliday() function in agenda.js file so that it looks like:
function fHoliday(y,m,d) {
var dayOfWeek=new Date(y,m-1,d).getDay();
if (dayOfWeek==0||dayOfWeek==6) return ["Weekend is not selectable!",null];
...
It creates a "null" agenda template, null
value in
the action property, for the weekends so that they can't be selected. You
may also disable other dates via the same way. A tip is to have other properties
of agenda defined in the template in order to make the disabled dates in different
colors, backgrounds or even images.
No, you don't need. Duplicate events can be treated as holidays. Instead
of repeating the fAddEvent()
calls, using fHoliday()
to return a single agenda template is much more faster and efficient. The
above FAQ for disabling weekends is a good example. Also please check the
setup agenda tutorial for more detailed info.
The build-in gContainer
reference, which points to the enclosing
window object, is made for such purpose. Suppose you have a form named "testForm"
with a <input> tag named "dateInput" laying in the same page
as the calendar. And you want to put the selected date from the calendar into
the "dateInput" field with the "y/m/d" date format. To
achieve such purpose, you should use the following code in plugins.js
file:
function fAfterSelected(y,m,d) {
gContainer.document.testForm.dateInput.value=y+"/"+m+"/"+d;
}
To submit the form associated with the current date field (the one you passed
in as a parameter of fPopCalendar), you should use the following code in plugins.js
file:
function fAfterSelected(y,m,d) {
gdCtrl.form.submit();
}
To submit a static form named as "testForm", you may use:
function fAfterSelected(y,m,d) {
gContainer.document.testForm.submit();
}
The calendar engine uses 2 system objects gd
and gToday
to control the date of today. You may override them in the plugins.js
file with any date you like, you can even rename it to plugins.asp
to take advantage of ASP generated date.
1st, you need to prepend the following lines of code to the top of plugins.js
file.
gd=new Date(2003,3-1,11); // You may use any date you want.
gToday=[gd.getFullYear(),gd.getMonth()+1,gd.getDate()];
gCurMonth=eval(gTheme[0]); // re-init the gCurMonth in case it using gToday.
2nd, you need to search through the theme-name.js file,
e.g. normal.js
, for any references to gToday
, and
copy them to the plugins.js
file and put them behind the above gCurMonth definition so that they can be re-initialized. e.g.
gd=new Date(2003,3-1,11); // You may use any date you want.
gToday=[gd.getFullYear(),gd.getMonth()+1,gd.getDate()];
gCurMonth=eval(gTheme[0]); // re-init the gCurMonth in case it using gToday.
gsBottom="..."; // re-init gsBottom if it contains reference to gToday. (optional)
gdSelect=gToday; // re-init gdSelect if it references to gToday. (optional)
Finally, you may want to rename the plugins file to plugins.asp
and use a date generated from ASP variables to replace the static one:
gd=new Date(<%= year %>,<%= month %>-1,<%= day %>); // year, month, day are server-end variables
...
Remember to modify the name & id of the calendar iframe tag accordingly to reflect the above renaming - e.g. "gToday:normal:agenda.js::plugins.asp"
. You can also use path in the name & id, more details can be found in the HelloWorld tutorial.
Also note that all options in the theme-name.js can be reset dynamically in this manner.
Please check whether the upper Navigation Section or lower Today Section is wider than the total width of date cells. The calendar panel will automatically get stretched if the outter table width becomes larger, and the streched part might not be evenly distributed among all columns.
You may either enlarge the giCellWidth
or cut down the stuff
in top/bottom sections to fix this problem.
Simply set the gBegin
option to gToday
in theme-name.js
file, as following:
...
var gBegin=gToday; // calendar date range begin from [Year,Month,Date]
var gEnd=[2030,12,31];
...
It's a bug of IE6 when setting the border style of <iframe> tag in
standard mode. To workaround, you may remove the border style from the <iframe>
tag and put it into the #outerTable
class in theme-name.css file
instead. All themes in version 7.0 and above have already been using this
solution to create calendar borders.
#outerTable {border:2px ridge #808080;}
Yes, easy. There is an option in the theme-name.js
file called
gsDays
which will be evaluated upon each calendar cell. Simply
name your image files as day1.gif, day2.gif, ... and create a function, named
fGetDateCell(), in the plugins.js as following:
function fGetDateCell(dateStr) {
var d=dateStr.split(",")[2];
return "<IMG src='/images/day"+d+".gif' height=... width=... >";
}
and set the gsDays
to:
var gsDays="fGetDateCell(sCellDate);";
Note the sCellDate
above is an internal contextual variable
that stores the current cell date in format "y,m,d".
Opera 7 seems to have a z-index bug and layer the iframe objects only by loading sequence. To work around, simply move the calendar iframe tag from the page bottom to page top, as following:
<BODY>
<iframe width=174 height=189 name="gToday:normal:agenda.js" id="gToday:normal:agenda.js"
src="ipopeng.htm" scrolling="no" frameborder="0"
style="visibility:visible; z-index:999; position:absolute; left:-500px;
top:0px;">
</iframe>
...
... your html page contents ...
...
<LAYER name="gToday:normal:agenda.js" src="npopeng.htm">
</LAYER>
</BODY>
NOTE that you mustn't move the <LAYER>
calendar tag, otherwise
NN4 will fail.
Easy. There is an option in the theme-name.js
file called giFirstDOW
.
Set it to 0,1-6 will make Sunday, Monday-Saturday the first day of week.
Easy. Just need to add 1 line of code in fHoliday()
to return
a default agenda instead of null
value for every normal day.
e.g.
function fHoliday(y,m,d) {
...
if (r==null) return ["A message for everyday", gsAction];
return r; // if r is null, the engine will just render it as a normal day.
}
Although most common date formats can be easily set via the theme options, sometimes user do need special customized ones. It's not difficult as long as you know how to intercept the input and output of the calendar.
Now let's illustrate the process of setting a format of "WEEKDAY, MMM DD, YYYY", which is not directly supported by the theme.
1st, set the theme date format to be "YYYY-MMM-DD", as following
var gsSplit="-"; // separator of date string, AT LEAST one char.
var giDatePos=2; // date format sequence 0: D-M-Y ; 1: M-D-Y; 2: Y-M-D
var gbPadZero=false; // whether to pad the digits with 0 in the left when less than 10.
var giMonthMode=1; // month format 0: digits ; 1: full name from gMonths; >2: abbreviated name
var gbShortYear=false; // year format true: 2-digits; false: 4-digits
2nd, add the following to your plugins.js
:
function fParseInput(str) {
var dt=/^(\w+), (\w+) (\d{1,2}), (\d{4})$/.exec(str);
if (dt==null) return null;
else return fParseDate(dt[4]+gsSplit+dt[2]+gsSplit+dt[3]);
}
function fFormatInput(y,m,d) {
var str=fFormatDate(y,m,d).split(gsSplit);
var d=new Date(y,m-1,d).getDay();
var wd=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
return wd[d]+", "+str[1]+" "+str[2]+", "+str[0];
}
Note: These 2 plugin functions are the new features that are only available after version 8.2. Please check the Plugins SDK for details.
In the calendar tag, you need to change the value of name & id properties to include the absolute/relative path to the theme directory. e.g.
<iframe name="gToday:/theme1/normal:agenda.js:gfPop:./plugins.js" id="gToday:/theme1/normal:agenda.js:gfPop:./plugins.js" src="/engine/ipopeng.htm" ... > </iframe>
The above tag will load the normal theme from absolute web path /theme1/
, while loading agenda.js
and plugins.js
from /engine/
. This may be confusing because paths in the name & id are relative to the src
, not the containing page. Therefore we always recommend you put all calendar related files together within the same directory with the ipopeng.htm and use path in src
ONLY.
It's a bug of the Thawte seal script and can be easily fixed by appending a line of script right behind it. i.e.
<script src="https://siteseal.thawte.com/cgi/server/thawte_seal_generator.exe"></script>
<script>if (document.layers) document.releaseEvents(Event.MOUSEDOWN);</script>
The 1st <script>
is the Thawte seal script, and the
2nd one is the fix.
Check the theme-name.js file and look for the gbAutoClose
option. Make sure it's set to true
. It's a flexible feature
of the calendar, and there are tons of alike features in the theme waiting
for your inspecting.
Please try the following one. Note the form id must be set to the same
as the one passed in to gfPop.fPopCalendar()
, otherwise the
calendar will not be able to find the date input field.
TabStripDemo.aspx
<%@ Register TagPrefix="ie" Namespace="Microsoft.Web.UI.WebControls" Assembly="Microsoft.Web.UI.WebControls" %>
<html>
<body>
<form id="demoform" runat="server"><ie:TabStrip runat="server" TargetID="mpage" AutoPostBack="true"
TabDefaultStyle="background-color:#000000;font-family:verdana;font-weight:bold;font-size:8pt;color:#ffffff;width:100px;height:21px;text-align:center"
TabHoverStyle="background-color:#777777"
TabSelectedStyle="background-color:#ffffff;color:#000000">
<ie:Tab Text="PopCalendar" />
<ie:TabSeparator/>
<ie:Tab Text="FlatCalendar" />
<ie:TabSeparator/>
<ie:Tab Text="About"/>
</ie:TabStrip><ie:MultiPage id="mpage" SelectedIndex="1" runat="server">
<ie:PageView>
Date Field: <input name="dc" value="" size="11"><a href="javascript:void(0)" onclick="gfPop.fPopCalendar(document.demoform.dc);return false;" HIDEFOCUS><img class="PopcalTrigger" align="absbottom" src="calbtn.gif" width="34" height="22" border="0" alt=""></a>
</ie:PageView><ie:PageView>
<iframe name="gToday:normal:agenda.js:gfFlat" id="gToday:normal:agenda.js:gfFlat" src="iflateng.htm" scrolling="no" frameborder="0">
</iframe>
</ie:PageView><ie:PageView>
Copyright (C)2003-2004 Idemfactor Solutions, Inc.
</ie:PageView>
</ie:MultiPage>
</form>
<iframe name="gToday:supermini:agenda.js" id="gToday:supermini:agenda.js" src="ipopeng.htm" scrolling="no" frameborder="0" style="visibility:visible; z-index:999; position:absolute; left:-500px; top:0px;">
</iframe>
</body>
</html>
Put the above TabStripDemo.aspx into a virtual directory on your IIS with the supermini theme for PopCalendarXP and normal theme for FlatCalendarXP.
Note: If you don't want to set the AutoPostBack
of tabstrip
control, you should append the following onclick code to workaround a bug
in the tab/multipage control. (To workaround a bug that messes the calendar in IE and only in IE.)
<ie:TabStrip runat="server" TargetID="mpage" onclick="if(gfFlat)gfFlat.fResize()" ...>
You can reference anything inside the calendar engine by prefixing it with the engine's context name (more on this in the Hello World tutorial). e.g.
<ContextName>.fGetWeekNo(y,m,d)
NOTE: the context name (e.g. gfPop or gfFlat) will be only available after the engine is fully loaded. You may want to check it before calling by adding "if(self.<ContextName>)" to the above statement, otherwise you may get an "object not found" error upon an inmature loading.
If you need a default date, assign one directly to the value
property of the <input>
tag, either by asp or jsp. The calendar will automatically pick it up when it pops up. Be sure to use the date format in accordence with the calendar theme, otherwise the calendar won't recognize it and will just have it cleared. If you leave the value
property empty, the calendar will try to populate it with the gdSelect
option defined in your theme-name.js file when it pops up. Another solutions is to leverage javascript event as following (same day but in year 2003).
<body ... onload="document.formName.dateField.value=gfPop.fFormatInput(2003, gfPop.gToday[1], gfPop.gToday[2])">
You just need to set the input box to be readonly by appending [ readonly onfocus="this.blur()"
] to it. e.g.
<input name="dateField1" value="" readonly onfocus="this.blur()" >
Now the value of this field can only be set by scripts and you don't need to worry about user typing in wrong date any more.
If you want to create a calendar that belongs to a user, you may need to pass the user id to the scripts that generate the agenda file so that the calendar only shows up the events related to that specific user.
CalendarXP has already taken it into account and all you need is set the url in the name & id of the calendar tag, as following:
<iframe name="gToday:normal:agenda.jsp?userId=<%=obj.getUserID()%>" id="gToday:normal:agenda.jsp?userId=<%=obj.getUserID()%>"
...></iframe>
The above example is using JSP to generate the agenda file, of course you may use Perl, ASP, PHP or whatever else instead.
Note: you must escape any non-alphabetical chars in the URL, especially the colon char. Running the parameter string through an URL encoding filter and using the transformed string in the name & id of the calendar tag is always a safe way to go.
Yes, any actions can be associated with the week numbers, e.g. popup windows, change url or even update calendar events. There is a plugin in the plugins.js file:
function fOnWeekNo(year, weekNo) {
...put your code here...
}
Now you may do whatever you like in the fOnWeekNo() function. It'll be called every time when you click on the week numbers of the calendar.
The calendar size is determined by the calendar cell size and the padding and spacing size of the panel table. They can be adjusted easily by editing the following options in the theme-name.js file: giCellWidth, giCellHeight, gsInnerTable, gsOuterTable.
It's because sometimes the Konqueror has difficulty in expanding the calendar panel to the correct size. Currently it can be worked around by giving the iframe tag a larger-than-usual width value since it appears to have no problem in shrinking automatically. e.g. <iframe width=600 ...>
It's a bug of certain Konqueror version. This bug exists outside the calendar engine and you may test it with any simply link on a blank page - the onclick event will not be fired after your first click unless you move the mouse out of the link and back in again. Currently it can be worked around by using onmousedown
event handler instead of onclick
. (Modify gsNavPrev/gsNavNext options accordingly)
It looks like this bug only occurs on anchor links, it's not affecting buttons.
It means that the calendar engine has not yet been loaded when you try to popup the calendar.
Please check your calendar tag first and make sure the src
property is pointing to the engine file with correct web path. Then you need to make sure there is no error generated during the engine loading process - for example, you might have a typo when modifying the theme or plugin that introduces a syntax error. The easiest way to check is to load your page into a Mozilla browser and check its JavaScript Console to see if there were any errors being reported.
There is another possibility that you will see this error - if your page took a long time to load and the user tried to trigger the popup before the page is fully loaded. This usually is not an issue because it'll be working fine after the page finishes loading. If you really don't want to see this error, you may simply prepend "if(self.gfPop)" condition check to the onclick event handler. e.g.
<a onclick="if(self.gfPop)gfPop.fPopCalendar(...);else alert('Please wait until the page is fully loaded.'); return false;" ...>...</a>
You need to put 4 lines of code into the fOnChange() plugin function. e.g.
function fOnChange(y,m,d,e) {
...
if (m!=gCurMonth[1]&&[y,m,d]+''!=gToday+'') { // cancel the auto month switching
fRepaint();
return true;
}
return false; // return true to cancel the change.
}
So afterwards, clicking the dimmed days that belongs to prev/next months will no longer automatically switch the calendar.
It's a bug of IE, all other browsers work fine without any problem. To work around, you just need to append one more line as following to the document.onmousedown event handler in your page.
document.onmousedown=function(e){
...
if (!e) self.event.srcElement.focus();
}
It's a CSS bug of IE6 only, and doesn't exist in earlier versions of IE. To work around, you just need to give the tab page tag that contains the date field a style of at least 1px padding. e.g. If the tab page is a <div>
tag, you'll need the following css class definition in your page.
<style>
div {padding:1px}
</style>
There is a new call-back function in the plugins.js called fIsSelected(y,m,d)
, which determines whether to mark the passed-in date as a selected date. If this function returns true
, the specific date passed in will be marked as selected using theme options giMarkSelected
, gcFGSelected
, gcBGSelected
and guSelectedBGImg
. Please refer to the Plugins SDK tutorial for details.
To select multiple dates, you just need to create an array in the plugins.js to store either the selected dates or the selected date range. The array takes values via fOnChange()
or fAfterSelected()
, then it's checked from within the fIsSelected()
function. You may find a good example in the MultiPicker demo in FlatCalendarXP or the WeekPicker demo in PopCalendarXP.
Please have a look at the setup agenda and holidays tutorial, it's detailed there.
Please check the fOnDrag()
plugin call and make sure it returns false
. If it returns true
, the "set date" action will be cancelled and hence the fOnChange()
and fAfterSelected()
will not be called.
You just need to give your month navigator tags an id of "navPrev" or "navNext" and the calendar engine will then find them and start auto-traverse when you holding down the mouse button on them. Take a look at the existing themes for a sample.
In the theme-name.js file you may find an option called gsOutOfRange
, setting it to an empty string ""
will disable such alerts.
In the plugins.js file add some extra code to the fOnChange()
function, as following:
function fOnChange(y,m,d,e) {
if (d==0) {
var lastDay=fGetDays(y)[m];
fUpdSelect(y,m,lastDay<gdSelect[2]?lastDay:gdSelect[2]);
}
}
It's a CSS bug of Safari, and doesn't exist in other browsers. It's related to the way how Safari handles the CSS rule of "display:table-row".
To work around, you'll have to wrap another <div style='display:table-row'>
tag to the html
contents of the event if running inside Safari. e.g.
fAddEvent(2004,3,20,"test", ... ,(SA?"<div style='display:table-row'>":"")+"<div class='MsgBoard'>test</div>"+(SA?"</div>":""));
NOTE: You may ask why wrapping it conditionally(only when Safari is detected)? The answer is IE6 doesn't like such wrapping for some reason and will choke on it.
Check for gBegin
and gEnd
options in the theme-name.js
file and replace them with the following code:
var gBegin=gToday;
var _dEnd=new Date(gToday[0],gToday[1]-1,gToday[2]+7);
var gEnd=[_dEnd.getFullYear(),_dEnd.getMonth()+1,_dEnd.getDate()];
NOTE: The month number used in the javascript Date object is ranged from 0 to 11.
To get rid of the line-through effect on disabled or out-of-range dates, you just need to append the following line to the plugins.js file:
_lineThru=false;
By default the engine only provides 2 theme options to config the tooltip and background image of the out-of-range dates - gsOutOfRange
& guOutOfRange
. If you want more varied look-and-feel, you just have to code a bit more with the help of agenda.js
- for example adding the following line of code in fHoliday
will give the out-of-range dates a red font color and a green boxed background:
function fHoliday(y,m,d) {
if (!fValidRange(y,m,d)) return [gsOutOfRange,null,"green","red",guOutOfRange,true];
...
}
Make sure you have set the gAgendaMask
option properly beforehand, otherwise you may get nothing changed in the look since the corresponding bit may be masked.
The default algorithm employed is ISO8601 standard, which means Jan 1st will belong to the last week of last year if it falls in the last 3 days of a week. To make it more flexible, now you may re-define the fWeekOffset
function in plugins.js
to return an offset of 1 or 0, which will be used to adjust the week number.
The day-of-week location of Jan 1st will be passed in as the only parameter. This location is a number of between 0 and 6 that denotes one of the 7 day-of-week columns of the calendar from left to right. Say you want that Jan 1st should be taken into the week no.1 of the current year only when it falls between Monday-Friday, and the giFirstDOW
is set to 0 (means week column 0 is Sunday), then you should add the following code to plugins.js
:
function fWeekOffset(dow) {
return 1<=dow&&dow<=5?1:0;
}
If the giFirstDOW
is set to 1 (means week column 0 is Monday), then the following code should be used instead (because Monday - Friday is 0 - 4 now):
function fWeekOffset(dow) {
return dow<=4?1:0;
}
Please refer to the bundled Classic Demo for details.
In most themes, all you need is to clear the gdSelect
variable and repaint the calendar. e.g. create a de-select function in the plugins.js
:
function fDeselect() {
fUpdSelect(0,0,0); // clear gdSelect
fRepaint();
}
Then call it whenever you want to remove the selected date from the calendar. Note, some themes may use additional variable to store multiple selected dates, and you just need to clear them in the same call.
Most likely you are using the calendar within a relative-positioned tag, and this is a well-known css bug of IE. To work around, you just need to add the following rules to your css file (suppose the id of the relative-positioned tag is myTagId
). Of course you may use css class rule (.myTagClass) instead of id rule (#myTagId), but you must keep the "* html
" prefix to make the fix apply to IE without affecting the other browsers:
* html #myTagId {height: 1%;} /* for IE/Win */
*>html #myTagId {height: auto;} /* for IE5/Mac */
It's also known as "Holly Hack", you may follow the link for details if you are interested.
Some of our customers are interested in creating the calendar tag dynamically instead of having it written statically at the page bottom. The following code can do the trick on IE5+, Opera 7.54 and most Mozilla based browsers:
<script>
var html = '<ifr'+'ame name="gToday:normal:agenda.js" id="gToday:normal:agenda.js" src="ipopeng.htm" scrolling="no" frameborder="0" style="visibility:visible; z-index:999; position:absolute; left:-500px; top:0px;"></ifr'+'ame>';
if (document.all)
document.body.insertAdjacentHTML('beforeEnd', html);
else {
var range = document.createRange();
range.setStartAfter(document.body.lastChild);
var docFrag = range.createContextualFragment(html);
document.body.appendChild(docFrag);
}
</script>
It's not fully tested on every platform, but you got the idea on how to do it.
Since version 9.0.236, the engine has built-in support to hide the calendar panel if user clicks on places other than the trigger element. Nonetheless, if you use the onmousedown
event instead of the suggested onclick
event to trigger the calendar, you're required to mark down the trigger element explicitly by either giving it a css class name of "PopcalTrigger
" or name it directly as "popcal
". e.g.
<a href="javascript:void(0)" onmousedown="if(self.gfPop)gfPop.fPopCalendar(document.demoform.dc);return false;"><img class="PopcalTrigger" align="absmiddle" src="calbtn.gif" width="34" height="22" border="0" alt=""></a>
If you choose the css way, you don't even have to define the PopcalTrigger
in your css file, it's just a marker. Moreover, if you already had a class assigned to that tag, you still can append the marker to it - just separate them with a space char. e.g.
<img class="MyImgClass PopcalTrigger" align="absmiddle" src="calbtn.gif">
The marker wouldn't change the appearance at all, but if you don't mark it the calendar may not be able to show up. The engine needs to know the trigger tag (most of the time it's just a calendar image, but could also be a textfield or anything you use to take the mouse clicks) so that it will show, instead of hide, the calendar upon clicking.
However, you can't use this approach with NN4 since NN4 doesn't support multiple css classes. To take NN4 into account, you must either rename the MyImgClass
rule into PopcalTrigger
, or choose the 2nd option to name it directly as "popcal". e.g.
<img class="MyImgClass" name="popcal" align="absmiddle" src="calbtn.gif">
Although in most cases we only need 1 calendar engine tag (iframe) in page, it doesn't mean we are restricted to it. Sometimes we need 2 calendar pickers with different behaviors or looks, and the following steps to get them work:
This way, you can have one picker with format "YYYYMMDD" and the other with "DD/MM/YYYY", preferrably with different looks. You can even have different agendas assigned to each calendar if you like - just name them separately as agenda1.js and agenda2.js. All can happen in the same page.
If you allow user to key in date string directly, you may want to validate it. The easiest way is to use the built-in functions of the calendar engine to do the job:
onblur="fValidate(this)"
.<script>
function fValidate(textbox) {
var dt=gfPop.fParseInput(textbox.value);
if (dt==null) {alert("Invalid date format!");textbox.focus();}
}
</script>
Relax, that's the new script blocker introduced in IE6 of WinXP SP2. The alert will show up whenever you try to access a javascript page from local file explorer. However, it doesn't seem to affect the page on a real website. We've tested the calendars on different websites and haven't seen any alert. Please take a look at our online demos to get a peace of mind.
You'll need the following function and have to call it in the onload
event of your html body tag, at which point the calendar engine has been fully loaded. e.g.
<body onload="fPresetDate(document.form1.datefield1,2005,12,10);">
<script>
function fPresetDate(field,y,m,d) {
field.value=gfPop.fFormatInput(y,m,d);
}
</script>
Of course, you can replace the y
, m
or d
with server-side variables if you are using it in ASP or JSP.