//
// 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)
// Modified by dth

// Configurable values are set to defaults here; you can override them before calling Calendar( ) from your HTML page or common.js file

var SpecialDay=1;          // 1=Sunday, 2=Monday, . . . 7=Saturday
var ColorBackground="#f4f1e5";  // Color of the Calendar Background
var ColorSpecialDay = "#5e8cc7";  // Special Day can be any day of the week as set by SpecialDay above
var ColorToday = "green";  // Current Date color
var ColorEvent = "blue";  // Color of Event Date
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 = true;   // 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 = true;           // span empty cells (before 1st day and after last) for messageBox use
var showMini = true;     // 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 = "#c8b49a";  // Background color of Message Box
var msgBoxText = "#c8b49a";  // font color of messages
var navColor = "#c8b49a";  // Background color of Navigation Hyperlinks
var imageAlign = "left";   // default event image alignment
var imageScale = 100;    // percent scale factor for images
var altAlign = false;     // 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
var defaultMsgBox = "<b></b>";  // blank message in message box
var frames = "yes";    // value of "yes" opens second browser window, "no" does not.
var DateFontSize=5;    // calendar dates font size
var DateFontColor="black"  // calendar dates font color
var holidaycolor="#999999";  // color of Holiday text (#999999 = Gray)

// all format codes must have "|" to separate before and after tags

var AltDateFormat = "<font color=#999999 size=2>|</font>";
var MonthFormat = "<font size=" + DateFontSize + "><b>|</b></font>";
var AltMonthFormat = "<br><font color=#999999 size=" + DateFontSize/2 + ">|</font>";
var HolidayFormat = "<font color=" +holidaycolor+" size=2><b><center>|</center></b></font>";
var AltHolyFormat = "<font  size=2><b><center>|</center></b></font>";
var DefaultLayerFormat = "<font size=2>|</font>";



// 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 = false;

// 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 <BR>, <strong>, 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 setEvent(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<arr.arguments.length;n++) {
    this[n+1] = arr.arguments[n];
  }
}

// Create the array of month names (used in various places)

var months = new arr("January","February","March","April","May","June","July","August","September","October","November","December");

//
//
// Calendar( ) is the only routine that needs to be called to display the calendar
//
//

var cookieName = "layerCalendar";
var pre, post, tmp, gloMo, gloYr, gloYearmonth;

function Calendar( ) {
  var curdy, curmo, yr, mo, dy, firstday, yearmonth, bgn, lastdate, jump;
  var weekdays = new arr("Sun","Mon","Tue","Wed","Thu","Fri","Sat");

  var thispage = window.location.pathname;

  var myMsgBox = "";
  var href;
  // define default MsgBox messages

  AddMsgBox(0, defaultMsgBox);
  AddMsgBox(0, myMsgBox);

  // Save current day and month for comparison

  curdy = today.getDate();
  curmo = today.getMonth()+1;
  initCal(curmo);
  mo = gloMo; yr = gloYr; yearmonth = gloYearmonth;
  getLayersVisible();     // get layer visibility settings from cookie

  // Create a date object for the first day of the desired month

  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);
  lastday = 1+(firstday + lastdate - 1)%7;
  prev = next = "&nbsp;";
  if (showNav) {
    if (yearmonth > FirstMonth)
                        prev = '<a class="navlink" href="' + thispage + '?'+PrevYearMonth(yearmonth)+'">&lt;-- View '+months[PrevMonth(mo)]+'</a>';
    if (yearmonth < LastMonth)
                        next += '<a class="navlink" href="' + thispage + '?'+NextYearMonth(yearmonth)+'">View '+months[NextMonth(mo)]+' --&gt;</a>';
  }

  parseFormat(MonthFormat);
  tmp = "<TABLE width=80% ALIGN=CENTER BORDER=2 BGCOLOR="+ColorBackground+"><TR BORDER=0 BGCOLOR="+navColor+">";
  tmp += "<TD ALIGN=CENTER BGCOLOR="+navColor+">" + prev + "</TD>";
  tmp += "<TD ALIGN=CENTER COLSPAN=5>" + pre + months[mo] + " " + yr + post;

  if (showAltDate) {
    parseFormat(AltMonthFormat);
    altMonth = getAltMonth(1, mo, yr, lastdate);
    tmp += pre + (altMonth ? altMonth : "") + post;
  }
  tmp += "</TD><TD ALIGN=CENTER BGCOLOR="+navColor+">" + next + "</TD></TR>";
  document.write(tmp);
  document.write("<TR BGCOLOR="+navColor+">");

  for (var i=1;i<=7;i++){
    document.write("<TD ALIGN=CENTER WIDTH=14%><FONT SIZE=2>"+weekdays[i]+"</FONT></TD>");
  }
  dy = 1;
  document.write("</TR><TR>");

  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("<TD BGCOLOR="+ColorBackground+">");
            MiniMonth(PrevYearMonth(yearmonth));
          } else {
            document.write("<TD>&nbsp;");
          }
        } else if (showMsgBox && i==2) {   // span empty cells to allow messageBox
          msgSpan = firstday - 1;
          document.write("<TD BGCOLOR=" + navColor + " COLSPAN=" + msgSpan +">&nbsp;");
          DoMsgBox(yearmonth, msgSpan);
        } else if (!showMsgBox) {
          document.write("<TD>&nbsp;");
        }
        document.write("</TD>");

      // 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("<TD BGCOLOR="+ColorBackground+">");
            MiniMonth(NextYearMonth(yearmonth));
          } else {
            document.write("<TD>&nbsp;");
          }
        } else if (showMsgBox && i==(lastday+1)) {   // span empty cells to allow messageBox
          msgSpan = 6 - lastday;
          document.write("<TD BGCOLOR=" + navColor + " COLSPAN=" + msgSpan +">&nbsp;");
          DoMsgBox(yearmonth, msgSpan);
        } else if (!showMsgBox) {
          document.write("<TD>&nbsp;");
        }
        document.write("</TD>");


      // Otherwise, write date and the event, if any, in this cell of the table.

      } else {
        document.write("<TD VALIGN=TOP>");
        ShowDate(yr,mo,dy,i,curmo,curdy);
        document.write("</TD>");
        dy++;
      }
    }
    document.write("</TR>");
  }

  if (showNav) {
    prev = next = "&nbsp;";
    if (yearmonth > FirstMonth)
      prev = '<a class="navlink" href="' + thispage + '?'+PrevYearMonth(yearmonth)+'">&lt;-- View '+months[PrevMonth(mo)]+'</a>';
    if (yearmonth < LastMonth)
      next += '<a class="navlink" href="' + thispage + '?'+NextYearMonth(yearmonth)+'">View '+months[NextMonth(mo)]+' --&gt;</a>';
    tmp = "<TR BGCOLOR="+navColor+"><TD ALIGN=CENTER BGCOLOR="+navColor+">" + prev + "</TD>";
    tmp += "<TD colspan=5 align=center valign=middle><FORM>";
    if (ExportPage) tmp += '<a class="navlink" href="' + ExportPage + '?'+yearmonth+'">Export Events Displayed</a>&nbsp;&nbsp;|&nbsp;&nbsp;';
    tmp += 'Jump to month:&nbsp;&nbsp;';
    document.write(tmp);
    BuildSelectionList(yearmonth, thispage);
    if (PrintPage) document.write('&nbsp;&nbsp;|&nbsp;&nbsp;<a class="navlink" href="' + PrintPage + '?'+yearmonth+'">Print-friendly</a>');
    tmp = "</FORM></TD><TD ALIGN=CENTER BGCOLOR="+navColor+">" + next + "</TD>";
    document.write(tmp + "</TR>");
    if (layerCount>1) {
      document.write("<TR BGCOLOR="+navColor+"><TD colspan=7 align=center>");
      ChooseLayers(yearmonth, thispage);
      document.write("</TD></TR>");
    }
  }
  document.write("</TABLE>");
}

//
//  End of Calendar Function
//


// 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 = "<TABLE><TR VALIGN=TOP><TD ALIGN=LEFT WIDTH=10%>";
  tmp += "<FONT SIZE=" + DateFontSize;  // Note open tag!
  DayHighlighted = false;

  if ((mo == currentmonth) && (dy == currentday)) {
    tmp += " COLOR=" + ColorToday;
    DayHighlighted = true;
  } else if (dayofweek == SpecialDay) {
    tmp += " COLOR=" + ColorSpecialDay;
    DayHighlighted = true;
  }
  ind = (((yr * 100) + mo) * 100) + dy;
  if (Events[ind]) {
    //event = Events[ind];
    if (!DayHighlighted) tmp += " COLOR=" + ColorEvent;
  } else {
    tmp += " COLOR=" + DateFontColor;
    DayHighlighted = false;
  }
  tmp += "><B>" + dy + (dy<10 ? "&nbsp;" : "") + "&nbsp;</B></FONT></TD>";     // close tag
  document.write(tmp);

  if (showAltDate) {
    altDate = getAltDate(dy, mo, yr);
    parseFormat(AltDateFormat);
    document.write("<TD ALIGN=RIGHT>" + pre + altDate + post + "</TD>");
  }
  document.write("</TR></TABLE>");

  if (showAltHoly) {
    tmp = getAltHoly(dy,mo,yr);
    if (tmp) {
      parseFormat(AltHolyFormat);
      document.write(pre + tmp + post + "<BR>");
    }
  }

  if (showHolidays) {
    tmp = holidays(dy,mo,yr);
    if (tmp) {
      parseFormat(HolidayFormat);
      document.write(pre + tmp + post + "<BR>");
    }
  }

  images=0;
  for (j in Events[ind]) {
    ev = Events[ind][j];
    tmp = "";
    if (Layers[ev.layer].show == "true") {
      tmp += (j>0 ? "<br>" : "");
      if (ev.image && showImages) {
        if (ev.align) {
          align = ev.align;
        } else if (altAlign && images>0) {
          align = (lastAlign=="left" ? "right" : "left");
        } else {
          align = imageAlign;
        }
        tmp += '<img src="' + ev.image +
             (ev.width ? '"  width="' + ev.width*imageScale/100 : '') +
             (ev.height ? '" height="' + ev.height*imageScale/100 : '') +
             (ev.alt ? '" alt="' + ev.alt : '') +
             '" align="' + align + '" valign="top">';
        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);
      if (frames == "yes") {
        tmp += pre + (ev.link && showLinks ? "<a class=\"eventlink\" href="+ev.link+" target=_blank"+">"+ev.description+"</a>" : ev.description) + post + "<br>";
      } else if (frames == "no") {
        tmp += pre + (ev.link && showLinks ? "<a class=\"eventlink\" href="+ev.link+">"+ev.description+"</a>" : ev.description) + post + "<br>";
      }
    } else {

    }
  document.write("<FONT SIZE=1>" + tmp + "</FONT>");
  }
}

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 = "<textarea NAME=\"txt\"  ROWS=20 COLS=75 WRAP=VIRTUAL>";
  tmp += '"Subject","Start Date","Start Time","End Date","End Time","All day event","Description","Show time as","Location"\n';
  document.write(tmp);
  for (dy=1; dy<=lastdate; dy++) {
    ind = (((yr * 100) + mo) * 100) + dy;
    evdate = mo + "/" + dy + "/" + yr;
    for (j in Events[ind]) {
      ev = Events[ind][j];
      if (Layers[ev.layer].show == "true") {
        //alert("(+)showing event for "+ind+" in layer "+ev.layer);
        tmp = qw(ev.description) + "," + qw(evdate) + ",,,," + qw("true") + ",," +
           qw("3") + "," + qw("CalendarScript");
        if (ev.description) document.write(tmp+"\n");
      } else {
        //alert("(-)skipping event for "+ind+" in layer "+ev.layer);
      }
    }
  }
  document.write("</textarea>");
}

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<layerCookies.length; i++) {
          sep = layerCookies[i].indexOf("=");
    name = layerCookies[i].substring(0, sep);
    value = layerCookies[i].substring(sep+1, layerCookies[i].length);
    if (Layers[name]) Layers[name].show = value;
    //alert("Read cookie: "+name+"="+value+" Layers["+name+"]="+Layers[name].show);
      }
  }
}
function initCal(curmo) {

  // create default layer

  if (!Layers["default"]) DefineLayer("default", DefaultLayerFormat);

  // Default to current month and year

  mo = curmo;
  yr = GetFullYear(today);
  yearmonth = (yr * 100) + mo;

  // If querystring parameter is present, get the month/year ("calendar.htm?YYYYMM")

  if (location.search.length > 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 "&quot;" + string + "&quot;";
}

// 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("<b><tt><Font Size=2><div align=center>&nbsp;" + months[mo] + "</div></font>");
  miniweek = "<font size=1>&nbsp;<u>";
  for (d in days) { miniweek += "&nbsp;" + days[d] + "&nbsp;"; }
  document.write(miniweek,"</u>");
  dy = 1;

  // Rest of the weeks . . .

  while (dy <= lastdate) {
    miniweek = "<br>";
    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 += "&nbsp;&nbsp;&nbsp;";

      // 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 += "&nbsp;" + ( dy<10 ? "&nbsp;" : "" ) +dy;
        dy++;
      }
    }
    document.write(miniweek);
  }
  document.write("</font></tt></b>");
}


// 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 = "<select name=\"jumpmonth\" size=1 onchange=\"JumpTo(this,'" + thispage + "')\">";
  while (yearmonth <= LastMonth) {
    mo = yearmonth % 100;
    yr = (yearmonth - mo) / 100;
    selected = (yearmonth == current ? " selected" : "");
    tmp += "<option value=" + yearmonth + selected + ">" + months[mo]+" "+yr;
    yearmonth = NextYearMonth(yearmonth);
  }

  document.write(tmp + "</select>");
}

// 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 + "<br>");
        if (!monthlyMsg.minspan || monthlyMsg.minspan <= msgSpan) {
          tmp = "<table border=2 bgcolor=" + msgBoxColor + " align=center>";
          tmp += "<TR><TD>"+ "<font color=" + msgBoxText + ">" + monthlyMsg.message + "</TD></TR></table>";
          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 + "<br>");
        if (!monthlyMsg.minspan || monthlyMsg.minspan <= msgSpan) {
          tmp = "<table border=0 bgcolor=" + msgBoxColor + " align=center>";
          tmp += "<TR><TD>"+ "<font color=" + msgBoxText + ">" + monthlyMsg.message + "</TD></TR></table>";
          document.write(tmp);
          monthlyMsg.shown = true;
          return;
        }
      }
    }
  }
}

// Utility routines

function escramVal(j,k){var a,b,c,d,e;a='<a href=\"mai';c='\">';a+='lto:';b=j+'@';e='</a>';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 = '<form name="layerform"><b>Filter Events:</b>&nbsp;';
  for (i in Layers) {
    if (i != "default") {
      checked = (Layers[i].show == "true" ? " checked" : "");
      parseFormat(Layers[i].format);
      tmp += pre + '<input type="checkbox" name="' + i + '" value="' + i + '"' +checked +
        ' onClick="ChangeLayer(\''+i+'\')">' + i + "&nbsp;" + post;
    }
   }
  tmp += '&nbsp;<input type="button" name="ApplyChanges" value="Apply Changes"' +
    'onClick="ApplyLayerChange(\'' + thispage + '\',\'' + yearmonth + '\')">';
  document.write(tmp + "</form>");
}

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;
    }
  }
  document.cookie = escape(cookie);
  document.location = thispage + (yearmonth ? "?"+yearmonth : "");
}
