//
// Enhanced JavaScript Event Calendar
//
// Author: Rick Pike
// Website: http://calendar.pikesys.com
// Email: calendar@pikesys.com
//'Version 0.3 - (07-May-2004)
//
// based on an earlier script by Kevin Ilsen (http://calendar.ilsen.net or kevin@ilsen.net)
// Configurable values are set to defaults here; you can override them before calling Calendar( ) from your HTML page
var SpecialDay=0; // 1=Sunday, 2=Monday, . . . 7=Saturday
var ColorBackground=""; //normally "ffffcc"
var ColorSpecialDay = "#807559"; //normally "red"
var ColorToday = "#A84808"; //normally #BFA660
var ColorEvent = ""; //normally "blue"
var showAltDate = false; // add display of alternate date using results from user supplied "getAltMonth(dy, mo, yr, last)" and "getAltDate(dy, mo, yr)" functions
var showHolidays = false; // add display of holidays using result from user supplied "holidays(dy, mo, yr)" function
var showAltHoly = false; // add display of alternate holidays using result from user supplied "getAltHoly(dy, mo, yr)" function
var showMsgBox = false; // span empty cells (before 1st day and after last) for messageBox use
var showMini = false; // add minimonth display of prior and next months if first and/or last boxes are available
var showNav = true; // enable month navigation (might disable for print version)
var showImages = true; // enable event images (might disable for print version)
var showLinks = true; // enable event hyperlinks (might disable for print version)
var msgBoxColor = "#ffcc99";
var navColor = "A8C4E3"; //normally "#ffff99"
var imageAlign = "left"; // default event image alignment
var imageScale = 100; // percent scale factor for images
var altAlign = true; // alternate left/right alignment of event images on same date for readability
var DefaultFormat = "layer"; // for compatibility; set to "layer" to simplify formatting
var ExportPage = ""; // name of html page for displaying event text for export
var PrintPage = ""; // name of html page for printer-friendly format
// all format codes must have "|" to separate before and after tags
var DateFontSize=4;
var AltDateFormat = "|";
var MonthFormat = "|";
var AltMonthFormat = " |";
var HolidayFormat = "
|
";
var AltHolyFormat = "
|
";
var DefaultLayerFormat = "|";
var defaultMsgBox = "Note: The information here may not be current; please confirm dates and times.
";
// Initialize the range of the calendar to Jan - Dec of the current year.
// Event definitions will change this as needed; or it can be explicitly
// overridden before calling Calendar( ) from the HTML page.
var today = new Date();
var FirstMonth=GetFullYear(today) * 100 + 1;
var LastMonth=FirstMonth + 11;
// Layers[] is an array of layer names and default formats. Call DefineLayer( ) to add the
// layer name and corresponding format. New layer names in event definitions will
// be added automatically (watch case and spelling).
var Layers = new Array;
var LayerString = "|";
var layerCount = 0;
var layerChange = true;
// MsgBoxes[] is a SPARSE array; Call AddMsgBox( ) to populate it
var MsgBoxes = new Array;
// Events[] is a SPARSE array; Call AddEvent( ) to populate it or DefineEvent( ) for
// compatibility with existing calendar definition scripts.
var Events = new Array;
// Each event is defined by calling the AddEvent( ) routine with the following parameters:
//
// AddEvent(Date, Description, Layer, Format, Link, Image, Width, Height, Align, Alt)
// Date is a numeric value in the format YYYYMMDD
// Description is a string (may include embedded HTML tags such as , , etc.)
// Layer is an event category whose display on the calendar can be toggled on/off by the user
// Format specifies the source of the format info for Description. Note that any embedded
// formats in Description will still be applied; this argument is primarily to provide
// a more convenient way to specify formats.
// "layer" = use default format from layer definition (plus any embedded tags!)
// "custom" = only use format tags embedded in Description string
// "<...>|" = series of before and after tags separated by a "|" to wrap around
// Description (plus any embedded tags!)
// Link is the URL of the target page if a hyperlink is desired from this event entry
// Image is the URL of the image if you want to display an image with this event
// Width is the width of the image in pixels
// Height is the height of the image in pixels
// Align is the alignment of the image such as "left", or "right"
// Alt is the alternate text of the image (for mouseover or non-graphic browser)
// The function DefineEvent(Date, Description, Link, Image, Width, Height) is used
// for compatibility with previous calendar definition scripts
// Event constructor
function Event(description, layer, format, link, image, width, height, align, alt) {
this.description = description;
if (link) this.link = link;
if (image) {
this.image = image;
if (width) this.width = width;
if (height) this.height = height;
if (align) this.align = align;
if (alt) this.alt = alt;
//alert("Event: ("+this.width+","+this.height+")");
}
this.layer = (layer ? layer : "default"); // must have some associated layer
if (format) {
if (CheckFormat(format)) this.format = format;
}
}
// Compatibility function for existing calendar definition scripts
function DefineEvent(Date, Description, Link, Image, Width, Height) {
AddEvent(Date, Description, "", "", Link, Image, Width, Height, "", "");
}
function AddEvent(Date, Description, Layer, Format, Link, Image, Width, Height, Align, Alt) {
var i;
if (!Events[Date]) Events[Date] = new Array;
i = Events[Date].length;
Events[Date][i] = new Event(Description, Layer, Format, Link, Image, Width, Height, Align, Alt);
// Adjust the minimum and maximum month & year to include this date
tmp = Math.floor(Date / 100);
if (tmp < FirstMonth) FirstMonth = tmp;
if (tmp > LastMonth) LastMonth = tmp;
// if EventLayer not in Layers, add it
// NOTE: watch case in DefineLayer and DefineEvent to avoid undesired "duplicates"
//alert("AddEvent("+Date+","+Description+","+Width+","+Height+"...)");
if (Layer && !Layers[Layer]) DefineLayer(Layer);
}
// Layer constructor
function Layer(format, show) {
if (format) {
if (format.indexOf("|")>0) {
this.format = format;
} else {
alert("Invalid Calendar Format String: " + format);
}
} else {
this.format = DefaultLayerFormat;
}
this.show = (show=="false" ? "false" : "true"); // watch boolean vs. string arg
}
function DefineLayer(LayerName, LayerFormat, LayerShow) {
Layers[LayerName] = new Layer(LayerFormat, LayerShow);
layerCount++;
}
// Utility function to populate an array with values
function arr() {
for (var n=0;n FirstMonth)
prev = '';
if (yearmonth < LastMonth)
next += '';
}
parseFormat(MonthFormat);
tmp = "
");
while (dy <= lastdate) {
for (var i=1; i<=7; i++) {
// If the day cell is before the first day of the month, print a miniMonth display of previous month in the first cell,
// otherwise print a space in this cell of the table.
if (dy == 1 && i <= firstday) {
if (i == 1) {
if (showMini) {
document.write("
");
DoMsgBox(yearmonth, msgSpan);
} else if (!showMsgBox) {
document.write("
");
}
document.write("
");
// If the day cell is after the last day of the month, print a miniMonth display of following month in the last cell,
// otherwise print a space in this cell of the table.
} else if (dy > lastdate) {
if (i == 7) {
if (showMini) {
document.write("
");
}
// Display a date in the appropriate color, with events (if there are any)
function ShowDate(yr, mo, dy, dayofweek, currentmonth, currentday) {
var ind, DayHighlighted, tmp, event;
tmp = "
";
tmp += "" + dy + (dy<10 ? " " : "") + "
"; // close tag BG MOD change
document.write(tmp);
if (showAltDate) {
altDate = getAltDate(dy, mo, yr);
parseFormat(AltDateFormat);
document.write("
" + pre + altDate + post + "
");
}
document.write("
");
if (showAltHoly) {
tmp = getAltHoly(dy,mo,yr);
if (tmp) {
parseFormat(AltHolyFormat);
document.write(pre + tmp + post + " ");
// removed between quotation marks
}
}
if (showHolidays) {
tmp = holidays(dy,mo,yr);
if (tmp) {
parseFormat(HolidayFormat);
document.write(pre + tmp + post + " ");
// removed between quotation marks
}
}
// document.write("
" + event );
images=0;
for (j in Events[ind]) {
ev = Events[ind][j];
tmp = "";
if (Layers[ev.layer].show == "true") {
//alert("(+)showing event for "+ind+" in layer "+ev.layer);
// Build the HTML string for this event
tmp += (j>0 ? " " : "");
// removed between quotation marks
if (ev.image && showImages) {
if (ev.align) {
align = ev.align;
} else if (altAlign && images>0) {
align = (lastAlign=="left" ? "right" : "left");
} else {
align = imageAlign;
}
tmp += '';
lastAlign = align;
images++;
}
format = "";
if (ev.format == "layer") { // use format from layer (and embedded tags)
format = Layers[ev.layer].format;
} else if (ev.format == "custom") { // use only embedded tags
format = "";
} else if (ev.format) { // format string?
if (CheckFormat(ev.format)) format = ev.format;
} else if (DefaultFormat == "layer") { // use format from layer if no custom format
format = Layers[ev.layer].format;
}
parseFormat(format);
tmp += pre + "" + (ev.link && showLinks ? ""+ev.description+"" : ev.description) + post + "";
// removed between quotation marks
} else {
}
document.write(tmp);
}
}
function exportCal( ) {
var curdy, curmo, yr, mo, dy, firstday, yearmonth, lastdate;
// Save current day and month for comparison
curdy = today.getDate();
curmo = today.getMonth()+1;
initCal(curmo);
mo = gloMo; yr = gloYr; yearmonth = gloYearmonth;
getLayersVisible();
// Create a date object for the first day of the desired month
lastdate = NumDaysIn(mo,yr);
tmp = "");
}
function getLayersVisible() {
// get layer visibility settings from cookie
prefix = cookieName + "|";
cookie = unescape(document.cookie);
pos = cookie.indexOf(prefix);
if (pos>=0) {
pos += prefix.length;
sep = cookie.indexOf(";");
if (sep == -1) sep = cookie.length;
var layerCookies = cookie.substring(pos, sep).split("|");
for (i=0; i 1) {
yearmonth = parseInt(location.search.substring(1,location.search.length));
if ((""+yearmonth).length == 6) {
mo = yearmonth % 100;
yr = (yearmonth - mo) / 100;
}
}
// Constrain to the range of months with events
if (yearmonth < FirstMonth) {
mo = FirstMonth % 100;
yr = (FirstMonth - mo) / 100;
yearmonth = FirstMonth;
}
if (yearmonth > LastMonth) {
mo = LastMonth % 100;
yr = (LastMonth - mo) / 100;
yearmonth = LastMonth;
}
gloMo = mo; gloYr = yr; gloYearmonth = yearmonth;
}
function qw(string) {
return """ + string + """;
}
// Create a mini display of the desired month
function MiniMonth(yearmonth) {
var bgn, firstday, lastdate, miniweek;
var days = new arr("S","M","T","W","T","F","S");
mo = yearmonth % 100;
yr = (yearmonth - mo) / 100;
bgn = new Date(months[mo] + " 1," + yr);
// Get the day-of-week of the first day, and the # days in the month
firstday = bgn.getDay();
lastdate = NumDaysIn(mo,yr);
document.write("
" + months[mo] + "
");
miniweek = " ";
for (d in days) { miniweek += " " + days[d] + " "; }
document.write(miniweek,"");
dy = 1;
// Rest of the weeks . . .
while (dy <= lastdate) {
miniweek = " ";
// removed between quotation marks
for (var i=1;i<=7;i++) {
// If the day is less than the day of the week of the first day of the month, append spaces
if (dy == 1 && i <= firstday){
miniweek += " ";
// End minimonth if the day > last day of the month
} else if (dy > lastdate) {
break;
// Otherwise, append date (w/ extra space for single digits)
} else {
miniweek += " " + ( dy<10 ? " " : "" ) +dy;
dy++;
}
}
document.write(miniweek);
}
document.write("");
}
// Remaining routines are utilities used above
function NumDaysIn(mo,yr) {
if (mo==4 || mo==6 || mo==9 || mo==11) return 30;
else if ((mo==2) && LeapYear(yr)) return 29;
else if (mo==2) return 28;
else return 31;
}
function LeapYear(yr) {
return ( (yr%4 == 0 && yr%100 != 0) || yr % 400 == 0 ? true : false );
}
// fixes a Netscape 2 and 3 bug
function GetFullYear(d) { // d is a date object
var yr = d.getYear();
return ( yr < 1000 ? yr + 1900 : yr );
}
function PrevMonth(mth) {
return ( mth == 1 ? 12 : mth - 1 );
}
function NextMonth(mth) {
return ( mth == 12 ? 1 : mth + 1 );
}
function PrevYearMonth(yrmth) {
return ( yrmth%100 == 1 ? yrmth-100+11 : yrmth-1 );
}
function NextYearMonth(yrmth) {
return ( yrmth%100 == 12 ? yrmth-11+100 : yrmth+1 );
}
function JumpTo(calendar, thispage) {
var sel, yrmo;
sel = calendar.selectedIndex;
yrmo = calendar.form.jumpmonth[sel].value;
document.location = thispage + "?" + yrmo;
}
function BuildSelectionList(current, thispage) {
var mo, yr, yearmonth;
yearmonth = FirstMonth;
tmp = "");
}
// Create a message box
function DoMsgBox(yearmonth, msgSpan) {
if (MsgBoxes[yearmonth]) {
for (j in MsgBoxes[yearmonth]) { // find first unshown message for month that fits
monthlyMsg =MsgBoxes[yearmonth][j];
if (!monthlyMsg.shown) {
//document.write("monthlyMsg.minspan = " + monthlyMsg.minspan + " ");
if (!monthlyMsg.minspan || monthlyMsg.minspan <= msgSpan) {
tmp = "
";
tmp += "
"+ monthlyMsg.message + "
";
document.write(tmp);
monthlyMsg.shown = true;
return;
}
}
}
}
if (MsgBoxes[0]) { // show default MsgBox messages if they exists
for (j in MsgBoxes[0]) { // find first unshown message for month that fits
monthlyMsg =MsgBoxes[0][j];
if (!monthlyMsg.shown) {
//document.write("monthlyMsg.minspan = " + monthlyMsg.minspan + " ");
if (!monthlyMsg.minspan || monthlyMsg.minspan <= msgSpan) {
tmp = "
";
tmp += "
"+ monthlyMsg.message + "
";
document.write(tmp);
monthlyMsg.shown = true;
return;
}
}
}
}
}
// Utility routines
function escramVal(j,k){var a,b,c,d,e;a='';a+='lto:';b=j+'@';e='';b+=k;d=b;return(a+b+c+d+e);}
function parseFormat(format) {
// pre and post are globals
pre = post = "";
if (format) {
var sep = format.indexOf("|");
if (sep > 0) { // split format into pre and post strings
pre = format.substring(0, sep);
post= format.substring(1+sep, format.length);
}
}
}
function CheckFormat(String) {
var okay;
okay =(String == "layer" || String == "custom" || String.indexOf("|")>0);
if (!okay) alert("Invalid Calendar Format String: " + String);
return okay;
}
// MsgBox constructor
function MsgBox(message,minspan,maxspan) {
//alert("MsgBox("+message+","+minspan+","+maxspan+")");
this.message = message;
this.minspan = (minspan ? minspan : 1);
if (maxspan) this.maxspan = maxspan;
//this.shown = false;
}
function AddMsgBox(yearmonth,message,minspan,maxspan) {
var i;
if (!MsgBoxes[yearmonth]) MsgBoxes[yearmonth] = new Array;
i = MsgBoxes[yearmonth].length;
MsgBoxes[yearmonth][i] = new MsgBox(message,minspan,maxspan);
}
function ChooseLayers(yearmonth, thispage) {
var i, checked;
tmp = '");
}
function ChangeLayer(layer) {
layerChange=true;
Layers[layer].show = document.layerform[layer].checked;
}
function ApplyLayerChange(thispage, yearmonth) {
layerChange=false;
cookie = cookieName;
for (layer in Layers) {
if (layer != "default") {
cookie += "|" + layer + "=" + Layers[layer].show;
}
}
// persist cookie?
document.cookie = escape(cookie);
//alert("set cookie="+cookie);
document.location = thispage + (yearmonth ? "?"+yearmonth : "");
}