function getItem(itemId){
 if (document.getElementById) return document.getElementById(itemId);
 else if (document.all) return document.all[itemId];
 else return new Object();
 }

//Colours current menu item.
function init(i){
 if (window.top != window.self) {
  try{
   window.top.location.href = location.href + getsource();
   }
  catch (e) {}
  }
 getItem("menu" + i).className = "thismenu";
 }

//On mouseover menu item.
function menu(item){
 item.className += " mouseovermenu";
 }

//On mouseout menu item.
function nomenu(item){
 item.className = item.className.split(" ")[0];
 }

//Highlight a picture.
function highlight(item){
 var obj = getItem(item);
 obj.width = obj.width - 10;
 obj.height = obj.height - 10;
 obj.style.border = "5px solid #959E9B";
 }

//Un-highlight a picture.
function unhighlight(item){
 var obj = getItem(item);
 obj.width = obj.width + 10;
 obj.height = obj.height + 10;
 obj.style.borderStyle = "none";
 }

//Returns the parameter value of key from the URI.
function param(key){
 var pat = new RegExp("([?]|&)" + key + "=([^&]*)");
 var text = pat.exec(location.search);
 return text ? decodeURIComponent(text[2]) : "";
 }

//Returns source taken either from query string or referrer.
function getsource(){
 var source = param("source");
 if (!source) {
  var referrer = document.referrer;
  if (referrer) {
   if (!(/^http:\/\/(www[.])?stmichaelsfarmhouse/.test(referrer))) source = referrer;
   }
  }
 return source ? "?source=" + encodeURIComponent(source.substr(0,50)) : "";
 }

//Appends source when user clicks on a link.
function doopen(item, e){
 if (!e) var e = window.event;
 e.cancelBubble = true;
 if (e.stopPropagation) e.stopPropagation();
 var source = getsource();
 if (window.top == window.self) {
  location.href = getItem(item).href + source;
  }
 else {
  window.open(getItem(item).href + source);
  location.href = "close.htm";
  }
 }

//Constructor for an Img object which stores details of an image and preloads it.
function Img(src, alt){
 this.src = src;
 this.alt = alt;
 this.image = new Image();
 this.image.loaded = 0;
 this.image.onload = function(){
  this.loaded = 1;
  }
 this.image.src = src;
 }

//Constructor for a Swap object which manages a fade/swap effect between the Img objects
//stored in its imgs array. Needs two <img> tags occupying the same size and position
//identified by its parameters. Limiting opacity to 99.9% avoids jerkiness in Mozilla.
function Swap(id0, id1){
 this.imgs = new Array();
 this.obj0 = getItem(id0);
 this.obj1 = getItem(id1);
 this.index0 = 0;
 this.index1 = 1;
 this.step = 0;
 this.action = undefined;
 }

//Removed to prototype to avoid creating unnecessary closures.
Swap.prototype.countloaded = function(){
 var loadcount = 0;
 for (var i=0; i<this.imgs.length; i++){
  if (this.imgs[i].image.loaded == 1) loadcount++;
  }
 return loadcount;
 }

Swap.prototype.initialise = function(){
  this.obj0.src = this.imgs[0].src;
  this.obj0.alt = this.imgs[0].alt;
  this.obj0.title = this.imgs[0].alt;
  this.obj0.style.zIndex = 30;
  this.obj1.style.zIndex = 20;
 }

Swap.prototype.fade = function(inc){
 if (this.step >= 100 + inc){
  this.index0 ++;
  if (this.index0 >= this.imgs.length) this.index0 = 0;
  this.index1 ++;
  if (this.index1 >= this.imgs.length) this.index1 = 0;
  this.obj0.src = this.imgs[this.index0].src;
  this.obj0.alt = "";
  this.obj0.title = "";
  this.step = 0;
  window.clearInterval(this.action);
  }
 else if (this.step == 0){
  this.obj0.style.zIndex = 10;
  opac(this.obj1, 0);
  this.obj1.src = this.imgs[this.index1].src;
  this.obj1.alt = this.imgs[this.index1].alt;
  this.obj1.title = this.imgs[this.index1].alt;
  this.step = this.step + inc;
  }
 else if (this.step >= 100){
  opac(this.obj1, 99.9);
  this.step = this.step + inc;
  }
 else{
  opac(this.obj1, this.step);
  this.step = this.step + inc;
  }
 }

//Initiates fade/swap on an array of Swap objects alternately after they have been created and their imgs loaded;
//inc is the transparency increment, rept is the fade repeat interval,
//cycle is the time cycle to repead the fade.
var nextswap = -1;
function doFade(swaparray, inc, rept, cycle){
 for (var i=0; i<swaparray.length; i++){
  swaparray[i].initialise();
  }
 window.setTimeout("interval(swaparray," + inc + "," + rept + "," + cycle +")", cycle);
 }

//Handles fade timings; we use setTimeout rather than setInterval because the latter goes 
//out of sync after a print preview has interrupted the process in Mozilla.
function interval(swaparray, inc, rept, cycle){
 var isready = 1;
 for (var i=0; i<swaparray.length; i++){
  if (swaparray[i].countloaded() < swaparray[i].imgs.length) isready = 0;
  if (swaparray[i].step > 0) isready = 0;
  }
 if (isready == 1){
  nextswap++;
  if (nextswap >= swaparray.length) nextswap=0;
  swaparray[nextswap].action = window.setInterval("swaparray[" + nextswap + "].fade(" + inc + ")", rept);
  }
 window.setTimeout("interval(swaparray," + inc + "," + rept + "," + cycle +")", cycle);
 }

//Cross-browser function to set opacity.
function opac(obj, opacity){
 if (obj.style.filter){
  obj.style.filter = "alpha(opacity=" + opacity + ")";
  }
 else if (obj.style.opacity){
  obj.style.opacity = opacity/100;
  }
 else if (obj.style.MozOpacity){
  obj.style.MozOpacity = opacity/100;
  }
 }

//Converts date (day,month,year) to day of week (0 Sunday - 6 Saturday).
//Day and month start at 1.
function dayofweek(day, month, year){
 var monthoffset = new Array(0,3,2,5,0,3,5,1,4,6,2,4);
 day = parseInt(day);
 month = parseInt(month);
 year = parseInt(year);
 if(isNaN(day) || day > 31  || day < 1 ) return "ERR";
 if(isNaN(month) || month > 12  || month < 1 ) return "ERR";
 if(isNaN(year) || year>9999 || year < 1 ) return "ERR";
 if(month == 1) year--;
 if(month == 2) year--;
 return ((day+monthoffset[month-1]+year+(Math.floor(year/4))-(Math.floor(year/100))+(Math.floor(year/400)))%7);
 }

//Returns number of days in the month.
function daysinmonth(month, year) {
 var m = [31,28,31,30,31,30,31,31,30,31,30,31];
 if (month != 2) return m[month - 1];
 if (year%4 != 0) return m[1];
 if (year%100 == 0 && year%400 != 0) return m[1];
 return m[1] + 1;
} 

//Returns month name.
function monthname(month){
 var monthnames = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");
 return monthnames[month - 1];
 }

//Returns day name.
function dayname(day){
 var daynames = new Array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday");
 return daynames[day];
 }

//Draws calendar for given month and year (default is current month).
function drawcal(month, year){
 var i, obj;
 var today = new Date();
 if (!year){
  month = today.getMonth() + 1;
  year = today.getFullYear();
  }
 var firstday = dayofweek(1, month, year);
 var monthdays = daysinmonth(month, year);
 var startday = 0;
 var ym = today.getFullYear() * 12 + today.getMonth() + 1;
 if (ym >= year * 12 + month){
  startday = today.getDate() - 1;
  } 
 getItem("caltop").innerHTML = monthname(month) + " " + year;
 for (i=0; i<firstday+startday; i++){
  obj = getItem("cal" + i);
  obj.innerHTML = "&nbsp;";
  obj.style.cursor = "auto";
  obj.onmouseover = new Function();
  obj.onmouseout = new Function();
  obj.onclick = new Function();
  }
 for (i=firstday+startday; i<(firstday+monthdays); i++){
  obj = getItem("cal" + i);
  var day = i - firstday + 1;
  obj.innerHTML = day;
  obj.style.cursor = "pointer";
  obj.onmouseover = new Function("getItem('cal" + i + "').style.color = '#505E5F'");
  obj.onmouseout = new Function("getItem('cal" + i + "').style.color = 'white'");
  obj.onclick = new Function("optionDate(" + day + "," + month + "," + year + ")");
  }
 for (i=(firstday+monthdays); i<42; i++){
  obj = getItem("cal" + i);
  obj.innerHTML = "&nbsp;";
  obj.style.cursor = "auto";
  obj.onmouseover = new Function();
  obj.onmouseout = new Function();
  obj.onclick = new Function();
  }
 var month2 = month + 1;
 var year2 = year;
 if (month2 > 12){
  month2 = 1
  year2 = year + 1
  }
 getItem("calright").onclick = new Function("drawcal(" + month2 + "," + year2 + ")");
 getItem("calright").style.cursor = "pointer";
 month2 = month - 1;
 year2 = year;
 if (month2 < 1){
  month2 = 12
  year2 = year - 1
  }
 if (ym >= year * 12 + month){
  getItem("calleft").onclick = new Function();
  getItem("calleft").style.cursor = "auto";
  getItem("calleft").innerHTML = "&nbsp;";
  }
 else{
  getItem("calleft").onclick = new Function("drawcal(" + month2 + "," + year2 + ")");
  getItem("calleft").style.cursor = "pointer";
  getItem("calleft").innerHTML = "&lt;";
  }
 }

//Sets up and maintains date dropdowns.
function optionDate(day, month, year){
 var maxdays, firstmonth, firstday, curday, curmonth, curyear, i;
 if (day){
  curday = day;
  }
 else{
  curday = parseInt(getItem("day").value);
  }
 if (month){
  curmonth = month;
  }
 else{
  curmonth = parseInt(getItem("month").value);
  }
 if (year){
  curyear = year;
  }
 else{
  curyear = parseInt(getItem("year").value);
  }
 var today = new Date();
 if (curyear == 0 || curyear > today.getFullYear()){
  firstmonth = 1;
  firstday = 1;
  }
 else if (curmonth == 0 || curmonth > today.getMonth() + 1){
  firstmonth = today.getMonth() + 1;
  firstday = 1;
  }
 else{
  firstmonth = today.getMonth() + 1;
  firstday = today.getDate();
  }
 if (curmonth == 0 || curyear == 0){
  maxdays = 31;
  }
 else{
  maxdays = daysinmonth(curmonth, curyear);
  }
 getItem("year").options.length=0;
 getItem("year").options[0] = new Option(" ", 0);
 for (i=1; i<=5; i++){
  var year = today.getFullYear() + i - 1;
  getItem("year").options[i] = new Option(year, year);
  }
 if (curyear >= today.getFullYear()){
  getItem("year").selectedIndex = curyear - today.getFullYear() + 1;
  }
 getItem("month").options.length=0;
 getItem("month").options[0] = new Option(" ", 0);
 for (i=firstmonth; i<=12; i++){
  getItem("month").options[i - firstmonth + 1] = new Option(monthname(i), i);
  }
 if (curmonth >= firstmonth){
  getItem("month").selectedIndex = curmonth - firstmonth + 1;
  }
 getItem("day").options.length=0;
 getItem("day").options[0] = new Option(" ", 0);
 for (i=firstday; i<=maxdays; i++){
  getItem("day").options[i - firstday + 1] = new Option(i, i);
  }
 if (curday >= firstday && curday <= maxdays){
  getItem("day").selectedIndex = curday - firstday + 1;
  }
 getItem("caldiv").style.display = "none";
 clearRate();
 }

//Makes AJAX request; readyfn(httpRequest) is called when response received.
//rqtype is GET or POST; params (URI encoded) are for POST.
function makeRequest(url, readyfn, rqtype, params) {
 var httpRequest;
 if (!params) var params = null;
 if (window.XMLHttpRequest) { // Mozilla, Safari, ...
  httpRequest = new XMLHttpRequest();
  if (httpRequest.overrideMimeType) {
   httpRequest.overrideMimeType('text/xml');
   }
  } 
 else if (window.ActiveXObject) { // IE
  try {
   httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
   } 
  catch (e) {
   try {
    httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
    } 
   catch (e) {}
   }
  }
 if (!httpRequest) {
  alert('Cannot create request');
  return false;
  }
 httpRequest.onreadystatechange = function() {
  try {
   if (httpRequest.readyState == 4) {
    if (httpRequest.status == 200) {
     if(readyfn) readyfn(httpRequest);
     }
    else {
     alert('There was a problem with the request: ' + httpRequest.status);
     }
    }
   }
  catch(e) {
   alert('Error in response to request: ' + e.message);
   }
  };
 var now = "uid=" + new Date().getTime(); //IE prevent cache
 url += (url.indexOf("?")+1) ? "&" : "?";
 url += now;
 try {
  httpRequest.open(rqtype, url, true);
  if (rqtype == "POST"){
   httpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
   httpRequest.setRequestHeader("Content-length", params.length);
   httpRequest.setRequestHeader("Connection", "close");
   }
  httpRequest.send(params);
  }
 catch (e) {
  alert('Error opening request: ' + e.message);
  }
 }

//Handles request for rate and submits AJAX request.
function getRate(){
 var curday = parseInt(getItem("day").value);
 var curmonth = parseInt(getItem("month").value);
 var curyear = parseInt(getItem("year").value);
 var nights = parseInt(getItem("nights").value);
 if (curday == 0 || curmonth == 0 || curyear == 0 || isNaN(nights) || nights <= 0){
  getItem("arrival").innerHTML = "Please specify date &amp; nights";
  }
 else{
  var depday = curday + nights;
  var depmonth = curmonth;
  var depyear = curyear;
  while (depday > daysinmonth(depmonth, depyear)){
   depday = depday - daysinmonth(depmonth, depyear);
   depmonth++;
   if (depmonth > 12){
    depmonth = 1;
    depyear++;
    }
   }
  getItem("arrival").innerHTML = dayname(dayofweek(curday, curmonth, curyear)) + " " + curday + " " + monthname(curmonth) + " " + curyear;
  getItem("departure").innerHTML = dayname(dayofweek(depday, depmonth, depyear)) + " " + depday + " " + monthname(depmonth) + " " + depyear;
  getItem("price").innerHTML = "Please wait...";
  makeRequest("cgi-bin/getprice.cgi?day=" + curday + "&month=" + curmonth + "&year=" + curyear, alertContents, "GET");
  }
 }

//Handles AJAX response from rate request.
function alertContents(httpRequest) {
 var resulttext = httpRequest.responseText;
 resulttext = resulttext.replace(/%([0-9A-F][0-9A-F])/g, "&#x$1;");
 getItem("price").innerHTML = resulttext;
 }

//Clears rate fields on data change.
function clearRate(){
 getItem("arrival").innerHTML = "";
 getItem("departure").innerHTML = "";
 getItem("price").innerHTML = "";
 }

//Displays calendar if opt is true, else hides it.
function dispcal(opt, e){
 if (!e) var e = window.event;
 if (opt){
  getItem("caldiv").style.display = "block";
  e.cancelBubble = true;
  if (e.stopPropagation) e.stopPropagation();
  }
 else{
  var srcEl = e.srcElement ? e.srcElement : e.target
  if (srcEl.className != "calendar"){
   getItem("caldiv").style.display = "none";
   }
  }
 }

//Hides calendar on mouse out of calendar itself.
function leavecal(e){
 if (!e) var e = window.event;
 var toEl = e.toElement ? e.toElement : e.relatedTarget
 if (toEl.className != "calendar"){
  getItem("caldiv").style.display = "none";
  }
 }

//Handles submission of form via AJAX reqest.
function fmsubmit(){
 var paramtext = "";
 for (var i=0; i<getItem("enqform").elements.length; i++){
  if(getItem("enqform").elements[i].name){
   if (paramtext.length > 0) paramtext += "&";
   paramtext += getItem("enqform").elements[i].name + "=" + encodeURIComponent(getItem("enqform").elements[i].value);
   }
  }
 getItem("aftersubmit").innerHTML = "Please wait...";
 makeRequest("cgi-bin/submitform.cgi", alertform, 'POST', paramtext)
 getItem("btsubmit").disabled = "disabled";
 }

//Handles AJAX response from submission of form.
function alertform(httpRequest){
 getItem("aftersubmit").innerHTML = "&nbsp;";
 var resulttext = httpRequest.responseText;
 alert(decodeURIComponent(resulttext));
 getItem("btsubmit").disabled = "";
 }

// Google map functions.
// Display the map, with some controls and set the initial location 
function createMap(mapid, lat, lng, scale) {

// Check to see if this browser can run the Google API
 if (GBrowserIsCompatible()) {
  this.map = new GMap2(document.getElementById(mapid));
  this.map.addControl(new GLargeMapControl());
//this.map.addControl(new GMapTypeControl()); //map/satellite/composite
  this.map.setCenter(new GLatLng(lat, lng), scale);
  this.obj = mapid;
  this.gmarkers = [];
  this.htmls = [];
  this.to_htmls = [];
  this.from_htmls = [];
  }

// display a warning if the browser was not compatible
 else {
  alert("Sorry, Google Maps are not compatible with this browser");
  }
 }

// A function to create the marker and set up the event window
createMap.prototype.createMarker = function(name, html, lat, lng) {
 if (!this.map) return;
 var Icon = new GIcon();
 Icon.image = "http://www.google.com/mapfiles/gadget/arrowSmall80.png";
 Icon.shadow = "http://www.google.com/mapfiles/gadget/arrowshadowSmall80.png";;
 Icon.iconSize = new GSize(31, 27);
 Icon.shadowSize = new GSize(31, 27);
 Icon.iconAnchor = new GPoint(8, 27);
 Icon.infoWindowAnchor = new GPoint(5, 1);
 var point = new GLatLng(lat, lng);
 var marker = new GMarker(point, Icon);
 var i = this.gmarkers.length;

// The info window version with the "to here" form open
 this.to_htmls[i] = '<form action="http://maps.google.com/maps" method="get" onsubmit="' + this.obj + '.fmsubmit(this); return false;">' + html 
  + '<br/>Directions: <b>To here</b> - <a href="" onclick="' + this.obj + '.fromhere(' + i + '); return false;">From here</a>' +
  '<br/>Start address:<br/>' +
  '<input type="text" size="30" maxlength="50" name="saddr" id="saddr" value="" /><br/>' +
  '<input value="Get Directions" type="submit"/>' +
  '<input type="hidden" name="daddr" value="' + point.lat() + ',' + point.lng() + ' (' + name + ')"/>' +
  '</form>';

// The info window version with the "from here" form open
 this.from_htmls[i] = '<form action="http://maps.google.com/maps" method="get" onsubmit="' + this.obj + '.fmsubmit(this); return false;">' + html
  + '<br/>Directions: <a href="" onclick="' + this.obj + '.tohere(' + i + '); return false;">To here</a> - <b>From here</b>' +
  '<br/>End address:<br/>' +
  '<input type="text" size="30" maxlength="50" name="daddr" id="daddr" value="" /><br/>' +
  '<input value="Get Directions" type="submit"/>' +
  '<input type="hidden" name="saddr" value="' + point.lat() + ',' + point.lng() + " (" + name + ')"/>' +
  '</form>';

// The inactive version of the direction info
 html = html + '<br/>Directions: <a href="" onclick="' + this.obj + '.tohere(' + i + '); return false;">To here</a>' +
  ' - <a href="" onclick="' + this.obj + '.fromhere(' + i + '); return false;">From here</a>';

 GEvent.addListener(marker, "click", function() {
  marker.openInfoWindowHtml(html);
  });
 this.gmarkers[i] = marker;
 this.htmls[i] = html;
 this.map.addOverlay(marker);
 }

// Functions that open the directions forms.
createMap.prototype.tohere = function(i) {
 this.gmarkers[i].openInfoWindowHtml(this.to_htmls[i]);
 }
createMap.prototype.fromhere = function(i) {
 this.gmarkers[i].openInfoWindowHtml(this.from_htmls[i]);
 }

// Submit form avoiding use of target=_blank.
createMap.prototype.fmsubmit = function(obj) {
 var paramtext = "";
 for (var i=0; i<obj.elements.length; i++) {
  if (obj.elements[i].name) {
   paramtext += paramtext ? "&" : "?";
   paramtext += obj.elements[i].name + "=" + encodeURIComponent(obj.elements[i].value);
   }
  }
 window.open(obj.action + paramtext);
 }
// This Javascript is based on code provided by the
// Blackpool Community Church Javascript Team
// http://www.commchurch.freeserve.co.uk/   
// http://econym.googlepages.com/index.htm

//This sets the overall page length to the longer of the two columns.
//Needs to run as onload in compatibility view or else fails.
function setheights(){
 getItem("container").style.height = ((getItem("leftside").offsetHeight > getItem("rightside").offsetHeight) ? getItem("leftside").offsetHeight : 
 getItem("rightside").offsetHeight) + "px";
 }



